change version to 1.2.2.0
[platform/framework/native/net.git] / src / FNet_WifiSystemNetConnection.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  * @file                        FNet_WifiSystemNetConnection.cpp
19  * @brief               This is the implementation file for _WifiSystemNetConnection class.
20  * @version     3.0
21  *
22  * This file contains the implementation of _WifiSystemNetConnection class.
23  */
24
25 #include <net_connection.h>
26 #include <wifi.h>
27 #include <FNetNetConnectionInfo.h>
28 #include <FBaseRtMutexGuard.h>
29 #include <FBaseSysLog.h>
30 #include <FSysSettingInfo.h>
31 #include <FBase_StringConverter.h>
32 #include <FApp_AppManagerImpl.h>
33 #include "FNet_NetTypes.h"
34 #include "FNet_NetConnectionInfoImpl.h"
35 #include "FNet_WifiSystemNetConnection.h"
36 #include "FNet_NetAccountDatabase.h"
37 #include "FNet_NetAccountManagerImpl.h"
38 #include "FNet_NetConnectionEvent.h"
39 #include "FNet_NetConnectionEventArg.h"
40
41 using namespace std;
42 using namespace Tizen::App;
43 using namespace Tizen::Base;
44 using namespace Tizen::Base::Collection;
45 using namespace Tizen::Base::Runtime;
46 using namespace Tizen::System;
47
48 namespace Tizen { namespace Net {
49
50 static const char* _WIFI_QS_APP_ID = "net.wifi-qs";
51
52 void
53 WifiConnectionTypeChangedCallback(connection_type_e type, void* pUserData)
54 {
55         _WifiSystemNetConnection* pConnection = static_cast<_WifiSystemNetConnection*>(pUserData);
56
57         int ret = CONNECTION_ERROR_NONE;
58         connection_h connectionHandle = pConnection->GetConnectionHandle();
59         connection_profile_h profileHandle = null;
60         connection_wifi_state_e state = CONNECTION_WIFI_STATE_DEACTIVATED;
61
62         SysLog(NID_NET, "WifiConnectionTypeChangedCallback() has been called with type:%d", type);
63
64         ret = connection_get_wifi_state(connectionHandle, &state);
65         SysTryReturnVoidResult(NID_NET, ret == CONNECTION_ERROR_NONE, E_SYSTEM,
66                         "[%s] A system error has been called. The return value from connection_get_wifi_state() is %d", ret);
67
68         if (state == CONNECTION_WIFI_STATE_CONNECTED)
69         {
70                 profileHandle = _NetAccountManagerImpl::GetWifiProfileHandleN();
71                 SysTryReturnVoidResult(NID_NET, profileHandle != null,
72                                 E_SYSTEM, "WIFI profileHandle is not found.");
73
74                 SysLog(NID_NET, "Wifi is connected.");
75
76                 if (pConnection->GetConnectionState() == NET_CONNECTION_STATE_STARTING)
77                 {
78                         pConnection->HandleStartResponse(E_SUCCESS, profileHandle);
79                 }
80                 else
81                 {
82                         pConnection->HandleStartEvent();
83                         pConnection->UpdateConnectionInfo(profileHandle);
84                 }
85
86                 connection_profile_destroy(profileHandle);
87         }
88         else
89         {
90                 SysLog(NID_NET, "Wifi is not connected.");
91
92                 if (pConnection->GetConnectionState() == NET_CONNECTION_STATE_STARTING)
93                 {
94                         bool isWifiQsRunning = false;
95
96                         isWifiQsRunning = _AppManagerImpl::GetInstance()->IsRunning(String(_WIFI_QS_APP_ID));
97
98                         if (isWifiQsRunning)
99                         {
100                                 SysLog(NID_NET, "Ignore disconnected event on the starting state because Wi-Fi QuickStart is running.");
101                         }
102                         else
103                         {
104                                 SysLog(NID_NET, "Failed to connect Wifi.");
105                                 pConnection->HandleStartResponse(E_NETWORK_FAILED, null);
106                         }
107                 }
108                 else
109                 {
110                         pConnection->HandleStopEvent(E_NETWORK_FAILED);
111                         pConnection->UpdateConnectionInfo(null);
112                 }
113         }
114 }
115
116 void
117 WifiActivatedCallback(wifi_error_e res, void* pUserData)
118 {
119         _WifiSystemNetConnection* pConnection = static_cast<_WifiSystemNetConnection*>(pUserData);
120
121         SysLog(NID_NET, "Enter with res[%d].", res);
122
123         if (res != WIFI_ERROR_NONE)
124         {
125                 SysLogException(NID_NET, E_NETWORK_FAILED, "[E_NETWORK_FAILED] Failed to activate Wi-Fi.");
126                 pConnection->HandleStartResponse(E_NETWORK_FAILED, null);
127         }
128
129         SysLog(NID_NET, "Exit.");
130 }
131
132 _WifiSystemNetConnection::_WifiSystemNetConnection(void)
133         : __pConnectionHandle(null)
134         , __pTimer(null)
135 {
136 }
137
138 _WifiSystemNetConnection::~_WifiSystemNetConnection(void)
139 {
140 }
141
142 result
143 _WifiSystemNetConnection::Construct(void)
144 {
145         result r = E_SUCCESS;
146         unique_ptr<void, _ConnectionDeleter> pConnectionHandle;
147         unique_ptr<Timer> pTimer;
148
149         int ret = CONNECTION_ERROR_NONE;
150         connection_h connectionHandle = null;
151         connection_profile_h profileHandle = null;
152         connection_wifi_state_e state = CONNECTION_WIFI_STATE_DEACTIVATED;
153
154         SysAssertf(__pConnectionHandle == null,
155                         "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class.");
156
157         pTimer.reset(new (std::nothrow) Timer());
158         SysTryReturnResult(NID_NET, pTimer != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
159
160         r = pTimer->Construct(*this);
161         SysTryReturnResult(NID_NET, r == E_SUCCESS, r, "Propagating.");
162
163         r = _SystemNetConnection::Initialize(L"WIFI");
164         SysTryReturnResult(NID_NET, r == E_SUCCESS, r, "Propagating.");
165
166         ret = wifi_initialize();
167         SysTryCatch(NID_NET, ((ret == WIFI_ERROR_NONE) || (ret == WIFI_ERROR_INVALID_OPERATION)),
168                         r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] wifi_initialize() failed with ret=[%d]", ret);
169
170         ret = connection_create(&connectionHandle);
171         SysTryCatch(NID_NET, ret == CONNECTION_ERROR_NONE, r = E_SYSTEM, E_SYSTEM,
172                         "[%s] A system error has been occurred. The return value from connection_create() is %d", GetErrorMessage(E_SYSTEM), ret);
173         pConnectionHandle.reset(connectionHandle);
174
175         ret = connection_set_type_changed_cb(connectionHandle, WifiConnectionTypeChangedCallback, this);
176         SysTryCatch(NID_NET, ret == CONNECTION_ERROR_NONE, r = E_SYSTEM, E_SYSTEM,
177                         "[%s] A system error has been occurred. The return value from connection_set_type_changed_cb() is %d", ret);
178
179         ret = connection_get_wifi_state(connectionHandle, &state);
180         SysTryCatch(NID_NET, ret == CONNECTION_ERROR_NONE, r = E_SYSTEM, E_SYSTEM,
181                         "[%s] A system error has been occurred. The return value from connection_get_wifi_state() is %d", ret);
182
183         if (state == CONNECTION_WIFI_STATE_CONNECTED)
184         {
185                 profileHandle = _NetAccountManagerImpl::GetWifiProfileHandleN();
186                 if (profileHandle != null)
187                 {
188                         SysLog(NID_NET, "Wifi is connected.");
189                         UpdateConnectionInfo(profileHandle);
190                         connection_profile_destroy(profileHandle);
191                 }
192                 else
193                 {
194                         SysLog(NID_NET, "Wifi state is connected, but profileHandle is not found.");
195                         UpdateConnectionInfo(null);
196                 }
197         }
198         else
199         {
200                 SysLog(NID_NET, "Wifi is not connected.");
201                 UpdateConnectionInfo(null);
202         }
203
204         __pConnectionHandle = move(pConnectionHandle);
205         __pTimer = move(pTimer);
206
207         return r;
208
209 CATCH:
210         _SystemNetConnection::Deinitialize();
211
212         return r;
213 }
214
215 result
216 _WifiSystemNetConnection::Start(_NetConnectionEvent& event)
217 {
218         SysLog(NID_NET, "Starting WIFI connection.");
219
220         result r = E_SUCCESS;
221
222         SysAssertf(_pEventList != null, "Not yet constructed. Construct() should be called before use.");
223
224         MutexGuard locked(*_pLock);
225
226         if (_connectionState == NET_CONNECTION_STATE_STARTED)
227         {
228                 // Already Started
229                 SysLog(NID_NET, "WIFI connection is already started.");
230
231                 if (event.GetConnectionState() != NET_CONNECTION_STATE_STARTED)
232                 {
233                         unique_ptr<_NetConnectionEventArg> pEventArg(new (std::nothrow) _NetConnectionEventArg(_NET_CONNECTION_EVENT_TYPE_STARTED, E_SUCCESS));
234                         SysTryReturnResult(NID_NET, pEventArg != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
235
236                         event.SetConnectionState(NET_CONNECTION_STATE_STARTED);
237                         r = event.FireAsync(*pEventArg);
238                         SysTryReturnResult(NID_NET, r == E_SUCCESS, r, "Propagating.");
239
240                         _refCount++;
241                         pEventArg.release();
242                 }
243         }
244         else if ((_connectionState == NET_CONNECTION_STATE_STARTING) || (_connectionState == NET_CONNECTION_STATE_STOPPING))
245         {
246                 // Waiting Response
247                 SysLog(NID_NET, "WIFI connection is waiting response.");
248
249                 if (event.GetConnectionState() != NET_CONNECTION_STATE_STARTING)
250                 {
251                         event.SetConnectionState(NET_CONNECTION_STATE_STARTING);
252                         _refCount++;
253                 }
254         }
255         else
256         {
257                 // None or Stopped
258                 SysLog(NID_NET, "WIFI connection is not active.");
259
260                 SysTryReturnResult(NID_NET, !event.IsManagedSystemConnection(), E_INVALID_CONNECTION, "Wi-Fi activation is not allowed for a managed network connection.");
261
262                 int ret = WIFI_ERROR_NONE;
263                 bool isActivated = false;
264
265                 ret = wifi_is_activated(&isActivated);
266                 SysTryReturnResult(NID_NET, ret == WIFI_ERROR_NONE, E_SYSTEM, "wifi_is_activated() failed with ret=[%d].", ret);
267                 SysTryReturnResult(NID_NET, !isActivated, E_INVALID_CONNECTION, "Wi-Fi is already activated, so can't start it.");
268
269             bool isFlightModeEnabled = false;
270             r = SettingInfo::GetValue(L"http://tizen.org/setting/network.flight_mode", isFlightModeEnabled);
271                 SysTryReturnResult(NID_NET, r == E_SUCCESS && !isFlightModeEnabled, E_INVALID_CONNECTION, "Flight mode is enabled.");
272
273                 r = _AppManagerImpl::GetInstance()->AddAppEventListener(*this);
274                 SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM, "Failed to set application event listener.");
275
276                 ret = wifi_activate(WifiActivatedCallback, this);
277                 if (ret != WIFI_ERROR_NONE)
278                 {
279                         SysLogException(NID_NET, E_SYSTEM, "[E_SYSTEM] wifi_activate() failed with ret=[%d].", ret);
280
281                         _AppManagerImpl::GetInstance()->RemoveAppEventListener(*this);
282
283                         return E_SYSTEM;
284                 }
285
286                 _connectionState = NET_CONNECTION_STATE_STARTING;
287                 event.SetConnectionState(NET_CONNECTION_STATE_STARTING);
288                 _refCount++;
289         }
290
291         locked.Unlock();
292
293         SysLog(NID_NET, "Exit with result[%s].", GetErrorMessage(r));
294
295         return r;
296 }
297
298 void
299 _WifiSystemNetConnection::HandleStartResponse(result error, void* pData)
300 {
301         SysLog(NID_NET, "Start response is received with result[%s].", GetErrorMessage(error));
302
303         IEnumerator* pEnum = null;
304         _NetConnectionEvent* pEvent = null;
305         _NetConnectionEventArg* pStartEventArg = null;
306
307         if (_connectionState != NET_CONNECTION_STATE_STARTING)
308         {
309                 SysLog(NID_NET, "Ignore _WifiSystemNetConnection::HandleStartResponse() because this is NOT in starting state.");
310                 return;
311         }
312
313         _AppManagerImpl::GetInstance()->RemoveAppEventListener(*this);
314
315         MutexGuard locked(*_pLock);
316
317         if (error == E_SUCCESS)
318         {
319                 _bearerType = NET_BEARER_WIFI;
320                 _connectionState = NET_CONNECTION_STATE_STARTED;
321                 _pConnectionInfo->Update(pData);
322         }
323         else
324         {
325                 _bearerType = NET_BEARER_NONE;
326                 _connectionState = NET_CONNECTION_STATE_STOPPED;
327                 _pConnectionInfo->Clear();
328                 _refCount = 0;
329         }
330
331         pEnum = _pEventList->GetEnumeratorN();
332         if (pEnum != null)
333         {
334                 while (pEnum->MoveNext() == E_SUCCESS)
335                 {
336                         pEvent = dynamic_cast<_NetConnectionEvent*>(pEnum->GetCurrent());
337                         if (pEvent != null)
338                         {
339                                 if (pEvent->GetConnectionState() == NET_CONNECTION_STATE_STARTING)
340                                 {
341                                         if (error == E_SUCCESS)
342                                         {
343                                                 pEvent->SetConnectionState(NET_CONNECTION_STATE_STARTED);
344                                         }
345                                         else
346                                         {
347                                                 pEvent->SetConnectionState(NET_CONNECTION_STATE_STOPPED);
348                                         }
349
350                                         pStartEventArg = new (std::nothrow) _NetConnectionEventArg(_NET_CONNECTION_EVENT_TYPE_STARTED, error);
351                                         if (pStartEventArg != null)
352                                         {
353                                                 pEvent->FireAsync(*pStartEventArg);
354                                         }
355                                 }
356                         }
357                 }
358
359                 delete pEnum;
360         }
361
362         locked.Unlock();
363
364         SysLog(NID_NET, "Exit.");
365 }
366
367 void
368 _WifiSystemNetConnection::OnApplicationLaunched(const AppId& appId, int pid)
369 {
370         SysLog(NID_NET, "App is launched. appid[%ls] pid[%d].", appId.GetPointer(), pid);
371 }
372
373 void
374 _WifiSystemNetConnection::OnApplicationTerminated(const AppId& appId, int pid)
375 {
376         SysLog(NID_NET, "App is terminated. appid[%ls] pid[%d].", appId.GetPointer(), pid);
377
378         if (appId.Equals(String(_WIFI_QS_APP_ID), false))
379         {
380                 SysLog(NID_NET, "Wi-Fi QuickStart is terminated before Wi-Fi is connected.");
381                 __pTimer->Start(1);
382
383                 // ToDo - Remove timer and call HandleStartResponse here (After lockup issue is resolved.)
384 //              HandleStartResponse(E_NETWORK_FAILED, null);
385         }
386 }
387
388 void
389 _WifiSystemNetConnection::OnTimerExpired(Timer& timer)
390 {
391         SysLog(NID_NET, "Timer is expired, so treat as an error.");
392
393         HandleStartResponse(E_NETWORK_FAILED, null);
394 }
395
396 void
397 _WifiSystemNetConnection::UpdateConnectionInfo(void* pData)
398 {
399         MutexGuard locked(*_pLock);
400
401         if (pData != null)
402         {
403                 _bearerType = NET_BEARER_WIFI;
404                 _connectionState = NET_CONNECTION_STATE_STARTED;
405                 _pConnectionInfo->Update(pData);
406
407         }
408         else
409         {
410                 _bearerType = NET_BEARER_NONE;
411                 _connectionState = NET_CONNECTION_STATE_STOPPED;
412                 _pConnectionInfo->Clear();
413         }
414
415         locked.Unlock();
416 }
417
418 void*
419 _WifiSystemNetConnection::GetConnectionHandle(void) const
420 {
421         return __pConnectionHandle.get();
422 }
423
424 } } // Tizen::Net