[WiFi] Modified the framework code to use SafeHandle for CAPI handles.
[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 Interop.WiFi.SafeWiFiManagerHandle _handle;
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         internal Interop.WiFi.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 WiFiManagerImpl _instance = null;
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                 Log.Debug(Globals.LogTag, "Instance getter");
126                 if (_instance == null)
127                 {
128                     Log.Debug(Globals.LogTag, "Instance is null");
129                     _instance = new WiFiManagerImpl();
130                 }
131
132                 return _instance;
133             }
134         }
135
136         private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
137         {
138             Log.Info(Globals.LogTag, "In threadlocal delegate");
139             return new HandleHolder();
140         });
141
142         private WiFiManagerImpl()
143         {
144         }
145
146         internal Interop.WiFi.SafeWiFiManagerHandle GetSafeHandle()
147         {
148             Log.Debug(Globals.LogTag, "GetHandle, Thread Id = " + Thread.CurrentThread.ManagedThreadId);
149             return s_threadName.Value.GetSafeHandle();
150         }
151
152         internal Interop.WiFi.SafeWiFiManagerHandle Initialize()
153         {
154             Interop.WiFi.SafeWiFiManagerHandle handle = new Interop.WiFi.SafeWiFiManagerHandle();
155             int ret = Interop.WiFi.Initialize(out handle);
156             if (ret != (int)WiFiError.None)
157             {
158                 Log.Error(Globals.LogTag, "Failed to initialize wifi, Error - " + (WiFiError)ret);
159                 WiFiErrorFactory.ThrowWiFiException(ret);
160             }
161             return handle;
162         }
163
164         internal IEnumerable<WiFiAP> GetFoundAPs()
165         {
166             List<WiFiAP> apList = new List<WiFiAP>();
167             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
168             {
169                 if (apHandle != IntPtr.Zero)
170                 {
171                     IntPtr clonedHandle;
172                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
173                     WiFiAP apItem = new WiFiAP(clonedHandle);
174                     apList.Add(apItem);
175                     return true;
176                 }
177                 return false;
178             };
179
180             int ret = Interop.WiFi.GetForeachFoundAPs(GetSafeHandle(), callback, IntPtr.Zero);
181             if (ret != (int)WiFiError.None)
182             {
183                 Log.Error(Globals.LogTag, "Failed to get all APs, Error - " + (WiFiError)ret);
184                 WiFiErrorFactory.ThrowWiFiException(ret);
185             }
186
187             return apList;
188         }
189
190         internal IEnumerable<WiFiAP> GetFoundSpecificAPs()
191         {
192             List<WiFiAP> apList = new List<WiFiAP>();
193             Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) =>
194             {
195                 if (apHandle != IntPtr.Zero)
196                 {
197                     IntPtr clonedHandle;
198                     Interop.WiFi.AP.Clone(out clonedHandle, apHandle);
199                     WiFiAP apItem = new WiFiAP(clonedHandle);
200                     apList.Add(apItem);
201                     return true;
202                 }
203                 return false;
204
205             };
206
207             int ret = Interop.WiFi.GetForeachFoundSpecificAPs(GetSafeHandle(), callback, IntPtr.Zero);
208             if (ret != (int)WiFiError.None)
209             {
210                 Log.Error(Globals.LogTag, "Failed to get specific APs, Error - " + (WiFiError)ret);
211                 WiFiErrorFactory.ThrowWiFiException(ret);
212             }
213
214             return apList;
215         }
216
217         internal IEnumerable<WiFiConfiguration> GetWiFiConfigurations()
218         {
219             List<WiFiConfiguration> configList = new List<WiFiConfiguration>();
220             Interop.WiFi.HandleCallback callback = (IntPtr configHandle, IntPtr userData) =>
221             {
222                 if (configHandle != IntPtr.Zero)
223                 {
224                     IntPtr clonedConfig;
225                     Interop.WiFi.Config.Clone(configHandle, out clonedConfig);
226                     WiFiConfiguration configItem = new WiFiConfiguration(clonedConfig);
227                     configList.Add(configItem);
228                     return true;
229                 }
230                 return false;
231             };
232
233             int ret = Interop.WiFi.Config.GetForeachConfiguration(GetSafeHandle(), callback, IntPtr.Zero);
234             if (ret != (int)WiFiError.None)
235             {
236                 Log.Error(Globals.LogTag, "Failed to get configurations, Error - " + (WiFiError)ret);
237                 WiFiErrorFactory.ThrowWiFiException(ret);
238             }
239
240             return configList;
241         }
242
243         internal void SaveWiFiNetworkConfiguration(WiFiConfiguration config)
244         {
245             IntPtr configHandle = config.GetHandle();
246             int ret = Interop.WiFi.Config.SaveConfiguration(GetSafeHandle(), configHandle);
247             if (ret != (int)WiFiError.None)
248             {
249                 Log.Error(Globals.LogTag, "Failed to save configuration, Error - " + (WiFiError)ret);
250                 WiFiErrorFactory.ThrowWiFiException(ret);
251             }
252         }
253
254         internal WiFiAP GetConnectedAP()
255         {
256             IntPtr apHandle;
257
258             int ret = Interop.WiFi.GetConnectedAP(GetSafeHandle(), out apHandle);
259             if (ret != (int)WiFiError.None)
260             {
261                 Log.Error(Globals.LogTag, "Failed to connect with AP, Error - " + (WiFiError)ret);
262                 WiFiErrorFactory.ThrowWiFiException(ret);
263             }
264             WiFiAP ap = new WiFiAP(apHandle);
265             return ap;
266         }
267
268         internal Task ActivateAsync()
269         {
270             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
271             IntPtr id;
272             lock (_callback_map)
273             {
274                 id = (IntPtr)_requestId++;
275                 _callback_map[id] = (error, key) =>
276                 {
277                     Log.Debug(Globals.LogTag, "wifi activated");
278                     if (error != (int)WiFiError.None)
279                     {
280                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
281                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
282                     }
283                     task.SetResult(true);
284                     lock (_callback_map)
285                     {
286                         _callback_map.Remove(key);
287                     }
288                 };
289             }
290             int ret = Interop.WiFi.Activate(GetSafeHandle(), _callback_map[id], id);
291             if (ret != (int)WiFiError.None)
292             {
293                 Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
294                 WiFiErrorFactory.ThrowWiFiException(ret);
295             }
296             return task.Task;
297         }
298
299         internal Task ActivateWithWiFiPickerTestedAsync()
300         {
301             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
302             IntPtr id;
303             lock (_callback_map)
304             {
305                 id = (IntPtr)_requestId++;
306                 _callback_map[id] = (error, key) =>
307                 {
308                     Log.Debug(Globals.LogTag, "Activation finished");
309                     if (error != (int)WiFiError.None)
310                     {
311                         Log.Error(Globals.LogTag, "Error occurs during WiFi activating, " + (WiFiError)error);
312                         task.SetException(new InvalidOperationException("Error occurs during WiFi activating, " + (WiFiError)error));
313                     }
314                     task.SetResult(true);
315                     lock (_callback_map)
316                     {
317                         _callback_map.Remove(key);
318                     }
319                 };
320             }
321             int ret = Interop.WiFi.ActivateWithWiFiPickerTested(GetSafeHandle(), _callback_map[id], id);
322             if (ret != (int)WiFiError.None)
323             {
324                 Log.Error(Globals.LogTag, "Failed to activate wifi, Error - " + (WiFiError)ret);
325                 WiFiErrorFactory.ThrowWiFiException(ret);
326             }
327             return task.Task;
328         }
329
330         internal Task DeactivateAsync()
331         {
332             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
333             IntPtr id;
334             lock (_callback_map)
335             {
336                 id = (IntPtr)_requestId++;
337                 _callback_map[id] = (error, key) =>
338                 {
339                     Log.Debug(Globals.LogTag, "Deactivation finished");
340                     if (error != (int)WiFiError.None)
341                     {
342                         Log.Error(Globals.LogTag, "Error occurs during WiFi deactivating, " + (WiFiError)error);
343                         task.SetException(new InvalidOperationException("Error occurs during WiFi deactivating, " + (WiFiError)error));
344                     }
345                     task.SetResult(true);
346                     lock (_callback_map)
347                     {
348                         _callback_map.Remove(key);
349                     }
350                 };
351             }
352             int ret = Interop.WiFi.Deactivate(GetSafeHandle(), _callback_map[id], id);
353             if (ret != (int)WiFiError.None)
354             {
355                 Log.Error(Globals.LogTag, "Failed to deactivate wifi, Error - " + (WiFiError)ret);
356                 WiFiErrorFactory.ThrowWiFiException(ret);
357             }
358             return task.Task;
359         }
360
361         internal Task ScanAsync()
362         {
363             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
364             IntPtr id;
365             lock (_callback_map)
366             {
367                 id = (IntPtr)_requestId++;
368                 _callback_map[id] = (error, key) =>
369                 {
370                     Log.Debug(Globals.LogTag, "Scanning finished");
371                     if (error != (int)WiFiError.None)
372                     {
373                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
374                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
375                     }
376                     task.SetResult(true);
377                     lock (_callback_map)
378                     {
379                         _callback_map.Remove(key);
380                     }
381                 };
382             }
383             int ret = Interop.WiFi.Scan(GetSafeHandle(), _callback_map[id], id);
384             if (ret != (int)WiFiError.None)
385             {
386                 Log.Error(Globals.LogTag, "Failed to scan all AP, Error - " + (WiFiError)ret);
387                 WiFiErrorFactory.ThrowWiFiException(ret);
388             }
389             return task.Task;
390         }
391
392         internal Task ScanSpecificAPAsync(string essid)
393         {
394             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
395             IntPtr id;
396             lock (_callback_map)
397             {
398                 id = (IntPtr)_requestId++;
399                 _callback_map[id] = (error, key) =>
400                 {
401                     Log.Debug(Globals.LogTag, "Scanning with specific AP finished");
402                     if (error != (int)WiFiError.None)
403                     {
404                         Log.Error(Globals.LogTag, "Error occurs during WiFi scanning, " + (WiFiError)error);
405                         task.SetException(new InvalidOperationException("Error occurs during WiFi scanning, " + (WiFiError)error));
406                     }
407                     task.SetResult(true);
408                     lock (_callback_map)
409                     {
410                         _callback_map.Remove(key);
411                     }
412                 };
413             }
414             int ret = Interop.WiFi.ScanSpecificAP(GetSafeHandle(), essid, _callback_map[id], id);
415             if (ret != (int)WiFiError.None)
416             {
417                 Log.Error(Globals.LogTag, "Failed to scan with specific AP, Error - " + (WiFiError)ret);
418                 WiFiErrorFactory.ThrowWiFiException(ret);
419             }
420             return task.Task;
421         }
422     }
423 }