[Tizen.Network.WiFi] Use lock on checking if instance is null (#119)
[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
23 namespace Tizen.Network.WiFi
24 {
25     static internal class Globals
26     {
27         internal const string LogTag = "Tizen.Network.WiFi";
28     }
29
30     internal class HandleHolder
31     {
32         private SafeWiFiManagerHandle _handle;
33
34         internal HandleHolder()
35         {
36             _handle = WiFiManagerImpl.Instance.Initialize();
37             Log.Debug(Globals.LogTag, "Handle: " + _handle);
38         }
39
40         internal SafeWiFiManagerHandle GetSafeHandle()
41         {
42             Log.Debug(Globals.LogTag, "Handleholder safehandle = " + _handle);
43             return _handle;
44         }
45     }
46
47     internal partial class WiFiManagerImpl
48     {
49         private static readonly Lazy<WiFiManagerImpl> _instance =
50             new Lazy<WiFiManagerImpl>(() => new WiFiManagerImpl());
51         private Dictionary<IntPtr, Interop.WiFi.VoidCallback> _callback_map = new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
52         private int _requestId = 0;
53         private string _macAddress;
54
55         internal string MacAddress
56         {
57             get
58             {
59                 if (String.IsNullOrEmpty(_macAddress))
60                 {
61                     string address;
62                     int ret = Interop.WiFi.GetMacAddress(GetSafeHandle(), out address);
63                     if (ret != (int)WiFiError.None)
64                     {
65                         Log.Error(Globals.LogTag, "Failed to get mac address, Error - " + (WiFiError)ret);
66                         _macAddress = "";
67                     }
68                     else
69                     {
70                         _macAddress = address;
71                     }
72                 }
73                 return _macAddress;
74             }
75         }
76
77         internal string InterfaceName
78         {
79             get
80             {
81                 string name;
82                 int ret = Interop.WiFi.GetNetworkInterfaceName(GetSafeHandle(), out name);
83                 if (ret != (int)WiFiError.None)
84                 {
85                     Log.Error(Globals.LogTag, "Failed to get interface name, Error - " + (WiFiError)ret);
86                     return "";
87                 }
88                 return name;
89             }
90         }
91
92         internal WiFiConnectionState ConnectionState
93         {
94             get
95             {
96                 int state;
97                 int ret = Interop.WiFi.GetConnectionState(GetSafeHandle(), out state);
98                 if (ret != (int)WiFiError.None)
99                 {
100                     Log.Error(Globals.LogTag, "Failed to get connection state, Error - " + (WiFiError)ret);
101                     return WiFiConnectionState.Failure;
102                 }
103                 return (WiFiConnectionState)state;
104             }
105         }
106
107         internal bool IsActive
108         {
109             get
110             {
111                 bool active;
112                 int ret = Interop.WiFi.IsActive(GetSafeHandle(), out active);
113                 if (ret != (int)WiFiError.None)
114                 {
115                     Log.Error(Globals.LogTag, "Failed to get isActive, Error - " + (WiFiError)ret);
116                 }
117                 return active;
118             }
119         }
120
121         internal static WiFiManagerImpl Instance
122         {
123             get
124             {
125                return _instance.Value;
126             }
127         }
128
129         private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
130         {
131             Log.Info(Globals.LogTag, "In threadlocal delegate");
132             return new HandleHolder();
133         });
134
135         private WiFiManagerImpl()
136         {
137             Log.Info(Globals.LogTag, "WiFiManagerImpl constructor");
138         }
139
140         internal SafeWiFiManagerHandle GetSafeHandle()
141         {
142             return s_threadName.Value.GetSafeHandle();
143         }
144
145         internal SafeWiFiManagerHandle Initialize()
146         {
147             SafeWiFiManagerHandle handle;
148             int ret = Interop.WiFi.Initialize(out handle);
149             if (ret != (int)WiFiError.None)
150             {
151                 Log.Error(Globals.LogTag, "Failed to initialize wifi, Error - " + (WiFiError)ret);
152                 WiFiErrorFactory.ThrowWiFiException(ret, "http://tizen.org/privilege/network.get");
153             }
154             return handle;
155         }
156
157         internal IEnumerable<WiFiAP> GetFoundAPs()
158         {
159             Log.Debug(Globals.LogTag, "GetFoundAPs");
160             List<WiFiAP> apList = new List<WiFiAP>();
161             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
162             {
163                 if (apHandle != IntPtr.Zero)
164                 {
165                     IntPtr clonedHandle;
166                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
167                     WiFiAP apItem = new WiFiAP(clonedHandle);
168                     apList.Add(apItem);
169                     return true;
170                 }
171                 return false;
172             };
173
174             int ret = Interop.WiFi.GetForeachFoundAPs(GetSafeHandle(), callback, IntPtr.Zero);
175             if (ret != (int)WiFiError.None)
176             {
177                 Log.Error(Globals.LogTag, "Failed to get all APs, Error - " + (WiFiError)ret);
178                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.get");
179             }
180
181             return apList;
182         }
183
184         internal IEnumerable<WiFiAP> GetFoundSpecificAPs()
185         {
186             Log.Debug(Globals.LogTag, "GetFoundSpecificAPs");
187             List<WiFiAP> apList = new List<WiFiAP>();
188             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
189             {
190                 if (apHandle != IntPtr.Zero)
191                 {
192                     IntPtr clonedHandle;
193                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
194                     WiFiAP apItem = new WiFiAP(clonedHandle);
195                     apList.Add(apItem);
196                     return true;
197                 }
198                 return false;
199
200             };
201
202             int ret = Interop.WiFi.GetForeachFoundSpecificAPs(GetSafeHandle(), callback, IntPtr.Zero);
203             if (ret != (int)WiFiError.None)
204             {
205                 Log.Error(Globals.LogTag, "Failed to get specific APs, Error - " + (WiFiError)ret);
206                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.get");
207             }
208
209             return apList;
210         }
211
212         internal IEnumerable<WiFiConfiguration> GetWiFiConfigurations()
213         {
214             Log.Debug(Globals.LogTag, "GetWiFiConfigurations");
215             List<WiFiConfiguration> configList = new List<WiFiConfiguration>();
216             Interop.WiFi.HandleCallback callback = (IntPtr configHandle, IntPtr userData) =>
217             {
218                 if (configHandle != IntPtr.Zero)
219                 {
220                     IntPtr clonedConfig;
221                     Interop.WiFi.Config.Clone(configHandle, out clonedConfig);
222                     WiFiConfiguration configItem = new WiFiConfiguration(clonedConfig);
223                     configList.Add(configItem);
224                     return true;
225                 }
226                 return false;
227             };
228
229             int ret = Interop.WiFi.Config.GetForeachConfiguration(GetSafeHandle(), callback, IntPtr.Zero);
230             if (ret != (int)WiFiError.None)
231             {
232                 Log.Error(Globals.LogTag, "Failed to get configurations, Error - " + (WiFiError)ret);
233                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.profile");
234             }
235
236             return configList;
237         }
238
239         internal void SaveWiFiNetworkConfiguration(WiFiConfiguration config)
240         {
241             Log.Debug(Globals.LogTag, "SaveWiFiNetworkConfiguration");
242             if (config == null)
243             {
244                 throw new ArgumentNullException("WiFi configuration is null");
245             }
246
247             IntPtr configHandle = config.GetHandle();
248             int ret = Interop.WiFi.Config.SaveConfiguration(GetSafeHandle(), configHandle);
249             if (ret != (int)WiFiError.None)
250             {
251                 Log.Error(Globals.LogTag, "Failed to save configuration, Error - " + (WiFiError)ret);
252                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.profile");
253             }
254         }
255
256         internal WiFiAP GetConnectedAP()
257         {
258             Log.Debug(Globals.LogTag, "GetConnectedAP");
259             IntPtr apHandle;
260             int ret = Interop.WiFi.GetConnectedAP(GetSafeHandle(), out apHandle);
261             if (ret != (int)WiFiError.None)
262             {
263                 if (ret == (int)WiFiError.NoConnectionError)
264                 {
265                     Log.Error(Globals.LogTag, "No connection " + (WiFiError)ret);
266                     return null;
267                 }
268                 else
269                 {
270                     Log.Error(Globals.LogTag, "Failed to get connected AP, Error - " + (WiFiError)ret);
271                     WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle(), "http://tizen.org/privilege/network.get");
272                 }
273             }
274             WiFiAP ap = new WiFiAP(apHandle);
275             return ap;
276         }
277
278         internal Task ActivateAsync()
279         {
280             Log.Debug(Globals.LogTag, "ActivateAsync");
281             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
282             IntPtr id;
283             lock (_callback_map)
284             {
285                 id = (IntPtr)_requestId++;
286                 _callback_map[id] = (error, key) =>
287                 {
288                     Log.Debug(Globals.LogTag, "wifi activated");
289                     if (error != (int)WiFiError.None)
290                     {
291                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
292                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
293                     }
294                     else
295                     {
296                         task.SetResult(true);
297                     }
298                     lock (_callback_map)
299                     {
300                         _callback_map.Remove(key);
301                     }
302                 };
303             }
304             int ret = Interop.WiFi.Activate(GetSafeHandle(), _callback_map[id], id);
305             if (ret != (int)WiFiError.None)
306             {
307                 Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
308                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
309             }
310             return task.Task;
311         }
312
313         internal Task ActivateWithWiFiPickerTestedAsync()
314         {
315             Log.Debug(Globals.LogTag, "ActivateWithWiFiPickerTestedAsync");
316             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
317             IntPtr id;
318             lock (_callback_map)
319             {
320                 id = (IntPtr)_requestId++;
321                 _callback_map[id] = (error, key) =>
322                 {
323                     Log.Debug(Globals.LogTag, "Activation finished");
324                     if (error != (int)WiFiError.None)
325                     {
326                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
327                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
328                     }
329                     else
330                     {
331                         task.SetResult(true);
332                     }
333                     lock (_callback_map)
334                     {
335                         _callback_map.Remove(key);
336                     }
337                 };
338             }
339             int ret = Interop.WiFi.ActivateWithWiFiPickerTested(GetSafeHandle(), _callback_map[id], id);
340             if (ret != (int)WiFiError.None)
341             {
342                 Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
343                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
344             }
345             return task.Task;
346         }
347
348         internal Task DeactivateAsync()
349         {
350             Log.Debug(Globals.LogTag, "DeactivateAsync");
351             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
352             IntPtr id;
353             lock (_callback_map)
354             {
355                 id = (IntPtr)_requestId++;
356                 _callback_map[id] = (error, key) =>
357                 {
358                     Log.Debug(Globals.LogTag, "Deactivation finished");
359                     if (error != (int)WiFiError.None)
360                     {
361                         Log.Error(Globals.LogTag, "Error occurs during WiFi deactivating, " + (WiFiError)error);
362                         task.SetException(new InvalidOperationException("Error occurs during WiFi deactivating, " + (WiFiError)error));
363                     }
364                     else
365                     {
366                         task.SetResult(true);
367                     }
368                     lock (_callback_map)
369                     {
370                         _callback_map.Remove(key);
371                     }
372                 };
373             }
374             int ret = Interop.WiFi.Deactivate(GetSafeHandle(), _callback_map[id], id);
375             if (ret != (int)WiFiError.None)
376             {
377                 Log.Error(Globals.LogTag, "Failed to deactivate wifi, Error - " + (WiFiError)ret);
378                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
379             }
380             return task.Task;
381         }
382
383         internal Task ScanAsync()
384         {
385             Log.Debug(Globals.LogTag, "ScanAsync");
386             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
387             IntPtr id;
388             lock (_callback_map)
389             {
390                 id = (IntPtr)_requestId++;
391                 _callback_map[id] = (error, key) =>
392                 {
393                     Log.Debug(Globals.LogTag, "Scanning finished");
394                     if (error != (int)WiFiError.None)
395                     {
396                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
397                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
398                     }
399                     else
400                     {
401                         task.SetResult(true);
402                     }
403                     lock (_callback_map)
404                     {
405                         _callback_map.Remove(key);
406                     }
407                 };
408             }
409             int ret = Interop.WiFi.Scan(GetSafeHandle(), _callback_map[id], id);
410             if (ret != (int)WiFiError.None)
411             {
412                 Log.Error(Globals.LogTag, "Failed to scan all AP, Error - " + (WiFiError)ret);
413                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
414             }
415             return task.Task;
416         }
417
418         internal Task ScanSpecificAPAsync(string essid)
419         {
420             Log.Debug(Globals.LogTag, "ScanSpecificAPAsync " + essid);
421             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
422             IntPtr id;
423             lock (_callback_map)
424             {
425                 id = (IntPtr)_requestId++;
426                 _callback_map[id] = (error, key) =>
427                 {
428                     Log.Debug(Globals.LogTag, "Scanning with specific AP finished");
429                     if (error != (int)WiFiError.None)
430                     {
431                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
432                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
433                     }
434                     else
435                     {
436                         task.SetResult(true);
437                     }
438                     lock (_callback_map)
439                     {
440                         _callback_map.Remove(key);
441                     }
442                 };
443             }
444             int ret = Interop.WiFi.ScanSpecificAP(GetSafeHandle(), essid, _callback_map[id], id);
445             if (ret != (int)WiFiError.None)
446             {
447                 Log.Error(Globals.LogTag, "Failed to scan with specific AP, Error - " + (WiFiError)ret);
448                 WiFiErrorFactory.ThrowWiFiException(ret, GetSafeHandle().DangerousGetHandle());
449             }
450             return task.Task;
451         }
452     }
453 }