2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file WifiService.cpp
20 * @brief This is the implementation file for the %WifiService class.
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"
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;
50 static void WifiDirectDeviceStateChangedCallbackFunction(int error_code, wifi_direct_device_state_e device_state,
53 struct _WifiBssIdHandlePair
55 const Tizen::Base::String* pBssId;
59 WifiService::WifiService(void)
60 : __newWifiDirectName()
61 , __wifiDirectNameChangerId()
67 WifiService::~WifiService(void)
69 if (__appPkgIdList.GetCount() > 0)
71 (void) wifi_direct_unset_device_state_changed_cb();
72 (void) wifi_direct_deinitialize();
77 WifiService::Construct(void)
80 bool isWifiDirectSupported = false;
81 String key(L"http://tizen.org/feature/network.wifi.direct");
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.");
87 r = __listMutex.Create();
88 SysTryReturnResult(NID_NET_WIFI, r == E_SUCCESS, E_SYSTEM, "Failed to create a mutex.");
94 WifiService::SetWifiSystemScanMode(int mode)
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
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
107 int bgScanMode = VCONFKEY_WIFI_BGSCAN_MODE_EXPONENTIAL;
108 int ugRunState = VCONFKEY_WIFI_UG_RUN_STATE_OFF;
109 WifiSystemScanMode scanMode = (WifiSystemScanMode) mode;
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)");
119 case WIFI_SYSTEM_SCAN_MODE_PASSIVE:
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)");
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.");
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]"
140 WifiService::UpdateWifiBssInfo(const Tizen::Net::Wifi::WifiBssInfo& bssInfo)
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;
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.");
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()))
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);
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);
177 if (ipScheme == NET_ADDRESS_SCHEME_STATIC)
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)
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);
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)
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);
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)
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);
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)
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);
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)
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);
230 proxyType = pBssInfoImpl->GetProxyType();
232 if (proxyType == NET_PROXY_TYPE_MANUAL)
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);
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);
252 WifiService::Initialize(const Tizen::Base::String& clientPkgId)
254 result r = E_SUCCESS;
255 int ret = WIFI_DIRECT_ERROR_NONE;
257 MutexGuard locked(__listMutex);
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)
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);
267 ret = wifi_direct_set_device_state_changed_cb(WifiDirectDeviceStateChangedCallbackFunction, this);
268 if (ret != WIFI_DIRECT_ERROR_NONE)
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();
276 SysLog(NID_NET_WIFI, "Initializing Wi-Fi Direct is successful.");
279 // Add the ID of the application which initializes Wi-Fi Direct client to the list.
280 if (!__appPkgIdList.Contains(clientPkgId))
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));
293 WifiService::GetWifiDirectLocalDeviceName(Tizen::Base::String* pLocalName)
296 int ret = WIFI_DIRECT_ERROR_NONE;
298 // Gets the local name from the underlying Wi-Fi Direct subsystem, if Wi-Fi Direct is on.
299 if (IsWifiDirectActivated() == true)
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);
306 // Converts the UTF8 multibyte string to Unicode String
307 r = StringUtil::Utf8ToString(pDeviceName, *pLocalName);
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)
313 *pLocalName = __newWifiDirectName;
316 // Gets the phone name from the system info
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");
323 // Converts the UTF8 multibyte string to Unicode String
324 r = StringUtil::Utf8ToString(pPhoneName, *pLocalName);
332 WifiService::SetWifiDirectLocalDeviceName(const Tizen::Base::String& clientPkgId, const Tizen::Base::String& localName)
334 result r = E_SUCCESS;
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)
340 r = UpdateWifiDirectLocalDeviceName(localName);
343 __newWifiDirectName = localName;
344 __wifiDirectNameChangerId = clientPkgId;
349 __newWifiDirectName = localName;
350 __wifiDirectNameChangerId = clientPkgId;
351 SysLog(NID_NET_WIFI, "The input name is reserved as the Wi-Fi Direct local name.");
358 WifiService::UpdateWifiDirectLocalDeviceName(const Tizen::Base::String& name)
361 char* pConvertedName = NULL;
363 pConvertedName = _StringConverter::CopyToCharArrayN(name);
364 SysTryReturnResult(NID_NET_WIFI, pConvertedName != null, E_INVALID_ARG, "Invalid device name.");
366 ret = wifi_direct_set_device_name(pConvertedName);
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);
372 SysLog(NID_NET_WIFI, "Updating the Wi-Fi Direct local name is successful.");
378 WifiService::IsWifiDirectActivated(void) const
380 int ret = WIFI_DIRECT_ERROR_NONE;
381 wifi_direct_state_e currentState = WIFI_DIRECT_STATE_DEACTIVATED;
383 ret = wifi_direct_get_state(¤tState);
384 if (ret == WIFI_DIRECT_ERROR_NONE)
386 if (currentState != WIFI_DIRECT_STATE_DEACTIVATED)
393 SysLog(NID_NET_WIFI, "Getting the current status of Wi-Fi Direct has failed. [0x%x]", ret);
400 WifiService::GetApHandle(const Tizen::Base::String& bssId)
402 _WifiBssIdHandlePair pair;
403 pair.pBssId = &bssId;
404 pair.apHandle = null;
406 wifi_foreach_found_aps(OnWifiEachAccessPointFound, &pair);
408 return pair.apHandle;
412 WifiService::ProcessAppTermination(const Tizen::Base::String& clientPkgId)
414 char* pPhoneName = null;
415 String convertedName;
416 result r = E_SUCCESS;
418 if (__wifiDirectNameChangerId == clientPkgId)
420 SysLog(NID_NET_WIFI, "The application which set the Wi-Fi Direct local name is terminated.");
422 if (IsWifiDirectActivated() == true)
424 SysLog(NID_NET_WIFI, "The Wi-Fi Direct SSID is restored to the phone name.");
426 // Gets the phone name from the system info
427 pPhoneName = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
430 r = StringUtil::Utf8ToString(pPhoneName, convertedName);
435 // Updates the Wi-Fi Direct local name with the phone name
436 (void) UpdateWifiDirectLocalDeviceName(convertedName);
441 __newWifiDirectName.Clear();
442 __wifiDirectNameChangerId.Clear();
445 // Deinitialize Wi-Fi Direct client if the last application which initialized Wi-Fi Direct is terminated.
446 __listMutex.Acquire();
448 if (__appPkgIdList.Contains(clientPkgId))
450 r = __appPkgIdList.Remove(clientPkgId);
452 if ((r == E_SUCCESS) && (__appPkgIdList.GetCount() == 0))
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.");
460 __listMutex.Release();
464 WifiService::OnWifiDirectActivated(void)
466 // Updates the local Wi-Fi Direct name.
467 // This is a reserved action.
468 if (__newWifiDirectName.GetLength() > 0)
470 (void) UpdateWifiDirectLocalDeviceName(__newWifiDirectName);
475 WifiService::OnWifiEachAccessPointFound(wifi_ap_h apHandle, void* pUserData)
477 int res = WIFI_ERROR_NONE;
479 _WifiBssIdHandlePair* pPair = static_cast<_WifiBssIdHandlePair*>(pUserData);
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.");
485 if (pPair->pBssId->Equals(String(_WifiUtility::ConvertMacAddress(bssId))))
487 pPair->apHandle = apHandle;
495 WifiDirectDeviceStateChangedCallbackFunction(int error_code, wifi_direct_device_state_e device_state, void* user_data)
497 WifiService* pService = (WifiService*)user_data;
499 switch (device_state)
501 case WIFI_DIRECT_DEVICE_STATE_ACTIVATED:
502 // if the Wi-Fi Direct is activated successfully
503 if (error_code == WIFI_DIRECT_ERROR_NONE)
505 SysLog(NID_NET_WIFI, "An event received from SLP Wi-Fi Direct FW (type: WIFI_DIRECT_DEVICE_STATE_ACTIVATED)");
506 pService->OnWifiDirectActivated();
511 break; // ignore other types of event