[WiFi] Fixes for design issues reported in confluence
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.WiFi / Tizen.Network.WiFi / WiFiManagerImpl.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Threading;
20 using System.Threading.Tasks;
21
22 namespace Tizen.Network.WiFi
23 {
24     static internal class Globals
25     {
26         internal const string LogTag = "Tizen.Network.WiFi";
27     }
28
29     internal class HandleHolder : IDisposable
30     {
31         private IntPtr _handle = IntPtr.Zero;
32         private bool disposed = false;
33
34         internal HandleHolder()
35         {
36             Log.Debug(Globals.LogTag, "HandleHolder() Constructor");
37             _handle = WiFiManagerImpl.Instance.Initialize();
38             Log.Debug(Globals.LogTag, "Handle: " + _handle);
39         }
40
41         ~HandleHolder()
42         {
43             Dispose(false);
44         }
45
46         internal IntPtr GetHandle()
47         {
48             Log.Debug(Globals.LogTag, "Handleholder handle = " + _handle);
49             return _handle;
50         }
51         public void Dispose()
52         {
53             Dispose(true);
54             GC.SuppressFinalize(this);
55         }
56
57         private void Dispose(bool disposing)
58         {
59             Log.Debug(Globals.LogTag, ">>> HandleHolder Dispose with " + disposing);
60             Log.Debug(Globals.LogTag, ">>> Handle: " + _handle);
61             if (disposed)
62                 return;
63
64             if (disposing)
65             {
66                 // Free managed objects.
67                 WiFiManagerImpl.Instance.Deinitialize(_handle);
68             }
69             disposed = true;
70         }
71     }
72
73     internal partial class WiFiManagerImpl : IDisposable
74     {
75         private static WiFiManagerImpl _instance = null;
76         private Dictionary<IntPtr, Interop.WiFi.VoidCallback> _callback_map = new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
77         private int _requestId = 0;
78         private string _macAddress;
79         private bool disposed = false;
80
81         internal string MacAddress
82         {
83             get
84             {
85                 if (String.IsNullOrEmpty(_macAddress))
86                 {
87                     string address;
88                     int ret = Interop.WiFi.GetMacAddress(GetHandle(), out address);
89                     if (ret != (int)WiFiError.None)
90                     {
91                         Log.Error(Globals.LogTag, "Failed to get mac address, Error - " + (WiFiError)ret);
92                         _macAddress = "";
93                     }
94                     else
95                     {
96                         _macAddress = address;
97                     }
98                 }
99                 return _macAddress;
100             }
101         }
102
103         internal string InterfaceName
104         {
105             get
106             {
107                 string name;
108                 int ret = Interop.WiFi.GetNetworkInterfaceName(GetHandle(), out name);
109                 if (ret != (int)WiFiError.None)
110                 {
111                     Log.Error(Globals.LogTag, "Failed to get interface name, Error - " + (WiFiError)ret);
112                     return "";
113                 }
114                 return name;
115             }
116         }
117
118         internal WiFiConnectionState ConnectionState
119         {
120             get
121             {
122                 int state;
123                 int ret = Interop.WiFi.GetConnectionState(GetHandle(), out state);
124                 if (ret != (int)WiFiError.None)
125                 {
126                     Log.Error(Globals.LogTag, "Failed to get connection state, Error - " + (WiFiError)ret);
127                     return WiFiConnectionState.Failure;
128                 }
129                 return (WiFiConnectionState)state;
130             }
131         }
132
133         internal bool IsActive
134         {
135             get
136             {
137                 bool active;
138                 int ret = Interop.WiFi.IsActive(GetHandle(), out active);
139                 if (ret != (int)WiFiError.None)
140                 {
141                     Log.Error(Globals.LogTag, "Failed to get isActive, Error - " + (WiFiError)ret);
142                 }
143                 return active;
144             }
145         }
146
147         internal static WiFiManagerImpl Instance
148         {
149             get
150             {
151                 Log.Debug(Globals.LogTag, "Instance getter");
152                 if (_instance == null)
153                 {
154                     Log.Debug(Globals.LogTag, "Instance is null");
155                     _instance = new WiFiManagerImpl();
156                 }
157
158                 return _instance;
159             }
160         }
161
162         private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
163         {
164             Log.Info(Globals.LogTag, "In threadlocal delegate");
165             return new HandleHolder();
166         });
167
168         private WiFiManagerImpl()
169         {
170         }
171
172         ~WiFiManagerImpl()
173         {
174             Dispose(false);
175         }
176
177         public void Dispose()
178         {
179             Dispose(true);
180             GC.SuppressFinalize(this);
181         }
182
183         private void Dispose(bool disposing)
184         {
185             if (disposed)
186                 return;
187
188             if (disposing)
189             {
190                 // Free managed objects.
191             }
192             //Free unmanaged objects
193             RemoveAllRegisteredEvent();
194             disposed = true;
195         }
196
197         internal IntPtr GetHandle()
198         {
199             Log.Debug(Globals.LogTag, "GetHandle, Thread Id = " + Thread.CurrentThread.ManagedThreadId);
200             return s_threadName.Value.GetHandle();
201         }
202
203         internal IntPtr Initialize()
204         {
205             IntPtr handle;
206             int ret = Interop.WiFi.Initialize(out handle);
207             if (ret != (int)WiFiError.None)
208             {
209                 Log.Error(Globals.LogTag, "Failed to initialize wifi, Error - " + (WiFiError)ret);
210                 WiFiErrorFactory.ThrowWiFiException(ret);
211             }
212             return handle;
213         }
214
215         internal void Deinitialize(IntPtr handle)
216         {
217             int ret = Interop.WiFi.Deinitialize(handle);
218             if (ret != (int)WiFiError.None)
219             {
220                 Log.Error(Globals.LogTag, "Failed to deinitialize wifi, Error - " + (WiFiError)ret);
221                 WiFiErrorFactory.ThrowWiFiException(ret);
222             }
223         }
224
225         internal IEnumerable<WiFiAP> GetFoundAPs()
226         {
227             List<WiFiAP> apList = new List<WiFiAP>();
228             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
229             {
230                 if (apHandle != IntPtr.Zero)
231                 {
232                     IntPtr clonedHandle;
233                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
234                     WiFiAP apItem = new WiFiAP(clonedHandle);
235                     apList.Add(apItem);
236                     return true;
237                 }
238                 return false;
239             };
240
241             int ret = Interop.WiFi.GetForeachFoundAPs(GetHandle(), callback, IntPtr.Zero);
242             if (ret != (int)WiFiError.None)
243             {
244                 Log.Error(Globals.LogTag, "Failed to get all APs, Error - " + (WiFiError)ret);
245                 WiFiErrorFactory.ThrowWiFiException(ret);
246             }
247
248             return apList;
249         }
250
251         internal IEnumerable<WiFiAP> GetFoundSpecificAPs()
252         {
253             List<WiFiAP> apList = new List<WiFiAP>();
254             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
255             {
256                 if (apHandle != IntPtr.Zero)
257                 {
258                     IntPtr clonedHandle;
259                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
260                     WiFiAP apItem = new WiFiAP(clonedHandle);
261                     apList.Add(apItem);
262                     return true;
263                 }
264                 return false;
265
266             };
267
268             int ret = Interop.WiFi.GetForeachFoundSpecificAPs(GetHandle(), callback, IntPtr.Zero);
269             if (ret != (int)WiFiError.None)
270             {
271                 Log.Error(Globals.LogTag, "Failed to get specific APs, Error - " + (WiFiError)ret);
272                 WiFiErrorFactory.ThrowWiFiException(ret);
273             }
274
275             return apList;
276         }
277
278         internal IEnumerable<WiFiConfiguration> GetWiFiConfigurations()
279         {
280             List<WiFiConfiguration> configList = new List<WiFiConfiguration>();
281             Interop.WiFi.HandleCallback callback = (IntPtr configHandle, IntPtr userData) =>
282             {
283                 if (configHandle != IntPtr.Zero)
284                 {
285                     IntPtr clonedConfig;
286                     Interop.WiFi.Config.Clone(configHandle, out clonedConfig);
287                     WiFiConfiguration configItem = new WiFiConfiguration(clonedConfig);
288                     configList.Add(configItem);
289                     return true;
290                 }
291                 return false;
292             };
293
294             int ret = Interop.WiFi.Config.GetForeachConfiguration(GetHandle(), callback, IntPtr.Zero);
295             if (ret != (int)WiFiError.None)
296             {
297                 Log.Error(Globals.LogTag, "Failed to get configurations, Error - " + (WiFiError)ret);
298                 WiFiErrorFactory.ThrowWiFiException(ret);
299             }
300
301             return configList;
302         }
303
304         internal void SaveWiFiNetworkConfiguration(WiFiConfiguration config)
305         {
306             IntPtr configHandle = config.GetHandle();
307             int ret = Interop.WiFi.Config.SaveConfiguration(GetHandle(), configHandle);
308             if (ret != (int)WiFiError.None)
309             {
310                 Log.Error(Globals.LogTag, "Failed to save configuration, Error - " + (WiFiError)ret);
311                 WiFiErrorFactory.ThrowWiFiException(ret);
312             }
313         }
314
315         internal WiFiAP GetConnectedAP()
316         {
317             IntPtr apHandle;
318
319             int ret = Interop.WiFi.GetConnectedAP(GetHandle(), out apHandle);
320             if (ret != (int)WiFiError.None)
321             {
322                 Log.Error(Globals.LogTag, "Failed to connect with AP, Error - " + (WiFiError)ret);
323                 WiFiErrorFactory.ThrowWiFiException(ret);
324             }
325             WiFiAP ap = new WiFiAP(apHandle);
326             return ap;
327         }
328
329         internal Task ActivateAsync()
330         {
331             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
332             IntPtr id;
333             lock (_callback_map)
334             {
335                 id = (IntPtr)_requestId++;
336                 _callback_map[id] = (error, key) =>
337                 {
338                     Log.Debug(Globals.LogTag, "wifi activated");
339                     if (error != (int)WiFiError.None)
340                     {
341                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
342                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
343                     }
344                     task.SetResult(true);
345                     lock (_callback_map)
346                     {
347                         _callback_map.Remove(key);
348                     }
349                 };
350             }
351             int ret = Interop.WiFi.Activate(GetHandle(), _callback_map[id], id);
352             if (ret != (int)WiFiError.None)
353             {
354                 Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
355                 WiFiErrorFactory.ThrowWiFiException(ret);
356             }
357             return task.Task;
358         }
359
360         internal Task ActivateWithWiFiPickerTestedAsync()
361         {
362             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
363             IntPtr id;
364             lock (_callback_map)
365             {
366                 id = (IntPtr)_requestId++;
367                 _callback_map[id] = (error, key) =>
368                 {
369                     Log.Debug(Globals.LogTag, "Activation finished");
370                     if (error != (int)WiFiError.None)
371                     {
372                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
373                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
374                     }
375                     task.SetResult(true);
376                     lock (_callback_map)
377                     {
378                         _callback_map.Remove(key);
379                     }
380                 };
381             }
382             int ret = Interop.WiFi.ActivateWithWiFiPickerTested(GetHandle(), _callback_map[id], id);
383             if (ret != (int)WiFiError.None)
384             {
385                 Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
386                 WiFiErrorFactory.ThrowWiFiException(ret);
387             }
388             return task.Task;
389         }
390
391         internal Task DeactivateAsync()
392         {
393             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
394             IntPtr id;
395             lock (_callback_map)
396             {
397                 id = (IntPtr)_requestId++;
398                 _callback_map[id] = (error, key) =>
399                 {
400                     Log.Debug(Globals.LogTag, "Deactivation finished");
401                     if (error != (int)WiFiError.None)
402                     {
403                         Log.Error(Globals.LogTag, "Error occurs during WiFi deactivating, " + (WiFiError)error);
404                         task.SetException(new InvalidOperationException("Error occurs during WiFi deactivating, " + (WiFiError)error));
405                     }
406                     task.SetResult(true);
407                     lock (_callback_map)
408                     {
409                         _callback_map.Remove(key);
410                     }
411                 };
412             }
413             int ret = Interop.WiFi.Deactivate(GetHandle(), _callback_map[id], id);
414             if (ret != (int)WiFiError.None)
415             {
416                 Log.Error(Globals.LogTag, "Failed to deactivate wifi, Error - " + (WiFiError)ret);
417                 WiFiErrorFactory.ThrowWiFiException(ret);
418             }
419             return task.Task;
420         }
421
422         internal Task ScanAsync()
423         {
424             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
425             IntPtr id;
426             lock (_callback_map)
427             {
428                 id = (IntPtr)_requestId++;
429                 _callback_map[id] = (error, key) =>
430                 {
431                     Log.Debug(Globals.LogTag, "Scanning finished");
432                     if (error != (int)WiFiError.None)
433                     {
434                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
435                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
436                     }
437                     task.SetResult(true);
438                     lock (_callback_map)
439                     {
440                         _callback_map.Remove(key);
441                     }
442                 };
443             }
444             int ret = Interop.WiFi.Scan(GetHandle(), _callback_map[id], id);
445             if (ret != (int)WiFiError.None)
446             {
447                 Log.Error(Globals.LogTag, "Failed to scan all AP, Error - " + (WiFiError)ret);
448                 WiFiErrorFactory.ThrowWiFiException(ret);
449             }
450             return task.Task;
451         }
452
453         internal Task ScanSpecificAPAsync(string essid)
454         {
455             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
456             IntPtr id;
457             lock (_callback_map)
458             {
459                 id = (IntPtr)_requestId++;
460                 _callback_map[id] = (error, key) =>
461                 {
462                     Log.Debug(Globals.LogTag, "Scanning with specific AP finished");
463                     if (error != (int)WiFiError.None)
464                     {
465                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
466                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
467                     }
468                     task.SetResult(true);
469                     lock (_callback_map)
470                     {
471                         _callback_map.Remove(key);
472                     }
473                 };
474             }
475             int ret = Interop.WiFi.ScanSpecificAP(GetHandle(), essid, _callback_map[id], id);
476             if (ret != (int)WiFiError.None)
477             {
478                 Log.Error(Globals.LogTag, "Failed to scan with specific AP, Error - " + (WiFiError)ret);
479                 WiFiErrorFactory.ThrowWiFiException(ret);
480             }
481             return task.Task;
482         }
483     }
484 }