[Connection][WiFi] Use TizenSynchronizationContext.Post for asynchronous methods...
[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<WiFiConfiguration> GetWiFiConfigurations()
222         {
223             Log.Debug(Globals.LogTag, "GetWiFiConfigurations");
224             List<WiFiConfiguration> configList = new List<WiFiConfiguration>();
225             Interop.WiFi.HandleCallback callback = (IntPtr configHandle, IntPtr userData) =>
226             {
227                 if (configHandle != IntPtr.Zero)
228                 {
229                     IntPtr clonedConfig;
230                     Interop.WiFi.Config.Clone(configHandle, out clonedConfig);
231                     WiFiConfiguration configItem = new WiFiConfiguration(clonedConfig);
232                     configList.Add(configItem);
233                     return true;
234                 }
235                 return false;
236             };
237
238             int ret = Interop.WiFi.Config.GetForeachConfiguration(GetSafeHandle(), callback, IntPtr.Zero);
239             if (ret != (int)WiFiError.None)
240             {
241                 Log.Error(Globals.LogTag, "Failed to get configurations, Error - " + (WiFiError)ret);
242                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.profile");
243             }
244
245             return configList;
246         }
247
248         internal void SaveWiFiNetworkConfiguration(WiFiConfiguration config)
249         {
250             Log.Debug(Globals.LogTag, "SaveWiFiNetworkConfiguration");
251             if (config == null)
252             {
253                 throw new ArgumentNullException("WiFi configuration is null");
254             }
255
256             IntPtr configHandle = config.GetHandle();
257             int ret = Interop.WiFi.Config.SaveConfiguration(GetSafeHandle(), configHandle);
258             if (ret != (int)WiFiError.None)
259             {
260                 Log.Error(Globals.LogTag, "Failed to save configuration, Error - " + (WiFiError)ret);
261                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.profile");
262             }
263         }
264
265         internal WiFiAP GetConnectedAP()
266         {
267             Log.Info(Globals.LogTag, "GetConnectedAP");
268             IntPtr apHandle;
269             int ret = Interop.WiFi.GetConnectedAP(GetSafeHandle(), out apHandle);
270             if (ret != (int)WiFiError.None)
271             {
272                 if (ret == (int)WiFiError.NoConnectionError)
273                 {
274                     Log.Error(Globals.LogTag, "No connection " + (WiFiError)ret);
275                     return null;
276                 }
277                 else
278                 {
279                     Log.Error(Globals.LogTag, "Failed to get connected AP, Error - " + (WiFiError)ret);
280                     WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.get");
281                 }
282             }
283             WiFiAP ap = new WiFiAP(apHandle);
284             return ap;
285         }
286
287         internal Task ActivateAsync()
288         {
289             Log.Info(Globals.LogTag, "ActivateAsync");
290             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
291             IntPtr id;
292             lock (_callback_map)
293             {
294                 id = (IntPtr)_requestId++;
295                 _callback_map[id] = (error, key) =>
296                 {
297                     Log.Info(Globals.LogTag, "ActivateAsync done");
298                     if (error != (int)WiFiError.None)
299                     {
300                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
301                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
302                     }
303                     else
304                     {
305                         task.SetResult(true);
306                     }
307                     lock (_callback_map)
308                     {
309                         _callback_map.Remove(key);
310                     }
311                 };
312             }
313
314             context.Post((x) =>
315             {
316                 Log.Info(Globals.LogTag, "Interop.WiFi.ActivateAsync");
317                 int ret = Interop.WiFi.Activate(GetSafeHandle(), _callback_map[id], id);
318                 if (ret != (int)WiFiError.None)
319                 {
320                 Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
321                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
322                 }
323             }, null);
324
325             return task.Task;
326         }
327
328         internal Task ActivateWithWiFiPickerTestedAsync()
329         {
330             Log.Info(Globals.LogTag, "ActivateWithWiFiPickerTestedAsync");
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.Info(Globals.LogTag, "ActivateWithWiFiPickerTestedAsync done");
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                     else
345                     {
346                         task.SetResult(true);
347                     }
348                     lock (_callback_map)
349                     {
350                         _callback_map.Remove(key);
351                     }
352                 };
353             }
354
355             context.Post((x) =>
356             {
357                 Log.Info(Globals.LogTag, "Interop.WiFi.ActivateWithWiFiPickerTestedAsync");
358                 int ret = Interop.WiFi.ActivateWithWiFiPickerTested(GetSafeHandle(), _callback_map[id], id);
359                 if (ret != (int)WiFiError.None)
360                 {
361                     Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
362                     WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
363                 }
364             }, null);
365             
366             return task.Task;
367         }
368
369         internal Task DeactivateAsync()
370         {
371             Log.Info(Globals.LogTag, "DeactivateAsync");
372             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
373             IntPtr id;
374             lock (_callback_map)
375             {
376                 id = (IntPtr)_requestId++;
377                 _callback_map[id] = (error, key) =>
378                 {
379                     Log.Info(Globals.LogTag, "DeactivateAsync done");
380                     if (error != (int)WiFiError.None)
381                     {
382                         Log.Error(Globals.LogTag, "Error occurs during WiFi deactivating, " + (WiFiError)error);
383                         task.SetException(new InvalidOperationException("Error occurs during WiFi deactivating, " + (WiFiError)error));
384                     }
385                     else
386                     {
387                         task.SetResult(true);
388                     }
389                     lock (_callback_map)
390                     {
391                         _callback_map.Remove(key);
392                     }
393                 };
394             }
395
396             context.Post((x) =>
397             {
398                 Log.Info(Globals.LogTag, "Interop.WiFi.Deactivate");
399                 int ret = Interop.WiFi.Deactivate(GetSafeHandle(), _callback_map[id], id);
400                 if (ret != (int)WiFiError.None)
401                 {
402                     Log.Error(Globals.LogTag, "Failed to deactivate wifi, Error - " + (WiFiError)ret);
403                     WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
404                 }
405             }, null);
406
407             return task.Task;           
408         }
409
410         internal Task ScanAsync()
411         {
412             Log.Info(Globals.LogTag, "ScanAsync");
413             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
414             IntPtr id;
415             lock (_callback_map)
416             {
417                 id = (IntPtr)_requestId++;
418                 _callback_map[id] = (error, key) =>
419                 {
420                     Log.Info(Globals.LogTag, "ScanAsync done");
421                     if (error != (int)WiFiError.None)
422                     {
423                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
424                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
425                     }
426                     else
427                     {
428                         task.SetResult(true);
429                     }
430                     lock (_callback_map)
431                     {
432                         _callback_map.Remove(key);
433                     }
434                 };
435             }
436
437             context.Post((x) =>
438             {
439                 Log.Info(Globals.LogTag, "Interop.WiFi.Scan");
440                 int ret = Interop.WiFi.Scan(GetSafeHandle(), _callback_map[id], id);
441                 if (ret != (int)WiFiError.None)
442                 {
443                     Log.Error(Globals.LogTag, "Failed to scan all AP, Error - " + (WiFiError)ret);
444                     WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
445                 }
446             }, null);
447
448             return task.Task;
449         }
450
451         internal Task ScanSpecificAPAsync(string essid)
452         {
453             Log.Info(Globals.LogTag, "ScanSpecificAPAsync " + essid);
454             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
455             IntPtr id;
456             lock (_callback_map)
457             {
458                 id = (IntPtr)_requestId++;
459                 _callback_map[id] = (error, key) =>
460                 {
461                     Log.Info(Globals.LogTag, "ScanSpecificAPAsync Done " + essid);
462                     if (error != (int)WiFiError.None)
463                     {
464                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
465                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
466                     }
467                     else
468                     {
469                         task.SetResult(true);
470                     }
471                     lock (_callback_map)
472                     {
473                         _callback_map.Remove(key);
474                     }
475                 };
476             }
477
478             context.Post((x) =>
479             {
480                 Log.Info(Globals.LogTag, "Interop.WiFi.ScanSpecificAPAsync");
481                 int ret = Interop.WiFi.ScanSpecificAP(GetSafeHandle(), essid, _callback_map[id], id);
482                 if (ret != (int)WiFiError.None)
483                 {
484                     Log.Error(Globals.LogTag, "Failed to scan with specific AP, Error - " + (WiFiError)ret);
485                     WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
486                 }
487             }, null);
488
489             return task.Task;
490         }
491
492         internal void UpdateAP(Interop.WiFi.SafeWiFiAPHandle apHandle)
493         {
494             int ret = Interop.WiFi.UpdateAP(GetSafeHandle(), apHandle.DangerousGetHandle());
495             if (ret != (int)WiFiError.None)
496             {
497                 Log.Error(Globals.LogTag, "Failed to update AP, Error - " + (WiFiError)ret);
498                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), apHandle.DangerousGetHandle());
499             }
500         }
501     }
502 }