Apply vconf key value for background scanning
[platform/framework/native/connectivity-service.git] / src / WifiService.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file    WifiService.cpp
20  * @brief   This is the implementation file for the %WifiService class.
21  */
22
23 #include <glib.h>
24 #include <vconf.h>
25 #include <vconf-keys.h>
26 #include <wifi-direct.h>
27 #include <unique_ptr.h>
28 #include <FBaseUtilStringUtil.h>
29 #include <FBaseRtMutexGuard.h>
30 #include <FBaseSysLog.h>
31 #include <FNetIp4Address.h>
32 #include <FNetWifiWifiTypes.h>
33 #include <FNetWifiWifiBssInfo.h>
34 #include <FSys_SystemInfoImpl.h>
35 #include <FBase_StringConverter.h>
36 #include <FNetWifi_WifiBssInfoImpl.h>
37 #include <FNetWifi_WifiUtility.h>
38 #include "WifiService.h"
39
40 using namespace std;
41 using namespace Tizen::Base;
42 using namespace Tizen::Base::Utility;
43 using namespace Tizen::Base::Runtime;
44 using namespace Tizen::Base::Collection;
45 using namespace Tizen::App;
46 using namespace Tizen::System;
47 using namespace Tizen::Net;
48 using namespace Tizen::Net::Wifi;
49
50 static void WifiDirectDeviceStateChangedCallbackFunction(int error_code, wifi_direct_device_state_e device_state,
51                                                                                                                         void* user_data);
52
53 struct _WifiBssIdHandlePair
54 {
55         const Tizen::Base::String* pBssId;
56         wifi_ap_h apHandle;
57 };
58
59 WifiService::WifiService(void)
60         : __newWifiDirectName()
61         , __wifiDirectNameChangerId()
62         , __listMutex()
63         , __appPkgIdList()
64 {
65 }
66
67 WifiService::~WifiService(void)
68 {
69         if (__appPkgIdList.GetCount() > 0)
70         {
71             (void) wifi_direct_unset_device_state_changed_cb();
72             (void) wifi_direct_deinitialize();
73         }
74 }
75
76 result
77 WifiService::Construct(void)
78 {
79         result r = E_SUCCESS;
80         bool isWifiDirectSupported = false;
81     String key(L"http://tizen.org/feature/network.wifi.direct");
82
83         r = Tizen::System::_SystemInfoImpl::GetSysInfo(key, isWifiDirectSupported);
84         SysTryReturnResult(NID_NET_WIFI, (r == E_SUCCESS) && (isWifiDirectSupported == true), E_UNSUPPORTED_OPERATION,
85                         "Wi-Fi Direct is not supported.");
86
87         r = __listMutex.Create();
88         SysTryReturnResult(NID_NET_WIFI, r == E_SUCCESS, E_SYSTEM, "Failed to create a mutex.");
89
90         return E_SUCCESS;
91 }
92
93 result
94 WifiService::SetWifiSystemScanMode(int mode)
95 {
96         // changes vconf value about Wi-Fi BG scan mode.
97         // Key:   VCONFKEY_WIFI_BGSCAN_MODE                "memory/wifi/bgscan_mode"
98         // Value: VCONFKEY_WIFI_BGSCAN_MODE_PERIODIC
99         //        VCONFKEY_WIFI_BGSCAN_MODE_EXPONENTIAL
100
101         // changes vconf value about Wi-Fi UG running mode.
102         // Key:   VCONFKEY_WIFI_UG_RUN_STATE                "memory/wifi/ug_run_state"
103         // Value: VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND - auto connect pop-up for selecting the AP is not displayed.
104         //        VCONFKEY_WIFI_UG_RUN_STATE_OFF
105
106         int vconfRes = 0;
107         int bgScanMode = VCONFKEY_WIFI_BGSCAN_MODE_EXPONENTIAL;
108         int ugRunState = VCONFKEY_WIFI_UG_RUN_STATE_OFF;
109         WifiSystemScanMode scanMode = (WifiSystemScanMode) mode;
110
111         switch(scanMode)
112         {
113         case WIFI_SYSTEM_SCAN_MODE_ACTIVE:
114                 bgScanMode = VCONFKEY_WIFI_BGSCAN_MODE_PERIODIC;
115                 ugRunState = VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND;
116                 SysLog(NID_NET_WIFI, "Change UG state (ON_FOREGROUND)");
117                 SysLog(NID_NET_WIFI, "Change BG scan mode (VCONFKEY_WIFI_BGSCAN_MODE_PERIODIC)");
118                 break;
119         case WIFI_SYSTEM_SCAN_MODE_PASSIVE:
120         default:
121                 ugRunState = VCONFKEY_WIFI_UG_RUN_STATE_OFF;
122                 bgScanMode = VCONFKEY_WIFI_BGSCAN_MODE_EXPONENTIAL;
123                 SysLog(NID_NET_WIFI, "Change UG state (OFF)");
124                 SysLog(NID_NET_WIFI, "Change BG scan mode (VCONFKEY_WIFI_BGSCAN_MODE_EXPONENTIAL)");
125                 break;
126         }
127
128         vconfRes = vconf_set_int(VCONFKEY_WIFI_UG_RUN_STATE, ugRunState);
129         SysTryReturnResult(NID_NET_WIFI, vconfRes == 0, E_OPERATION_FAILED, "Setting the running mode of the Wi-Fi UG has failed.");
130
131         vconfRes = vconf_set_int(VCONFKEY_WIFI_BGSCAN_MODE, bgScanMode);
132         SysTryReturnResult(NID_NET_WIFI, vconfRes == 0, E_OPERATION_FAILED, "Setting the BG scanning mode of the Wi-Fi has failed.[%d]"
133         , vconfRes);
134
135
136         return E_SUCCESS;
137 }
138
139 result
140 WifiService::UpdateWifiBssInfo(const Tizen::Net::Wifi::WifiBssInfo& bssInfo)
141 {
142         wifi_ap_h apHandle = null;
143         const _WifiBssInfoImpl* pBssInfoImpl = null;
144         int apRes = WIFI_ERROR_NONE;
145         NetAddressScheme ipScheme = NET_ADDRESS_SCHEME_DYNAMIC;
146         wifi_ip_config_type_e apIpScheme = WIFI_IP_CONFIG_TYPE_NONE;
147         const IpAddress* pAddress = null;
148         unique_ptr<char[]> pAddressStr;
149         NetProxyType proxyType = NET_PROXY_TYPE_NONE;
150         wifi_proxy_type_e apProxyType = WIFI_PROXY_TYPE_DIRECT;
151         String proxyAddressStr;
152         bool isKnown = false;
153
154         pBssInfoImpl = _WifiBssInfoImpl::GetInstance(bssInfo);
155         apHandle = GetApHandle(pBssInfoImpl->GetBssId());
156         SysTryReturnResult(NID_NET_WIFI, apHandle != null, E_OPERATION_FAILED,
157                         "The AP is not found in the current AP list of the system.");
158
159         // Setting the AP unknown
160         apRes = wifi_ap_is_favorite(apHandle, &isKnown);
161         SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
162                         "Checking the AP is a known device has failed. [0x%08X].", apRes);
163         if (isKnown && !(pBssInfoImpl->IsKnown()))
164         {
165                 apRes = wifi_forget_ap(apHandle);
166                 SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
167                                 "Setting the AP unknown has failed. [0x%08X].", apRes);
168         }
169
170         // Setting the IP address scheme. Only IPv4 as the address family is taken into consideration for now.
171         ipScheme = pBssInfoImpl->GetLocalAddressScheme();
172         apIpScheme = (ipScheme == NET_ADDRESS_SCHEME_STATIC) ? WIFI_IP_CONFIG_TYPE_STATIC : WIFI_IP_CONFIG_TYPE_DYNAMIC;
173         apRes = wifi_ap_set_ip_config_type(apHandle, WIFI_ADDRESS_FAMILY_IPV4, apIpScheme);
174         SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
175                         "Setting the IP address scheme to AP has failed. [0x%08X].", apRes);
176
177         if (ipScheme == NET_ADDRESS_SCHEME_STATIC)
178         {
179                 // Setting the IP address. Only IPv4 as the address family is taken into consideration for now.
180                 pAddress = pBssInfoImpl->GetLocalAddress();
181                 if (pAddress != null)
182                 {
183                         pAddressStr.reset(_StringConverter::CopyToCharArrayN(pAddress->ToString()));
184                         apRes = wifi_ap_set_ip_address(apHandle, WIFI_ADDRESS_FAMILY_IPV4, pAddressStr.get());
185                         SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
186                                         "Setting the IP address to AP has failed. [0x%08X].", apRes);
187                 }
188
189                 // Setting the subnet mask. Only IPv4 as the address family is taken into consideration for now.
190                 pAddress = pBssInfoImpl->GetSubnetMaskAddress();
191                 if (pAddress != null)
192                 {
193                         pAddressStr.reset(_StringConverter::CopyToCharArrayN(pAddress->ToString()));
194                         apRes = wifi_ap_set_subnet_mask(apHandle, WIFI_ADDRESS_FAMILY_IPV4, pAddressStr.get());
195                         SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
196                                         "Setting the subnet mask to AP has failed. [0x%08X].", apRes);
197                 }
198
199                 // Setting the default gateway address. Only IPv4 as the address family is taken into consideration for now.
200                 pAddress = pBssInfoImpl->GetDefaultGatewayAddress();
201                 if (pAddress != null)
202                 {
203                         pAddressStr.reset(_StringConverter::CopyToCharArrayN(pAddress->ToString()));
204                         apRes = wifi_ap_set_gateway_address(apHandle, WIFI_ADDRESS_FAMILY_IPV4, pAddressStr.get());
205                         SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
206                                         "Setting the default gateway address to AP has failed. [0x%08X].", apRes);
207                 }
208
209                 // Setting the primary DNS address. Only IPv4 as the address family is taken into consideration for now.
210                 pAddress = pBssInfoImpl->GetPrimaryDnsAddress();
211                 if (pAddress != null)
212                 {
213                         pAddressStr.reset(_StringConverter::CopyToCharArrayN(pAddress->ToString()));
214                         apRes = wifi_ap_set_dns_address(apHandle, 1, WIFI_ADDRESS_FAMILY_IPV4, pAddressStr.get());
215                         SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
216                                         "Setting the primary DNS address to AP has failed. [0x%08X].", apRes);
217                 }
218
219                 // Setting the secondary DNS address. Only IPv4 as the address family is taken into consideration for now.
220                 pAddress = pBssInfoImpl->GetSecondaryDnsAddress();
221                 if (pAddress != null)
222                 {
223                         pAddressStr.reset(_StringConverter::CopyToCharArrayN(pAddress->ToString()));
224                         apRes = wifi_ap_set_dns_address(apHandle, 2, WIFI_ADDRESS_FAMILY_IPV4, pAddressStr.get());
225                         SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
226                                         "Setting the secondary DNS address to AP has failed. [0x%08X].", apRes);
227                 }
228         }
229
230         proxyType = pBssInfoImpl->GetProxyType();
231
232         if (proxyType == NET_PROXY_TYPE_MANUAL)
233         {
234                 // Setting the proxy address. Only IPv4 as the address family is taken into consideration for now.
235                 proxyAddressStr = pBssInfoImpl->GetProxyAddress();
236                 pAddressStr.reset(_StringConverter::CopyToCharArrayN(proxyAddressStr));
237                 apRes = wifi_ap_set_proxy_address(apHandle, WIFI_ADDRESS_FAMILY_IPV4, pAddressStr.get());
238                 SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
239                                 "Setting the proxy address to AP has failed. [0x%08X].", apRes);
240         }
241
242         // Setting the proxy type.
243         apProxyType = (proxyType == NET_PROXY_TYPE_MANUAL) ? WIFI_PROXY_TYPE_MANUAL : WIFI_PROXY_TYPE_DIRECT;
244         apRes = wifi_ap_set_proxy_type(apHandle, apProxyType);
245         SysTryReturnResult(NID_NET_WIFI, apRes == WIFI_ERROR_NONE, E_OPERATION_FAILED,
246                         "Setting the proxy type to AP has failed. [0x%08X].", apRes);
247
248         return E_SUCCESS;
249 }
250
251 result
252 WifiService::Initialize(const Tizen::Base::String& clientPkgId)
253 {
254         result r = E_SUCCESS;
255     int ret = WIFI_DIRECT_ERROR_NONE;
256
257         MutexGuard locked(__listMutex);
258
259         // Initialize Wi-Fi Direct client of osp-connectivity-service
260         // if the first application initializes its Wi-Fi Direct client.
261         if (__appPkgIdList.GetCount() == 0)
262         {
263             ret = wifi_direct_initialize();
264             SysTryReturnResult(NID_NET_WIFI, ret == WIFI_DIRECT_ERROR_NONE, E_SYSTEM,
265                                 "Initializing Wi-Fi Direct has failed. [0x%08X]", ret);
266
267                 ret = wifi_direct_set_device_state_changed_cb(WifiDirectDeviceStateChangedCallbackFunction, this);
268                 if (ret != WIFI_DIRECT_ERROR_NONE)
269                 {
270                         SysLogException(NID_NET_WIFI, E_SYSTEM,
271                                 "[E_SYSTEM] Registration of a Wi-Fi Direct callback method has failed. [0x%08X]", ret);
272                     (void) wifi_direct_deinitialize();
273                         return E_SYSTEM;
274                 }
275
276                 SysLog(NID_NET_WIFI, "Initializing Wi-Fi Direct is successful.");
277         }
278
279         // Add the ID of the application which initializes Wi-Fi Direct client to the list.
280         if (!__appPkgIdList.Contains(clientPkgId))
281         {
282                 r = __appPkgIdList.Add(clientPkgId);
283                 // Ignore the error result of list operation.
284                 SysTryLog(NID_NET_WIFI, r == E_SUCCESS, "Insertion a new item to the app ID list has failed. (%s)", GetErrorMessage(r));
285         }
286
287         locked.Unlock();
288
289         return r;
290 }
291
292 result
293 WifiService::GetWifiDirectLocalDeviceName(Tizen::Base::String* pLocalName)
294 {
295         result r = E_SYSTEM;
296         int ret = WIFI_DIRECT_ERROR_NONE;
297
298         // Gets the local name from the underlying Wi-Fi Direct subsystem, if Wi-Fi Direct is on.
299         if (IsWifiDirectActivated() == true)
300         {
301             char* pDeviceName = null;
302                 ret = wifi_direct_get_device_name(&pDeviceName);
303                 SysTryReturnResult(NID_NET_WIFI, ret == WIFI_DIRECT_ERROR_NONE && pDeviceName != null, E_SYSTEM,
304                                 "Getting the SSID from Wi-Fi Direct subsystem has failed. [0x%x]", ret);
305
306                 // Converts the UTF8 multibyte string to Unicode String
307                 r = StringUtil::Utf8ToString(pDeviceName, *pLocalName);
308                 free(pDeviceName);
309         }
310         // Gets the name to be set, if Wi-Fi Direct is off and there is the name set by an application
311         else if (__newWifiDirectName.GetLength() > 0)
312         {
313                 *pLocalName = __newWifiDirectName;
314                 r = E_SUCCESS;
315         }
316         // Gets the phone name from the system info
317         else
318         {
319             char* pPhoneName = null;
320                 pPhoneName = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
321                 SysTryReturnResult(NID_NET_WIFI, pPhoneName != null, E_SYSTEM, "Getting the phone name has failed");
322
323                 // Converts the UTF8 multibyte string to Unicode String
324                 r = StringUtil::Utf8ToString(pPhoneName, *pLocalName);
325                 free(pPhoneName);
326         }
327
328         return r;
329 }
330
331 result
332 WifiService::SetWifiDirectLocalDeviceName(const Tizen::Base::String& clientPkgId, const Tizen::Base::String& localName)
333 {
334         result r = E_SUCCESS;
335
336         // Updates the local name instantly if the Wi-Fi Direct is turned on.
337         // Saves the setting name for the later use, otherwise.
338         if (IsWifiDirectActivated() == true)
339         {
340                 r = UpdateWifiDirectLocalDeviceName(localName);
341                 if (!IsFailed(r))
342                 {
343                         __newWifiDirectName = localName;
344                         __wifiDirectNameChangerId = clientPkgId;
345                 }
346         }
347         else
348         {
349                 __newWifiDirectName = localName;
350                 __wifiDirectNameChangerId = clientPkgId;
351                 SysLog(NID_NET_WIFI, "The input name is reserved as the Wi-Fi Direct local name.");
352         }
353
354         return r;
355 }
356
357 result
358 WifiService::UpdateWifiDirectLocalDeviceName(const Tizen::Base::String& name)
359 {
360         int ret = 0;
361         char* pConvertedName = NULL;
362
363         pConvertedName = _StringConverter::CopyToCharArrayN(name);
364         SysTryReturnResult(NID_NET_WIFI, pConvertedName != null, E_INVALID_ARG, "Invalid device name.");
365
366         ret = wifi_direct_set_device_name(pConvertedName);
367
368         delete[] pConvertedName;
369         SysTryReturnResult(NID_NET_WIFI, ret == WIFI_DIRECT_ERROR_NONE, E_SYSTEM,
370                                                 "Setting the Wi-Fi Direct SSID (local name) has failed. [0x%x]", ret);
371
372         SysLog(NID_NET_WIFI, "Updating the Wi-Fi Direct local name is successful.");
373
374         return E_SUCCESS;
375 }
376
377 bool
378 WifiService::IsWifiDirectActivated(void) const
379 {
380         int ret = WIFI_DIRECT_ERROR_NONE;
381         wifi_direct_state_e currentState = WIFI_DIRECT_STATE_DEACTIVATED;
382
383         ret = wifi_direct_get_state(&currentState);
384         if (ret == WIFI_DIRECT_ERROR_NONE)
385         {
386                 if (currentState != WIFI_DIRECT_STATE_DEACTIVATED)
387                 {
388                         return true;
389                 }
390         }
391         else
392         {
393                 SysLog(NID_NET_WIFI, "Getting the current status of Wi-Fi Direct has failed. [0x%x]", ret);
394         }
395
396         return false;
397 }
398
399 wifi_ap_h
400 WifiService::GetApHandle(const Tizen::Base::String& bssId)
401 {
402         _WifiBssIdHandlePair pair;
403         pair.pBssId = &bssId;
404         pair.apHandle = null;
405
406     wifi_foreach_found_aps(OnWifiEachAccessPointFound, &pair);
407
408     return pair.apHandle;
409 }
410
411 void
412 WifiService::ProcessAppTermination(const Tizen::Base::String& clientPkgId)
413 {
414         char* pPhoneName = null;
415         String convertedName;
416         result r = E_SUCCESS;
417
418         if (__wifiDirectNameChangerId == clientPkgId)
419         {
420                 SysLog(NID_NET_WIFI, "The application which set the Wi-Fi Direct local name is terminated.");
421
422                 if (IsWifiDirectActivated() == true)
423                 {
424                         SysLog(NID_NET_WIFI, "The Wi-Fi Direct SSID is restored to the phone name.");
425
426                         // Gets the phone name from the system info
427                         pPhoneName = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
428                         if (pPhoneName)
429                         {
430                                 r = StringUtil::Utf8ToString(pPhoneName, convertedName);
431                                 free(pPhoneName);
432
433                                 if (!IsFailed(r))
434                                 {
435                                         // Updates the Wi-Fi Direct local name with the phone name
436                                         (void) UpdateWifiDirectLocalDeviceName(convertedName);
437                                 }
438                         }
439                 }
440
441                 __newWifiDirectName.Clear();
442                 __wifiDirectNameChangerId.Clear();
443         }
444
445         // Deinitialize Wi-Fi Direct client if the last application which initialized Wi-Fi Direct is terminated.
446         __listMutex.Acquire();
447
448         if (__appPkgIdList.Contains(clientPkgId))
449         {
450                 r = __appPkgIdList.Remove(clientPkgId);
451
452                 if ((r == E_SUCCESS) && (__appPkgIdList.GetCount() == 0))
453                 {
454                     (void) wifi_direct_unset_device_state_changed_cb();
455                     (void) wifi_direct_deinitialize();
456                         SysLog(NID_NET_WIFI, "Deinitializing Wi-Fi Direct is successful.");
457                 }
458         }
459
460         __listMutex.Release();
461 }
462
463 void
464 WifiService::OnWifiDirectActivated(void)
465 {
466         // Updates the local Wi-Fi Direct name.
467         // This is a reserved action.
468         if (__newWifiDirectName.GetLength() > 0)
469         {
470                 (void) UpdateWifiDirectLocalDeviceName(__newWifiDirectName);
471         }
472 }
473
474 bool
475 WifiService::OnWifiEachAccessPointFound(wifi_ap_h apHandle, void* pUserData)
476 {
477         int res = WIFI_ERROR_NONE;
478         char* bssId = null;
479         _WifiBssIdHandlePair* pPair = static_cast<_WifiBssIdHandlePair*>(pUserData);
480
481     res = wifi_ap_get_bssid (apHandle, &bssId);
482     SysTryReturn(NID_NET_WIFI, res == WIFI_ERROR_NONE && bssId != null, true, E_OPERATION_FAILED,
483                 "[E_OPERATION_FAILED] Getting BSSID has failed.");
484
485     if (pPair->pBssId->Equals(String(_WifiUtility::ConvertMacAddress(bssId))))
486     {
487         pPair->apHandle = apHandle;
488         return false;
489     }
490
491     return true;
492 }
493
494 void
495 WifiDirectDeviceStateChangedCallbackFunction(int error_code, wifi_direct_device_state_e device_state, void* user_data)
496 {
497         WifiService* pService = (WifiService*)user_data;
498
499         switch (device_state)
500         {
501         case WIFI_DIRECT_DEVICE_STATE_ACTIVATED:
502                 // if the Wi-Fi Direct is activated successfully
503                 if (error_code == WIFI_DIRECT_ERROR_NONE)
504                 {
505                         SysLog(NID_NET_WIFI, "An event received from SLP Wi-Fi Direct FW (type: WIFI_DIRECT_DEVICE_STATE_ACTIVATED)");
506                         pService->OnWifiDirectActivated();
507                 }
508                 break;
509
510         default:
511                 break;       // ignore other types of event
512         }
513 }
514