Merge remote-tracking branch 'origin/API8' into tizen_6.0
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.WiFi / Tizen.Network.WiFi / WiFiAP.cs
1 /*
2  * Copyright (c) 2018 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.Threading.Tasks;
19 using System.Collections.Generic;
20 using Tizen.Applications;
21
22 namespace Tizen.Network.WiFi
23 {
24     /// <summary>
25     /// A class for managing the network information of the access point (AP).
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public class WiFiAP : IDisposable
29     {
30         private IntPtr _apHandle = IntPtr.Zero;
31         private Dictionary<IntPtr, Interop.WiFi.VoidCallback> _callback_map = new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
32         private static Dictionary<IntPtr, Interop.WiFi.VoidCallback> s_callbackMap = new Dictionary<IntPtr, Interop.WiFi.VoidCallback>();
33         private int _requestId = 0;
34         private static int s_requestId = 0;
35         private WiFiNetwork _network;
36         private WiFiSecurity _security;
37         private bool _disposed = false;
38
39         private static TaskCompletionSource<WiFiAP> wpsWithoutSsidTask = null;
40         private static Dictionary<IntPtr, TaskCompletionSource<bool>> _wpsTaskMap = new Dictionary<IntPtr, TaskCompletionSource<bool>>();
41         private TizenSynchronizationContext context = new TizenSynchronizationContext();
42         private static TizenSynchronizationContext s_context = new TizenSynchronizationContext();
43
44         /// <summary>
45         /// The network information of the access point (AP).
46         /// </summary>
47         /// <since_tizen> 3 </since_tizen>
48         /// <value>The WiFiNetwork instance containing the network information of the AP.</value>
49         public WiFiNetwork NetworkInformation
50         {
51             get
52             {
53                 return _network;
54             }
55         }
56
57         /// <summary>
58         /// The security information of the access point (AP).
59         /// </summary>
60         /// <since_tizen> 3 </since_tizen>
61         /// <value>The WiFiSecurity instance containing security information of the AP.</value>
62         public WiFiSecurity SecurityInformation
63         {
64             get
65             {
66                 return _security;
67             }
68         }
69
70         internal WiFiAP(IntPtr handle)
71         {
72             Log.Debug(Globals.LogTag, "New WiFiAP. Handle: " + handle);
73             _apHandle = handle;
74             Initialize();
75         }
76
77         /// <summary>
78         /// Creates an object for the access point.
79         /// </summary>
80         /// <since_tizen> 3 </since_tizen>
81         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
82         /// <feature>http://tizen.org/feature/network.wifi</feature>
83         /// <privilege>http://tizen.org/privilege/network.get</privilege>
84         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
85         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
86         /// <exception cref="ArgumentNullException">Thrown when the ESSID is passed as null.</exception>
87         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
88         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
89         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
90         public WiFiAP(string essid)
91         {
92             Log.Debug(Globals.LogTag, "New WiFiAP. Essid: " + essid);
93             createHandle(essid, true);
94             Initialize();
95         }
96
97         /// <summary>
98         /// Creates an object for the hidden access point.
99         /// </summary>
100         /// <since_tizen> 3 </since_tizen>
101         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
102         /// <param name="hidden">The value to set a hidden AP.</param>
103         /// <feature>http://tizen.org/feature/network.wifi</feature>
104         /// <privilege>http://tizen.org/privilege/network.get</privilege>
105         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
106         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
107         /// <exception cref="ArgumentNullException">Thrown when the ESSID is passed as null.</exception>
108         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
109         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
110         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
111         public WiFiAP(string essid, bool hidden)
112         {
113             createHandle(essid, hidden);
114             Initialize();
115         }
116
117         /// <summary>
118         /// Destroy the WiFiAP object
119         /// </summary>
120         ~WiFiAP()
121         {
122             Dispose(false);
123         }
124
125         /// <summary>
126         /// A method to destroy the managed WiFiAP objects.
127         /// </summary>
128         /// <since_tizen> 3 </since_tizen>
129         public void Dispose()
130         {
131             Dispose(true);
132             GC.SuppressFinalize(this);
133         }
134
135         private void Dispose(bool disposing)
136         {
137             if (_disposed)
138                 return;
139
140             Log.Info(Globals.LogTag, "WiFiAP Handle HashCode: " + _apHandle.GetHashCode());
141             int ret = Interop.WiFi.AP.Destroy(_apHandle);
142             if (ret == (int)WiFiError.None)
143             {
144                 _apHandle = IntPtr.Zero;
145             }
146             _disposed = true;
147         }
148
149         private void createHandle(string id, bool hidden)
150         {
151             int ret;
152             if (id == null)
153             {
154                 throw new ArgumentNullException("Essid is null");
155             }
156
157             if (hidden)
158             {
159                 ret = Interop.WiFi.AP.CreateHiddenAP(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
160             }
161             else
162             {
163                 ret = Interop.WiFi.AP.Create(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
164             }
165
166             if (ret != (int)WiFiError.None)
167             {
168                 Log.Error(Globals.LogTag, "Failed to create handle, Error - " + (WiFiError)ret);
169                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
170             }
171         }
172
173         private void Initialize()
174         {
175             Interop.WiFi.SafeWiFiAPHandle apHandle = new Interop.WiFi.SafeWiFiAPHandle(_apHandle);
176             _network = new WiFiNetwork(apHandle);
177             _security = new WiFiSecurity(apHandle);
178         }
179
180         /// <summary>
181         /// Refreshes the access point information.
182         /// </summary>
183         /// <since_tizen> 3 </since_tizen>
184         /// <feature>http://tizen.org/feature/network.wifi</feature>
185         /// <privilege>http://tizen.org/privilege/network.get</privilege>
186         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
187         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
188         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
189         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
190         public void Refresh()
191         {
192             Log.Debug(Globals.LogTag, "Refresh");
193             if (_disposed)
194             {
195                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
196             }
197             int ret = Interop.WiFi.AP.Refresh(_apHandle);
198             if (ret != (int)WiFiError.None)
199             {
200                 Log.Error(Globals.LogTag, "Failed to refresh ap handle, Error - " + (WiFiError)ret);
201                 if (ret == (int)WiFiError.InvalidParameterError)
202                 {
203                     throw new InvalidOperationException("Invalid handle");
204                 }
205                 WiFiErrorFactory.ThrowWiFiException(ret, _apHandle, "http://tizen.org/privilege/network.get");
206             }
207         }
208
209         /// <summary>
210         /// Connects the access point asynchronously.
211         /// </summary>
212         /// <since_tizen> 3 </since_tizen>
213         /// <returns> A task indicating whether the connect method is done or not.</returns>
214         /// <remarks>
215         /// This method must be called from MainThread.
216         /// </remarks>
217         /// <feature>http://tizen.org/feature/network.wifi</feature>
218         /// <privilege>http://tizen.org/privilege/network.set</privilege>
219         /// <privilege>http://tizen.org/privilege/network.get</privilege>
220         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
221         /// <exception cref="NowInProgressException">Thrown when the Wi-Fi connection is now in progress.</exception>
222         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
223         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
224         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
225         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
226         /// <exception cref="InvalidKeyException">Thrown when the key is wrong.</exception>
227         public Task ConnectAsync()
228         {
229             Log.Info(Globals.LogTag, "ConnectAsync HashCode: " + _apHandle.GetHashCode());
230             if (_disposed)
231             {
232                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
233             }
234             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
235             IntPtr id;
236             lock (_callback_map)
237             {
238                 id = (IntPtr)_requestId++;
239                 _callback_map[id] = (error, key) =>
240                 {
241                     Log.Info(Globals.LogTag, "ConnectAsync done " + (WiFiError)error);
242                     if (error != (int)WiFiError.None)
243                     {
244                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
245                         task.SetException(WiFiErrorFactory.GetException(error, "Error occurs during WiFi connecting"));
246                     }
247                     else
248                     {
249                         task.SetResult(true);
250                     }
251                     lock (_callback_map)
252                     {
253                         _callback_map.Remove(key);
254                     }
255                 };
256             }
257
258             context.Post((x) =>
259             {
260                 Log.Info(Globals.LogTag, "Interop.WiFi.Connect");
261                 try
262                 {
263                     int ret = Interop.WiFi.Connect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
264                     if (ret != (int)WiFiError.None)
265                     {
266                         Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
267                         if (ret == (int)WiFiError.InvalidParameterError)
268                         {
269                             throw new InvalidOperationException("Invalid handle");
270                         }
271                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
272                     }
273                 }
274                 catch (Exception e)
275                 {
276                     Log.Error(Globals.LogTag, "Exception on ConnectAsync\n" + e);
277                     task.SetException(e);
278                 }
279             }, null);
280
281             return task.Task;
282         }
283
284         /// <summary>
285         /// Connects the access point with the WPS asynchronously.
286         /// </summary>
287         /// <since_tizen> 3 </since_tizen>
288         /// <param name="info">A WpsInfo instance which is type of WpsPbcInfo or WpsPinInfo.</param>
289         /// <returns>A task indicating whether the ConnectWps method is done or not.</returns>
290         /// <remarks>
291         /// This method must be called from MainThread.
292         /// </remarks>
293         /// <feature>http://tizen.org/feature/network.wifi</feature>
294         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
295         /// <privilege>http://tizen.org/privilege/network.get</privilege>
296         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
297         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
298         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
299         /// <exception cref="ArgumentNullException">Thrown when the WpsPinInfo object is constructed with a null pin.</exception>
300         /// <exception cref="ArgumentOutOfRangeException">Thrown when the WpsPinInfo object is constructed with a pin which is an empty string or more than 7 characters.</exception>
301         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
302         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
303         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
304         /// <exception cref="NowInProgressException">Thrown when the Wi-Fi connection is now in progress.</exception>
305         /// <exception cref="TimeoutException">Thrown when the timeout of WPS connection is expired.</exception>
306         public Task ConnectWpsAsync(WpsInfo info)
307         {
308             Log.Info(Globals.LogTag, "ConnectWpsAsync");
309             if (_disposed)
310             {
311                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
312             }
313
314             TaskCompletionSource<bool> wpsTask = new TaskCompletionSource<bool>();
315             _wpsTaskMap[_apHandle] = wpsTask;
316
317             IntPtr id;
318             lock (_callback_map)
319             {
320                 id = (IntPtr)_requestId++;
321                 _callback_map[id] = (error, key) =>
322                 {
323                     Log.Info(Globals.LogTag, "ConnectWpsAsync done");
324                     if (error != (int)WiFiError.None)
325                     {
326                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
327                         wpsTask.SetException(WiFiErrorFactory.GetException(error, "Error occurs during WiFi connecting"));
328                         Log.Info(Globals.LogTag, "Remove task for ConnectWpsAsync");
329                         _wpsTaskMap.Remove(_apHandle);
330                     }
331                     else
332                     {
333                         wpsTask.SetResult(true);
334                         Log.Info(Globals.LogTag, "Remove task for ConnectWpsAsync");
335                         _wpsTaskMap.Remove(_apHandle);
336                     }
337                     lock (_callback_map)
338                     {
339                         _callback_map.Remove(key);
340                     }
341                 };
342             }
343
344             context.Post((x) =>
345             {
346                 try
347                 {
348                     int ret = -1;
349                     if (info.GetType() == typeof(WpsPbcInfo))
350                     {
351                         Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPb");
352                         ret = Interop.WiFi.ConnectByWpsPbc(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
353                     }
354                     else if (info.GetType() == typeof(WpsPinInfo))
355                     {
356                         WpsPinInfo pinInfo = (WpsPinInfo)info;
357                         if (pinInfo.GetWpsPin() == null)
358                         {
359                             throw new ArgumentNullException("Wps pin should not be null");
360                         }
361
362                         if (pinInfo.GetWpsPin().Length == 0 || pinInfo.GetWpsPin().Length > 8)
363                         {
364                             throw new ArgumentOutOfRangeException("Wps pin should not be empty or more than 7 characters");
365                         }
366
367                         Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPin");
368                         ret = Interop.WiFi.ConnectByWpsPin(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, pinInfo.GetWpsPin(), _callback_map[id], id);
369                     }
370
371                     if (ret != (int)WiFiError.None)
372                     {
373                         Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
374                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
375                     }
376                 }
377                 catch (Exception e)
378                 {
379                     Log.Error(Globals.LogTag, "Exception on ConnectWpsAsync\n" + e);
380                     wpsTask.SetException(e);
381                     Log.Info(Globals.LogTag, "Remove task for ConnectWpsAsync");
382                     _wpsTaskMap.Remove(_apHandle);
383                 }
384             }, null);
385
386             return wpsTask.Task;
387         }
388
389         /// <summary>
390         /// Connects the access point with WPS without SSID asynchronously.
391         /// </summary>
392         /// <since_tizen> 3 </since_tizen>
393         /// <param name="info">A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo.</param>
394         /// <returns>A task which contains Connected access point information.</returns>
395         /// <remarks>
396         /// If WpsPinInfo is used, its object has to be constructed with a pin which must be 4 or 8 characters long. \n
397         /// This method must be called from MainThread.
398         /// </remarks>
399         /// <feature>http://tizen.org/feature/network.wifi</feature>
400         /// <privilege>http://tizen.org/privilege/network.set</privilege>
401         /// <privilege>http://tizen.org/privilege/network.get</privilege>
402         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
403         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
404         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
405         /// <exception cref="ArgumentNullException">Thrown when the WpsPinInfo object is constructed with a null pin.</exception>
406         /// <exception cref="ArgumentOutOfRangeException">Thrown when the WpsPinInfo object is constructed with a pin which is not of 4 or 8 characters long.</exception>
407         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
408         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
409         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
410         /// <exception cref="NowInProgressException">Thrown when the Wi-Fi connection is now in progress.</exception>
411         /// <exception cref="TimeoutException">Thrown when the timeout of WPS connection is expired.</exception>
412         public static Task<WiFiAP> ConnectWpsWithoutSsidAsync(WpsInfo info)
413         {
414             Log.Info(Globals.LogTag, "ConnectWpsWithoutSsidAsync");
415             wpsWithoutSsidTask = new TaskCompletionSource<WiFiAP>();
416             IntPtr id;
417             lock (s_callbackMap)
418             {
419                 id = (IntPtr)s_requestId++;
420                 s_callbackMap[id] = (error, key) =>
421                 {
422                     Log.Info(Globals.LogTag, "ConnectWpsWithoutSsidAsync done");
423                     if (error != (int)WiFiError.None)
424                     {
425                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
426                         wpsWithoutSsidTask.SetException(WiFiErrorFactory.GetException(error, "Error occurs during WiFi connecting"));
427                         wpsWithoutSsidTask = null;
428                         Log.Info(Globals.LogTag, "task is null");
429                     }
430                     else
431                     {
432                         WiFiAP ap = WiFiManagerImpl.Instance.GetConnectedAP();
433                         wpsWithoutSsidTask.SetResult(ap);
434                         wpsWithoutSsidTask = null;
435                         Log.Info(Globals.LogTag, "task is null");
436                     }
437                     lock (s_callbackMap)
438                     {
439                         s_callbackMap.Remove(key);
440                     }
441                 };
442             }
443
444             s_context.Post((x) =>
445             {
446                 try
447                 {
448                     int ret = -1;
449                     if (info.GetType() == typeof(WpsPbcInfo))
450                     {
451                         Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPbcWithoutSsid");
452                         ret = Interop.WiFi.ConnectByWpsPbcWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), s_callbackMap[id], id);
453                     }
454                     else if (info.GetType() == typeof(WpsPinInfo))
455                     {
456                         WpsPinInfo pinInfo = (WpsPinInfo)info;
457                         if (pinInfo.GetWpsPin() == null)
458                         {
459                             throw new ArgumentNullException("Wps pin should not be null");
460                         }
461
462                         if (pinInfo.GetWpsPin().Length != 4 && pinInfo.GetWpsPin().Length != 8)
463                         {
464                             throw new ArgumentOutOfRangeException("Wps pin should be of 4 or 8 characters long");
465                         }
466
467                         Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPinWithoutSsid");
468                         ret = Interop.WiFi.ConnectByWpsPinWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), pinInfo.GetWpsPin(), s_callbackMap[id], id);
469                     }
470
471                     if (ret != (int)WiFiError.None)
472                     {
473                         Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
474                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
475                     }
476                 }
477                 catch (Exception e)
478                 {
479                     Log.Error(Globals.LogTag, "Exception on ConnectWpsWithoutSsidAsync\n" + e);
480                     wpsWithoutSsidTask.SetException(e);
481                     wpsWithoutSsidTask = null;
482                     Log.Info(Globals.LogTag, "task is null");
483                 }
484             }, null);
485
486             return wpsWithoutSsidTask.Task;
487         }
488
489         /// <summary>
490         /// Stops ongoing WPS provisioning
491         /// </summary>
492         /// <since_tizen> 5 </since_tizen>
493         /// <feature>http://tizen.org/feature/network.wifi</feature>
494         /// <privilege>http://tizen.org/privilege/network.set</privilege>
495         /// <privilege>http://tizen.org/privilege/network.get</privilege>
496         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
497         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
498         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
499         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
500         public static void CancelWps()
501         {
502             Log.Debug(Globals.LogTag, "CancelWps");
503             int ret = Interop.WiFi.CancelWps(WiFiManagerImpl.Instance.GetSafeHandle());
504             if (ret != (int)WiFiError.None)
505             {
506                 Log.Error(Globals.LogTag, "Failed to cancel Wps, Error - " + (WiFiError)ret);
507                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
508             }
509
510             // Cancel awaiting tasks
511             if (wpsWithoutSsidTask != null)
512             {
513                 Log.Info(Globals.LogTag, "Cancel ConnectWpsWithoutSsidAsync()");
514                 wpsWithoutSsidTask.SetCanceled();
515             }
516             foreach (var item in _wpsTaskMap)
517             {
518                 Log.Info(Globals.LogTag, "Cancel ConnectWpsAsync() by " + item.Key.GetHashCode());
519                 item.Value.SetCanceled();
520             }
521             _wpsTaskMap.Clear();
522
523         }
524
525
526         /// <summary>
527         /// Disconnects the access point asynchronously.
528         /// </summary>
529         /// <since_tizen> 3 </since_tizen>
530         /// <returns> A task indicating whether the disconnect method is done or not.</returns>
531         /// <remarks>
532         /// This method must be called from MainThread.
533         /// </remarks>
534         /// <feature>http://tizen.org/feature/network.wifi</feature>
535         /// <privilege>http://tizen.org/privilege/network.set</privilege>
536         /// <privilege>http://tizen.org/privilege/network.get</privilege>
537         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
538         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
539         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
540         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
541         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
542         public Task DisconnectAsync()
543         {
544             Log.Debug(Globals.LogTag, "DisconnectAsync");
545             if (_disposed)
546             {
547                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
548             }
549             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
550             IntPtr id;
551             lock (_callback_map)
552             {
553                 id = (IntPtr)_requestId++;
554                 _callback_map[id] = (error, key) =>
555                 {
556                     Log.Info(Globals.LogTag, "DisconnectAsync done");
557                     if (error != (int)WiFiError.None)
558                     {
559                         Log.Error(Globals.LogTag, "Error occurs during WiFi disconnecting, " + (WiFiError)error);
560                         task.SetException(new InvalidOperationException("Error occurs during WiFi disconnecting, " + (WiFiError)error));
561                     }
562                     else
563                     {
564                         task.SetResult(true);
565                     }
566                     lock (_callback_map)
567                     {
568                         _callback_map.Remove(key);
569                     }
570                 };
571             }
572
573             context.Post((x) =>
574             {
575                 Log.Info(Globals.LogTag, "Interop.WiFi.Disconnect");
576                 try
577                 {
578                     int ret = Interop.WiFi.Disconnect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
579                     if (ret != (int)WiFiError.None)
580                     {
581                         Log.Error(Globals.LogTag, "Failed to disconnect wifi, Error - " + (WiFiError)ret);
582                         if (ret == (int)WiFiError.InvalidParameterError)
583                         {
584                             throw new InvalidOperationException("Invalid handle");
585                         }
586                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
587                     }
588                 }
589                 catch (Exception e)
590                 {
591                     Log.Error(Globals.LogTag, "Exception on Disconnect\n" + e);
592                     task.SetException(e);
593                 }
594             }, null);
595
596             return task.Task;
597         }
598
599         /// <summary>
600         /// Deletes the information of a stored access point and disconnects it when the AP is connected.
601         /// If an AP is connected, then the connection information will be stored. This information is used when a connection to that AP is established automatically.
602         /// </summary>
603         /// <since_tizen> 3 </since_tizen>
604         /// <feature>http://tizen.org/feature/network.wifi</feature>
605         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
606         /// <privilege>http://tizen.org/privilege/network.get</privilege>
607         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
608         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
609         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
610         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
611         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
612         public void ForgetAP()
613         {
614             Log.Debug(Globals.LogTag, "ForgetAP");
615             if (_disposed)
616             {
617                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
618             }
619             int ret = Interop.WiFi.RemoveAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle);
620             if (ret != (int)WiFiError.None)
621             {
622                 Log.Error(Globals.LogTag, "Failed to forget AP, Error - " + (WiFiError)ret);
623                 if (ret == (int)WiFiError.InvalidParameterError)
624                 {
625                     throw new InvalidOperationException("Invalid handle");
626                 }
627                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
628             }
629         }
630
631         /// <summary>
632         /// Deletes the information of a stored access point and disconnects it when the AP is connected asyncronously.
633         /// If an AP is connected, then the connection information will be stored. This information is used when a connection to that AP is established automatically.
634         /// </summary>
635         /// <returns> A task indicating whether the disconnect method is done or not.</returns>
636         /// <remarks>
637         /// This method must be called from MainThread.
638         /// </remarks>
639         /// <since_tizen> 5 </since_tizen>
640         /// <feature>http://tizen.org/feature/network.wifi</feature>
641         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
642         /// <privilege>http://tizen.org/privilege/network.get</privilege>
643         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
644         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
645         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
646         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
647         public Task ForgetAPAsync()
648         {
649             Log.Debug(Globals.LogTag, "ForgetAPAsync");
650             if (_disposed)
651             {
652                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
653             }
654             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
655             IntPtr id;
656             lock (_callback_map)
657             {
658                 id = (IntPtr)_requestId++;
659                 _callback_map[id] = (error, key) =>
660                 {
661                     Log.Info(Globals.LogTag, "ForgetAPAsync done");
662                     if (error != (int)WiFiError.None)
663                     {
664                         Log.Error(Globals.LogTag, "Error occurs during WiFi disconnecting, " + (WiFiError)error);
665                         task.SetException(new InvalidOperationException("Error occurs during WiFi disconnecting, " + (WiFiError)error));
666                     }
667                     else
668                     {
669                         task.SetResult(true);
670                     }
671                     lock (_callback_map)
672                     {
673                         _callback_map.Remove(key);
674                     }
675                 };
676             }
677
678             context.Post((x) =>
679             {
680                 Log.Info(Globals.LogTag, "Interop.WiFi.ForgetAP");
681                 try
682                 {
683                     int ret = Interop.WiFi.ForgetAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
684                     if (ret != (int)WiFiError.None)
685                     {
686                         Log.Error(Globals.LogTag, "Failed to forget wifi, Error - " + (WiFiError)ret);
687                         if (ret == (int)WiFiError.InvalidParameterError)
688                         {
689                             throw new InvalidOperationException("Invalid handle");
690                         }
691                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
692                     }
693                 }
694                 catch (Exception e)
695                 {
696                     Log.Error(Globals.LogTag, "Exception on ForgetAPAsync\n" + e);
697                     task.SetException(e);
698                 }
699             }, null);
700
701             return task.Task;
702         }
703
704         /// <summary>
705         /// Update the information of a stored access point.
706         /// When a AP information is changed, the change will not be applied until this method is called.
707         /// </summary>
708         /// <since_tizen> 5 </since_tizen>
709         /// <feature>http://tizen.org/feature/network.wifi</feature>
710         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
711         /// <privilege>http://tizen.org/privilege/network.get</privilege>
712         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
713         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
714         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
715         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
716         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
717         public void Update()
718         {
719             Log.Debug(Globals.LogTag, "Update");
720             if (_disposed)
721             {
722                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
723             }
724             int ret = Interop.WiFi.UpdateAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle);
725             if (ret != (int)WiFiError.None)
726             {
727                 Log.Error(Globals.LogTag, "Failed to update AP, Error - " + (WiFiError)ret);
728                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
729             }
730         }
731   }
732
733     /// <summary>
734     /// An abstract class which is used to represent the WPS information of the access point.
735     /// </summary>
736     /// <since_tizen> 3 </since_tizen>
737     public abstract class WpsInfo
738     {
739     }
740
741     /// <summary>
742     /// A class which is used to represent WPS PBC information of the access point.
743     /// </summary>
744     /// <since_tizen> 3 </since_tizen>
745     public class WpsPbcInfo : WpsInfo
746     {
747     }
748
749     /// <summary>
750     /// A class which is used to represent WPS PIN information of the access point.
751     /// </summary>
752     /// <since_tizen> 3 </since_tizen>
753     public class WpsPinInfo : WpsInfo
754     {
755         private string _pin;
756
757         private WpsPinInfo()
758         {
759         }
760
761         /// <summary>
762         /// A public constructor which instantiates WpsPinInfo class with the given pin.
763         /// </summary>
764         /// <since_tizen> 3 </since_tizen>
765         /// <param name="pin">WPS Pin of the access point.</param>
766         /// <remarks>
767         /// Pin should not be null or empty. It should be of less than 8 characters.
768         /// </remarks>
769         public WpsPinInfo(string pin)
770         {
771             _pin = pin;
772         }
773
774         internal string GetWpsPin()
775         {
776             return _pin;
777         }
778     }
779 }