Tethering: Do not show device picker UI when turning on Wi-Fi tethering
[platform/core/connectivity/net-config.git] / src / utils / util.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 <unistd.h>
21 #include <string.h>
22 #include <sys/wait.h>
23 #include <sys/stat.h>
24 #include <vconf.h>
25 #include <vconf-keys.h>
26 #include <wifi-direct.h>
27 #include <syspopup_caller.h>
28 #include <aul.h>
29
30 #include "log.h"
31 #include "util.h"
32 #include "neterror.h"
33 #include "wifi-state.h"
34
35 #define WIFI_MAC_INFO_FILE      "/opt/etc/.mac.info"
36 #define WIFI_MAC_INFO_LENGTH    17
37
38 GKeyFile *netconfig_keyfile_load(const char *pathname)
39 {
40         GKeyFile *keyfile = NULL;
41         GError *error = NULL;
42
43         keyfile = g_key_file_new();
44         if (g_key_file_load_from_file(keyfile, pathname, 0, &error) != TRUE) {
45                 DBG("Unable to open %s, error %s", pathname, error->message);
46                 g_error_free(error);
47
48                 g_key_file_free(keyfile);
49                 keyfile = NULL;
50         }
51
52         return keyfile;
53 }
54
55 void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname)
56 {
57         gsize size = 0;
58         GError *error = NULL;
59         gchar *keydata = NULL;
60         gchar *needle = NULL, *directory = NULL;
61
62         directory = g_strdup(pathname);
63         needle = g_strrstr(directory, "/");
64
65         if (needle != NULL)
66                 *needle = '\0';
67
68         if (directory == NULL || (*directory) == '\0') {
69                 g_free(directory);
70                 return;
71         }
72
73         if (g_file_test(directory, G_FILE_TEST_IS_DIR) != TRUE) {
74                 if (g_mkdir_with_parents(directory,
75                                 S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
76                         g_free(directory);
77                         return;
78                 }
79         }
80         g_free(directory);
81
82         keydata = g_key_file_to_data(keyfile, &size, &error);
83         if (g_file_set_contents(pathname, keydata, size, &error) != TRUE) {
84                 DBG("Unable to save %s, error %s", pathname, error->message);
85                 g_error_free(error);
86         }
87
88         if (chmod(pathname, S_IRUSR | S_IWUSR) != 0)
89                 DBG("Unable to change permission of %s", pathname);
90
91         g_free(keydata);
92
93         g_key_file_free(keyfile);
94 }
95
96 void netconfig_start_timer_seconds(guint secs,
97                 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
98 {
99         guint t_id = 0;
100
101         if (callback == NULL) {
102                 ERR("callback function is NULL");
103                 return;
104         }
105
106         if ((timer_id != NULL && *timer_id != 0)) {
107                 ERR("timer already is registered");
108                 return;
109         }
110
111         t_id = g_timeout_add_seconds(secs, callback, user_data);
112
113         if (t_id == 0) {
114                 ERR("Can't add timer");
115                 return;
116         }
117
118         if (timer_id != NULL)
119                 *timer_id = t_id;
120 }
121
122 void netconfig_start_timer(guint msecs,
123                 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
124 {
125         guint t_id = 0;
126
127         INFO("Register timer with callback pointer (%p)", callback);
128
129         if (callback == NULL) {
130                 ERR("callback function is NULL");
131                 return;
132         }
133
134         if ((timer_id != NULL && *timer_id != 0)) {
135                 ERR("timer already is registered");
136                 return;
137         }
138
139         t_id = g_timeout_add(msecs, callback, user_data);
140
141         if (t_id == 0) {
142                 ERR("Can't add timer");
143                 return;
144         }
145
146         if (timer_id != NULL)
147                 *timer_id = t_id;
148 }
149
150 void netconfig_stop_timer(guint *timer_id)
151 {
152         if (timer_id == NULL) {
153                 ERR("timer is NULL");
154                 return;
155         }
156
157         if (*timer_id != 0) {
158                 g_source_remove(*timer_id);
159                 *timer_id = 0;
160         }
161 }
162
163 static gboolean __netconfig_test_device_picker()
164 {
165         char *favorite_wifi_service = NULL;
166
167         favorite_wifi_service = netconfig_wifi_get_favorite_service();
168         if (favorite_wifi_service != NULL) {
169                 g_free(favorite_wifi_service);
170                 return FALSE;
171         }
172
173         return TRUE;
174 }
175
176 static void __netconfig_pop_device_picker(void)
177 {
178         int rv = 0;
179         bundle *b = NULL;
180         int wifi_ug_state = 0;
181
182         vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
183         if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
184                 return;
185
186         b = bundle_create();
187
188         DBG("Launch Wi-Fi device picker");
189         rv = syspopup_launch("wifi-qs", b);
190
191         bundle_free(b);
192 }
193
194 static gboolean __netconfig_wifi_try_device_picker(gpointer data)
195 {
196         if (__netconfig_test_device_picker() == TRUE)
197                 __netconfig_pop_device_picker();
198
199         return FALSE;
200 }
201
202 static guint __netconfig_wifi_device_picker_timer_id(gboolean is_set_method,
203                 guint timer_id)
204 {
205         static guint netconfig_wifi_device_picker_service_timer = 0;
206
207         if (is_set_method != TRUE)
208                 return netconfig_wifi_device_picker_service_timer;
209
210         if (netconfig_wifi_device_picker_service_timer != timer_id)
211                 netconfig_wifi_device_picker_service_timer = timer_id;
212
213         return netconfig_wifi_device_picker_service_timer;
214 }
215
216 static void __netconfig_wifi_device_picker_set_timer_id(guint timer_id)
217 {
218         __netconfig_wifi_device_picker_timer_id(TRUE, timer_id);
219 }
220
221 static guint __netconfig_wifi_device_picker_get_timer_id(void)
222 {
223         return __netconfig_wifi_device_picker_timer_id(FALSE, -1);
224 }
225
226 void netconfig_wifi_device_picker_service_start(void)
227 {
228         int wifi_ug_state;
229         const int NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL = 700;
230         int hotspot_wifi_state = VCONFKEY_MOBILE_HOTSPOT_WIFI_OFF;
231         guint timer_id = 0;
232
233         vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
234         if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
235                 return;
236
237         /* If Wi-Fi tethering is pending on, don't show device picker UI*/
238         vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_WIFI_STATE, &hotspot_wifi_state);
239         if (hotspot_wifi_state == VCONFKEY_MOBILE_HOTSPOT_WIFI_PENDING_ON) {
240                 DBG("hotspot_wifi_state %d", hotspot_wifi_state);
241                 return;
242         }
243
244         DBG("Register device picker timer with %d milliseconds",
245                         NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL);
246
247         netconfig_start_timer(NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL,
248                         __netconfig_wifi_try_device_picker, NULL, &timer_id);
249
250         __netconfig_wifi_device_picker_set_timer_id(timer_id);
251 }
252
253 void netconfig_wifi_device_picker_service_stop(void)
254 {
255         guint timer_id = 0;
256
257         timer_id = __netconfig_wifi_device_picker_get_timer_id();
258         if (timer_id == 0)
259                 return;
260
261         DBG("Clear device picker timer with timer_id %d", timer_id);
262
263         netconfig_stop_timer(&timer_id);
264
265         __netconfig_wifi_device_picker_set_timer_id(timer_id);
266 }
267
268 gboolean netconfig_is_wifi_direct_on(void)
269 {
270         int wifi_direct_state = 0;
271
272         vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state);
273
274         DBG("Wi-Fi direct mode %d", wifi_direct_state);
275         return (wifi_direct_state != 0) ? TRUE : FALSE;
276 }
277
278 gboolean netconfig_is_wifi_tethering_on(void)
279 {
280         int wifi_tethering_state = 0;
281
282         vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &wifi_tethering_state);
283
284         DBG("Wi-Ti tethering mode %d", wifi_tethering_state);
285         if (wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI)
286                 return TRUE;
287
288         return FALSE;
289 }
290
291 /* args[] and env[] should be terminated with NULL pointer */
292 gboolean netconfig_execute_file(const char *file_path,
293                 char *const args[], char *const env[])
294 {
295         pid_t pid = 0;
296         int rv = 0;
297         errno = 0;
298
299         if (!(pid = fork())) {
300                 register unsigned int index = 0;
301                 INFO("pid(%d), ppid (%d)", getpid(), getppid());
302                 INFO("Inside child, exec (%s) command", file_path);
303
304                 index = 0;
305                 while (args[index] != NULL) {
306                         INFO(" %s", args[index]);
307                         index++;
308                 }
309
310                 errno = 0;
311                 if (execve(file_path, args, env) == -1) {
312                         DBG("Fail to execute command...(%s)",
313                                         strerror(errno));
314                         return FALSE;
315                 }
316         } else if (pid > 0) {
317                 if (waitpid(pid, &rv, 0) == -1) {
318                         DBG("wait pid (%u) rv (%d)", pid, rv);
319
320                         if (WIFEXITED(rv)) {
321                                 DBG("exited, rv=%d", WEXITSTATUS(rv));
322                         } else if (WIFSIGNALED(rv)) {
323                                 DBG("killed by signal %d", WTERMSIG(rv));
324                         } else if (WIFSTOPPED(rv)) {
325                                 DBG("stopped by signal %d", WSTOPSIG(rv));
326                         } else if (WIFCONTINUED(rv)) {
327                                 DBG("continued");
328                         }
329                 }
330                 return TRUE;
331         }
332
333         DBG("failed to fork()...(%s)", strerror(errno));
334         return FALSE;
335 }
336
337 gboolean netconfig_iface_wifi_launch_direct(NetconfigWifi *wifi, GError **error)
338 {
339         gboolean ret = TRUE;
340
341         DBG("Launch Wi-Fi direct daemon");
342
343         const char *path = "/usr/bin/wifi-direct-server.sh";
344         char *const args[] = { "wifi-direct-server.sh", "start", NULL};
345         char *const env[] = { NULL };
346
347         ret = netconfig_execute_file(path, args, env);
348
349         if (ret != TRUE) {
350                 INFO("Failed to launch Wi-Fi direct daemon");
351
352                 netconfig_error_wifi_direct_failed(error);
353         }
354
355         return ret;
356 }
357
358 void netconfig_add_wifi_found_notification(void)
359 {
360         int ret;
361         bundle *b = bundle_create();
362
363         bundle_add(b, "_SYSPOPUP_TYPE_", "add_found_ap_noti");
364
365         ret = aul_launch_app("org.tizen.net-popup", b);
366
367         bundle_free(b);
368
369         if (ret >= 0)
370                 DBG("Successfully added notification");
371         else
372                 ERR("Unable to launch noti-popup. Err = %d", ret);
373 }
374
375 void netconfig_del_wifi_found_notification(void)
376 {
377         int ret;
378         bundle *b = bundle_create();
379
380         bundle_add(b, "_SYSPOPUP_TYPE_", "del_found_ap_noti");
381
382         ret = aul_launch_app("org.tizen.net-popup", b);
383
384         bundle_free(b);
385
386         if (ret >= 0)
387                 DBG("Successfully deleted notification");
388         else
389                 ERR("Unable to launch noti-popup. Err = %d", ret);
390 }
391
392
393 void netconfig_set_wifi_mac_address(void)
394 {
395         FILE *fp;
396         char buf[WIFI_MAC_INFO_LENGTH + 1];
397         char *mac_info;
398
399         mac_info = vconf_get_str(VCONFKEY_WIFI_BSSID_ADDRESS);
400         if (mac_info == NULL) {
401                 ERR("Failed to open vconf key %s", VCONFKEY_WIFI_BSSID_ADDRESS);
402                 return;
403         }
404
405         INFO("%s : %s", VCONFKEY_WIFI_BSSID_ADDRESS, mac_info);
406
407         fp = fopen(WIFI_MAC_INFO_FILE, "r");
408         if (fp == NULL) {
409                 ERR("Failed to open file %s", WIFI_MAC_INFO_FILE);
410                 g_free(mac_info);
411                 return;
412         }
413
414         if (fgets(buf, sizeof(buf), fp) == NULL) {
415                 ERR("Failed to get MAC info from %s", WIFI_MAC_INFO_FILE);
416                 goto done;
417         }
418
419         INFO("%s : %s", WIFI_MAC_INFO_FILE, buf);
420
421         if (strlen(buf) < WIFI_MAC_INFO_LENGTH) {
422                 ERR("Failed to get MAC info from %s", WIFI_MAC_INFO_FILE);
423                 goto done;
424         }
425
426         buf[WIFI_MAC_INFO_LENGTH] = '\0';
427
428         if (g_str_equal(mac_info, buf) == TRUE)
429                 goto done;
430
431         if (vconf_set_str(VCONFKEY_WIFI_BSSID_ADDRESS, buf) != 0)
432                 ERR("Failed to set MAC info to %s", VCONFKEY_WIFI_BSSID_ADDRESS);
433
434 done:
435         g_free(mac_info);
436         fclose(fp);
437 }