[WiFi] TCSACR-149 (#292)
[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 using System.Runtime.InteropServices;
22 using Tizen.Applications;
23
24 namespace Tizen.Network.WiFi
25 {
26     static internal class Globals
27     {
28         internal const string LogTag = "Tizen.Network.WiFi";
29     }
30
31     internal class HandleHolder
32     {
33         private SafeWiFiManagerHandle _handle;
34
35         internal HandleHolder()
36         {
37             _handle = WiFiManagerImpl.Instance.Initialize();
38             Log.Info(Globals.LogTag, "Handle: " + _handle);
39         }
40
41         internal SafeWiFiManagerHandle GetSafeHandle()
42         {
43             Log.Debug(Globals.LogTag, "Handleholder safehandle = " + _handle);
44             return _handle;
45         }
46     }
47
48     internal partial class WiFiManagerImpl
49     {
50         private static readonly Lazy<WiFiManagerImpl> _instance =
51             new Lazy<WiFiManagerImpl>(() => new WiFiManagerImpl());
52
53         private TizenSynchronizationContext context = new TizenSynchronizationContext();
54         
55         private Dictionary<IntPtr, Interop.WiFi.VoidCallback> _callback_map =
56             new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
57         
58         private int _requestId = 0;
59         private string _macAddress;
60
61         internal string MacAddress
62         {
63             get
64             {
65                 if (String.IsNullOrEmpty(_macAddress))
66                 {
67                     string address;
68                     int ret = Interop.WiFi.GetMacAddress(GetSafeHandle(), out address);
69                     if (ret != (int)WiFiError.None)
70                     {
71                         Log.Error(Globals.LogTag, "Failed to get mac address, Error - " + (WiFiError)ret);
72                         _macAddress = "";
73                     }
74                     else
75                     {
76                         _macAddress = address;
77                     }
78                 }
79                 return _macAddress;
80             }
81         }
82
83         internal string InterfaceName
84         {
85             get
86             {
87                 string name;
88                 int ret = Interop.WiFi.GetNetworkInterfaceName(GetSafeHandle(), out name);
89                 if (ret != (int)WiFiError.None)
90                 {
91                     Log.Error(Globals.LogTag, "Failed to get interface name, Error - " + (WiFiError)ret);
92                     return "";
93                 }
94                 return name;
95             }
96         }
97
98         internal WiFiConnectionState ConnectionState
99         {
100             get
101             {
102                 int state;
103                 int ret = Interop.WiFi.GetConnectionState(GetSafeHandle(), out state);
104                 if (ret != (int)WiFiError.None)
105                 {
106                     Log.Error(Globals.LogTag, "Failed to get connection state, Error - " + (WiFiError)ret);
107                     return WiFiConnectionState.Failure;
108                 }
109                 return (WiFiConnectionState)state;
110             }
111         }
112
113         internal bool IsActive
114         {
115             get
116             {
117                 bool active;
118                 int ret = Interop.WiFi.IsActive(GetSafeHandle(), out active);
119                 if (ret != (int)WiFiError.None)
120                 {
121                     Log.Error(Globals.LogTag, "Failed to get isActive, Error - " + (WiFiError)ret);
122                 }
123                 return active;
124             }
125         }
126
127         internal static WiFiManagerImpl Instance
128         {
129             get
130             {
131                return _instance.Value;
132             }
133         }
134
135         private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
136         {
137             Log.Info(Globals.LogTag, "In threadlocal delegate");
138             return new HandleHolder();
139         });
140
141         private WiFiManagerImpl()
142         {
143             Log.Info(Globals.LogTag, "WiFiManagerImpl constructor");
144         }
145
146         internal SafeWiFiManagerHandle GetSafeHandle()
147         {
148             return s_threadName.Value.GetSafeHandle();
149         }
150
151         internal SafeWiFiManagerHandle Initialize()
152         {
153             SafeWiFiManagerHandle handle;
154             int tid = Thread.CurrentThread.ManagedThreadId;
155             Log.Info(Globals.LogTag, "PInvoke wifi_manager_initialize");
156             int ret = Interop.WiFi.Initialize(tid, out handle);
157             if (ret != (int)WiFiError.None)
158             {
159                 Log.Error(Globals.LogTag, "Failed to initialize wifi, Error - " + (WiFiError)ret);
160                 WiFiErrorFactory.ThrowWiFiException(ret, "http://tizen.org/privilege/network.get");
161             }
162             handle.SetTID(tid);
163             return handle;
164         }
165
166         internal IEnumerable<WiFiAP> GetFoundAPs()
167         {
168             Log.Info(Globals.LogTag, "GetFoundAPs");
169             List<WiFiAP> apList = new List<WiFiAP>();
170             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
171             {
172                 if (apHandle != IntPtr.Zero)
173                 {
174                     IntPtr clonedHandle;
175                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
176                     WiFiAP apItem = new WiFiAP(clonedHandle);
177                     apList.Add(apItem);
178                     return true;
179                 }
180                 return false;
181             };
182
183             int ret = Interop.WiFi.GetForeachFoundAPs(GetSafeHandle(), callback, IntPtr.Zero);
184             if (ret != (int)WiFiError.None)
185             {
186                 Log.Error(Globals.LogTag, "Failed to get all APs, Error - " + (WiFiError)ret);
187                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.get");
188             }
189
190             return apList;
191         }
192
193         internal IEnumerable<WiFiAP> GetFoundSpecificAPs()
194         {
195             Log.Info(Globals.LogTag, "GetFoundSpecificAPs");
196             List<WiFiAP> apList = new List<WiFiAP>();
197             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
198             {
199                 if (apHandle != IntPtr.Zero)
200                 {
201                     IntPtr clonedHandle;
202                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
203                     WiFiAP apItem = new WiFiAP(clonedHandle);
204                     apList.Add(apItem);
205                     return true;
206                 }
207                 return false;
208
209             };
210
211             int ret = Interop.WiFi.GetForeachFoundSpecificAPs(GetSafeHandle(), callback, IntPtr.Zero);
212             if (ret != (int)WiFiError.None)
213             {
214                 Log.Error(Globals.LogTag, "Failed to get specific APs, Error - " + (WiFiError)ret);
215                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.get");
216             }
217
218             return apList;
219         }
220
221         internal IEnumerable<WiFiAP> GetFoundBssids()
222         {
223             Log.Info(Globals.LogTag, "GetFoundBssids");
224             List<WiFiAP> apList = new List<WiFiAP>();
225             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
226             {
227                 if (apHandle != IntPtr.Zero)
228                 {
229                     IntPtr clonedHandle;
230                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
231                     WiFiAP apItem = new WiFiAP(clonedHandle);
232                     apList.Add(apItem);
233                     return true;
234                 }
235                 return false;
236             };
237
238             int ret = Interop.WiFi.GetForeachFoundBssids(GetSafeHandle(), callback, IntPtr.Zero);
239             if (ret != (int)WiFiError.None)
240             {
241                 Log.Error(Globals.LogTag, "Failed to get bssid APs, Error - " + (WiFiError)ret);
242                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.get");
243             }
244
245             return apList;
246         }
247
248         internal IEnumerable<WiFiConfiguration> GetWiFiConfigurations()
249         {
250             Log.Debug(Globals.LogTag, "GetWiFiConfigurations");
251             List<WiFiConfiguration> configList = new List<WiFiConfiguration>();
252             Interop.WiFi.HandleCallback callback = (IntPtr configHandle, IntPtr userData) =>
253             {
254                 if (configHandle != IntPtr.Zero)
255                 {
256                     IntPtr clonedConfig;
257                     Interop.WiFi.Config.Clone(configHandle, out clonedConfig);
258                     WiFiConfiguration configItem = new WiFiConfiguration(clonedConfig);
259                     configList.Add(configItem);
260                     return true;
261                 }
262                 return false;
263             };
264
265             int ret = Interop.WiFi.Config.GetForeachConfiguration(GetSafeHandle(), callback, IntPtr.Zero);
266             if (ret != (int)WiFiError.None)
267             {
268                 Log.Error(Globals.LogTag, "Failed to get configurations, Error - " + (WiFiError)ret);
269                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.profile");
270             }
271
272             return configList;
273         }
274
275         internal void SaveWiFiNetworkConfiguration(WiFiConfiguration config)
276         {
277             Log.Debug(Globals.LogTag, "SaveWiFiNetworkConfiguration");
278             if (config == null)
279             {
280                 throw new ArgumentNullException("WiFi configuration is null");
281             }
282
283             IntPtr configHandle = config.GetHandle();
284             int ret = Interop.WiFi.Config.SaveConfiguration(GetSafeHandle(), configHandle);
285             if (ret != (int)WiFiError.None)
286             {
287                 Log.Error(Globals.LogTag, "Failed to save configuration, Error - " + (WiFiError)ret);
288                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.profile");
289             }
290         }
291
292         internal WiFiAP GetConnectedAP()
293         {
294             Log.Info(Globals.LogTag, "GetConnectedAP");
295             IntPtr apHandle;
296             int ret = Interop.WiFi.GetConnectedAP(GetSafeHandle(), out apHandle);
297             if (ret != (int)WiFiError.None)
298             {
299                 if (ret == (int)WiFiError.NoConnectionError)
300                 {
301                     Log.Error(Globals.LogTag, "No connection " + (WiFiError)ret);
302                     return null;
303                 }
304                 else
305                 {
306                     Log.Error(Globals.LogTag, "Failed to get connected AP, Error - " + (WiFiError)ret);
307                     WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.get");
308                 }
309             }
310             WiFiAP ap = new WiFiAP(apHandle);
311             return ap;
312         }
313
314         internal Task ActivateAsync()
315         {
316             Log.Info(Globals.LogTag, "ActivateAsync");
317             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
318             IntPtr id;
319             lock (_callback_map)
320             {
321                 id = (IntPtr)_requestId++;
322                 _callback_map[id] = (error, key) =>
323                 {
324                     Log.Info(Globals.LogTag, "ActivateAsync done");
325                     if (error != (int)WiFiError.None)
326                     {
327                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
328                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
329                     }
330                     else
331                     {
332                         task.SetResult(true);
333                     }
334                     lock (_callback_map)
335                     {
336                         _callback_map.Remove(key);
337                     }
338                 };
339             }
340
341             context.Post((x) =>
342             {
343                 Log.Info(Globals.LogTag, "Interop.WiFi.ActivateAsync");
344                 try
345                 {
346                     int ret = Interop.WiFi.Activate(GetSafeHandle(), _callback_map[id], id);
347                     if (ret != (int)WiFiError.None)
348                     {
349                         Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
350                         WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
351                     }
352                 }
353                 catch (Exception e)
354                 {
355                     Log.Error(Globals.LogTag, "Exception on ActivateAsync\n" + e.ToString());
356                     task.SetException(e);
357                 }
358             }, null);
359
360             return task.Task;
361         }
362
363         internal Task ActivateWithWiFiPickerTestedAsync()
364         {
365             Log.Info(Globals.LogTag, "ActivateWithWiFiPickerTestedAsync");
366             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
367             IntPtr id;
368             lock (_callback_map)
369             {
370                 id = (IntPtr)_requestId++;
371                 _callback_map[id] = (error, key) =>
372                 {
373                     Log.Info(Globals.LogTag, "ActivateWithWiFiPickerTestedAsync done");
374                     if (error != (int)WiFiError.None)
375                     {
376                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
377                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
378                     }
379                     else
380                     {
381                         task.SetResult(true);
382                     }
383                     lock (_callback_map)
384                     {
385                         _callback_map.Remove(key);
386                     }
387                 };
388             }
389
390             context.Post((x) =>
391             {
392                 Log.Info(Globals.LogTag, "Interop.WiFi.ActivateWithWiFiPickerTestedAsync");
393                 try
394                 {
395                     int ret = Interop.WiFi.ActivateWithWiFiPickerTested(GetSafeHandle(), _callback_map[id], id);
396                     if (ret != (int)WiFiError.None)
397                     {
398                         Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
399                         WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
400                     }
401                 }
402                 catch (Exception e)
403                 {
404                     Log.Error(Globals.LogTag, "Exception on ActivateWithWiFiPickerTestedAsync\n" + e.ToString());
405                     task.SetException(e);
406                 }
407             }, null);
408             
409             return task.Task;
410         }
411
412         internal Task DeactivateAsync()
413         {
414             Log.Info(Globals.LogTag, "DeactivateAsync");
415             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
416             IntPtr id;
417             lock (_callback_map)
418             {
419                 id = (IntPtr)_requestId++;
420                 _callback_map[id] = (error, key) =>
421                 {
422                     Log.Info(Globals.LogTag, "DeactivateAsync done");
423                     if (error != (int)WiFiError.None)
424                     {
425                         Log.Error(Globals.LogTag, "Error occurs during WiFi deactivating, " + (WiFiError)error);
426                         task.SetException(new InvalidOperationException("Error occurs during WiFi deactivating, " + (WiFiError)error));
427                     }
428                     else
429                     {
430                         task.SetResult(true);
431                     }
432                     lock (_callback_map)
433                     {
434                         _callback_map.Remove(key);
435                     }
436                 };
437             }
438
439             context.Post((x) =>
440             {
441                 Log.Info(Globals.LogTag, "Interop.WiFi.Deactivate");
442                 try
443                 {
444                     int ret = Interop.WiFi.Deactivate(GetSafeHandle(), _callback_map[id], id);
445                     if (ret != (int)WiFiError.None)
446                     {
447                         Log.Error(Globals.LogTag, "Failed to deactivate wifi, Error - " + (WiFiError)ret);
448                         WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
449                     }
450                 }
451                 catch (Exception e)
452                 {
453                     Log.Error(Globals.LogTag, "Exception on Deactivate\n" + e.ToString());
454                     task.SetException(e);
455                 }
456             }, null);
457
458             return task.Task;           
459         }
460
461         internal Task ScanAsync()
462         {
463             Log.Info(Globals.LogTag, "ScanAsync");
464             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
465             IntPtr id;
466             lock (_callback_map)
467             {
468                 id = (IntPtr)_requestId++;
469                 _callback_map[id] = (error, key) =>
470                 {
471                     Log.Info(Globals.LogTag, "ScanAsync done");
472                     if (error != (int)WiFiError.None)
473                     {
474                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
475                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
476                     }
477                     else
478                     {
479                         task.SetResult(true);
480                     }
481                     lock (_callback_map)
482                     {
483                         _callback_map.Remove(key);
484                     }
485                 };
486             }
487
488             context.Post((x) =>
489             {
490                 Log.Info(Globals.LogTag, "Interop.WiFi.Scan");
491                 try
492                 {
493                     int ret = Interop.WiFi.Scan(GetSafeHandle(), _callback_map[id], id);
494                     if (ret != (int)WiFiError.None)
495                     {
496                         Log.Error(Globals.LogTag, "Failed to scan all AP, Error - " + (WiFiError)ret);
497                         WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
498                     }
499                 }
500                 catch (Exception e)
501                 {
502                     Log.Error(Globals.LogTag, "Exception on Scan\n" + e.ToString());
503                     task.SetException(e);
504                 }
505             }, null);
506
507             return task.Task;
508         }
509
510         internal Task ScanSpecificAPAsync(string essid)
511         {
512             Log.Info(Globals.LogTag, "ScanSpecificAPAsync " + essid);
513             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
514             IntPtr id;
515             lock (_callback_map)
516             {
517                 id = (IntPtr)_requestId++;
518                 _callback_map[id] = (error, key) =>
519                 {
520                     Log.Info(Globals.LogTag, "ScanSpecificAPAsync Done " + essid);
521                     if (error != (int)WiFiError.None)
522                     {
523                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
524                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
525                     }
526                     else
527                     {
528                         task.SetResult(true);
529                     }
530                     lock (_callback_map)
531                     {
532                         _callback_map.Remove(key);
533                     }
534                 };
535             }
536
537             context.Post((x) =>
538             {
539                 Log.Info(Globals.LogTag, "Interop.WiFi.ScanSpecificAPAsync");
540                 try
541                 {
542                     int ret = Interop.WiFi.ScanSpecificAP(GetSafeHandle(), essid, _callback_map[id], id);
543                     if (ret != (int)WiFiError.None)
544                     {
545                         Log.Error(Globals.LogTag, "Failed to scan with specific AP, Error - " + (WiFiError)ret);
546                         WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
547                     }
548                 }
549                 catch (Exception e)
550                 {
551                     Log.Error(Globals.LogTag, "Exception on ScanSpecificAPAsync\n" + e.ToString());
552                     task.SetException(e);
553                 }
554             }, null);
555
556             return task.Task;
557         }
558
559         internal Task BssidScanAsync()
560         {
561             Log.Info(Globals.LogTag, "BssidScanAsync");
562             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
563             IntPtr id;
564             lock (_callback_map)
565             {
566                 id = (IntPtr)_requestId++;
567                 _callback_map[id] = (error, key) =>
568                 {
569                     Log.Info(Globals.LogTag, "BssidScanAsync done");
570                     if (error != (int)WiFiError.None)
571                     {
572                         Log.Error(Globals.LogTag, "Error occurs during bssid scanning, " + (WiFiError)error);
573                         task.SetException(new InvalidOperationException("Error occurs during bssid scanning, " + (WiFiError)error));
574                     }
575                     else
576                     {
577                         task.SetResult(true);
578                     }
579                     lock (_callback_map)
580                     {
581                         _callback_map.Remove(key);
582                     }
583                 };
584             }
585
586             context.Post((x) =>
587             {
588                 Log.Info(Globals.LogTag, "Interop.WiFi.BssidScan");
589                 try
590                 {
591                     int ret = Interop.WiFi.BssidScan(GetSafeHandle(), _callback_map[id], id);
592                     if (ret != (int)WiFiError.None)
593                     {
594                         Log.Error(Globals.LogTag, "Failed to scan Bssid AP, Error - " + (WiFiError)ret);
595                         WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
596                     }
597                 }
598                 catch (Exception e)
599                 {
600                     Log.Error(Globals.LogTag, "Exception on BssidScan\n" + e.ToString());
601                     task.SetException(e);
602                 }
603             }, null);
604
605             return task.Task;
606         }
607     }
608 }