11d37d35d8d284545f985da3b2ca904e9e50ff2e
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.WiFi / Tizen.Network.WiFi / WiFiAP.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.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 = -1;
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="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
190         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
191         public void Refresh()
192         {
193             Log.Debug(Globals.LogTag, "Refresh");
194             if (_disposed)
195             {
196                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
197             }
198             int ret = Interop.WiFi.AP.Refresh(_apHandle);
199             if (ret != (int)WiFiError.None)
200             {
201                 Log.Error(Globals.LogTag, "Failed to refresh ap handle, Error - " + (WiFiError)ret);
202                 WiFiErrorFactory.ThrowWiFiException(ret, _apHandle, "http://tizen.org/privilege/network.get");
203             }
204         }
205
206         /// <summary>
207         /// Connects the access point asynchronously.
208         /// </summary>
209         /// <since_tizen> 3 </since_tizen>
210         /// <returns> A task indicating whether the connect method is done or not.</returns>
211         /// <remarks>
212         /// This method must be called from MainThread.
213         /// </remarks>
214         /// <feature>http://tizen.org/feature/network.wifi</feature>
215         /// <privilege>http://tizen.org/privilege/network.set</privilege>
216         /// <privilege>http://tizen.org/privilege/network.get</privilege>
217         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
218         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
219         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
220         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
221         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
222         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
223         public Task ConnectAsync()
224         {
225             Log.Info(Globals.LogTag, "ConnectAsync HashCode: " + _apHandle.GetHashCode());
226             if (_disposed)
227             {
228                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
229             }
230             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
231             IntPtr id;
232             lock (_callback_map)
233             {
234                 id = (IntPtr)_requestId++;
235                 _callback_map[id] = (error, key) =>
236                 {
237                     Log.Info(Globals.LogTag, "ConnectAsync done " + (WiFiError)error);
238                     if (error != (int)WiFiError.None)
239                     {
240                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
241                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
242                     }
243                     else
244                     {
245                         task.SetResult(true);
246                     }
247                     lock (_callback_map)
248                     {
249                         _callback_map.Remove(key);
250                     }
251                 };
252             }
253
254             context.Post((x) =>
255             {
256                 Log.Info(Globals.LogTag, "Interop.WiFi.Connect");
257                 try
258                 {
259                     int ret = Interop.WiFi.Connect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
260                     if (ret != (int)WiFiError.None)
261                     {
262                         Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
263                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
264                     }
265                 }
266                 catch (Exception e)
267                 {
268                     Log.Error(Globals.LogTag, "Exception on ConnectAsync\n" + e.ToString());
269                     task.SetException(e);
270                 }
271             }, null);
272
273             return task.Task;
274         }
275
276         /// <summary>
277         /// Connects the access point with the WPS asynchronously.
278         /// </summary>
279         /// <since_tizen> 3 </since_tizen>
280         /// <param name="info">A WpsInfo instance which is type of WpsPbcInfo or WpsPinInfo.</param>
281         /// <returns>A task indicating whether the ConnectWps method is done or not.</returns>
282         /// <remarks>
283         /// This method must be called from MainThread.
284         /// </remarks>
285         /// <feature>http://tizen.org/feature/network.wifi</feature>
286         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
287         /// <privilege>http://tizen.org/privilege/network.get</privilege>
288         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
289         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
290         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
291         /// <exception cref="ArgumentNullException">Thrown when the WpsPinInfo object is constructed with a null pin.</exception>
292         /// <exception cref="ArgumentOutOfRangeException">Thrown when the WpsPinInfo object is constructed with a pin which is an empty string or more than 7 characters.</exception>
293         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
294         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
295         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
296         public Task ConnectWpsAsync(WpsInfo info)
297         {
298             Log.Info(Globals.LogTag, "ConnectWpsAsync");
299             if (_disposed)
300             {
301                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
302             }
303
304             TaskCompletionSource<bool> wpsTask = new TaskCompletionSource<bool>();
305             _wpsTaskMap[_apHandle] = wpsTask;
306
307             IntPtr id;
308             lock (_callback_map)
309             {
310                 id = (IntPtr)_requestId++;
311                 _callback_map[id] = (error, key) =>
312                 {
313                     Log.Info(Globals.LogTag, "ConnectWpsAsync done");
314                     if (error != (int)WiFiError.None)
315                     {
316                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
317                         wpsTask.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
318                         Log.Info(Globals.LogTag, "Remove task for ConnectWpsAsync");
319                         _wpsTaskMap.Remove(_apHandle);
320                     }
321                     else
322                     {
323                         wpsTask.SetResult(true);
324                         Log.Info(Globals.LogTag, "Remove task for ConnectWpsAsync");
325                         _wpsTaskMap.Remove(_apHandle);
326                     }
327                     lock (_callback_map)
328                     {
329                         _callback_map.Remove(key);
330                     }
331                 };
332             }
333
334             context.Post((x) =>
335             {
336                 try
337                 {
338                     int ret = -1;
339                     if (info.GetType() == typeof(WpsPbcInfo))
340                     {
341                         Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPb");
342                         ret = Interop.WiFi.ConnectByWpsPbc(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
343                     }
344                     else if (info.GetType() == typeof(WpsPinInfo))
345                     {
346                         WpsPinInfo pinInfo = (WpsPinInfo)info;
347                         if (pinInfo.GetWpsPin() == null)
348                         {
349                             throw new ArgumentNullException("Wps pin should not be null");
350                         }
351
352                         if (pinInfo.GetWpsPin().Length == 0 || pinInfo.GetWpsPin().Length > 8)
353                         {
354                             throw new ArgumentOutOfRangeException("Wps pin should not be empty or more than 7 characters");
355                         }
356
357                         Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPin");
358                         ret = Interop.WiFi.ConnectByWpsPin(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, pinInfo.GetWpsPin(), _callback_map[id], id);
359                     }
360
361                     if (ret != (int)WiFiError.None)
362                     {
363                         Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
364                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
365                     }
366                 }
367                 catch (Exception e)
368                 {
369                     Log.Error(Globals.LogTag, "Exception on ConnectWpsAsync\n" + e.ToString());
370                     wpsTask.SetException(e);
371                     Log.Info(Globals.LogTag, "Remove task for ConnectWpsAsync");
372                     _wpsTaskMap.Remove(_apHandle);
373                 }
374             }, null);
375
376             return wpsTask.Task;
377         }
378
379         /// <summary>
380         /// Connects the access point with WPS without SSID asynchronously.
381         /// </summary>
382         /// <since_tizen> 3 </since_tizen>
383         /// <param name="info">A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo.</param>
384         /// <returns>A task which contains Connected access point information.</returns>
385         /// <remarks>
386         /// If WpsPinInfo is used, its object has to be constructed with a pin which must be 4 or 8 characters long. \n
387         /// This method must be called from MainThread.
388         /// </remarks>
389         /// <feature>http://tizen.org/feature/network.wifi</feature>
390         /// <privilege>http://tizen.org/privilege/network.set</privilege>
391         /// <privilege>http://tizen.org/privilege/network.get</privilege>
392         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
393         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
394         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
395         /// <exception cref="ArgumentNullException">Thrown when the WpsPinInfo object is constructed with a null pin.</exception>
396         /// <exception cref="ArgumentOutOfRangeException">Thrown when the WpsPinInfo object is constructed with a pin which is not of 4 or 8 characters long.</exception>
397         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
398         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
399         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
400         public static Task<WiFiAP> ConnectWpsWithoutSsidAsync(WpsInfo info)
401         {
402             Log.Info(Globals.LogTag, "ConnectWpsWithoutSsidAsync");
403             wpsWithoutSsidTask = new TaskCompletionSource<WiFiAP>();
404             IntPtr id;
405             lock (s_callbackMap)
406             {
407                 id = (IntPtr)s_requestId++;
408                 s_callbackMap[id] = (error, key) =>
409                 {
410                     Log.Info(Globals.LogTag, "ConnectWpsWithoutSsidAsync done");
411                     if (error != (int)WiFiError.None)
412                     {
413                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
414                         wpsWithoutSsidTask.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
415                         wpsWithoutSsidTask = null;
416                         Log.Info(Globals.LogTag, "task is null");
417                     }
418                     else
419                     {
420                         WiFiAP ap = WiFiManagerImpl.Instance.GetConnectedAP();
421                         wpsWithoutSsidTask.SetResult(ap);
422                         wpsWithoutSsidTask = null;
423                         Log.Info(Globals.LogTag, "task is null");
424                     }
425                     lock (s_callbackMap)
426                     {
427                         s_callbackMap.Remove(key);
428                     }
429                 };
430             }
431
432             s_context.Post((x) =>
433             {
434                 try
435                 {
436                     int ret = -1;
437                     if (info.GetType() == typeof(WpsPbcInfo))
438                     {
439                         Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPbcWithoutSsid");
440                         ret = Interop.WiFi.ConnectByWpsPbcWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), s_callbackMap[id], id);
441                     }
442                     else if (info.GetType() == typeof(WpsPinInfo))
443                     {
444                         WpsPinInfo pinInfo = (WpsPinInfo)info;
445                         if (pinInfo.GetWpsPin() == null)
446                         {
447                             throw new ArgumentNullException("Wps pin should not be null");
448                         }
449
450                         if (pinInfo.GetWpsPin().Length != 4 && pinInfo.GetWpsPin().Length != 8)
451                         {
452                             throw new ArgumentOutOfRangeException("Wps pin should be of 4 or 8 characters long");
453                         }
454
455                         Log.Info(Globals.LogTag, "Interop.WiFi.ConnectByWpsPinWithoutSsid");
456                         ret = Interop.WiFi.ConnectByWpsPinWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), pinInfo.GetWpsPin(), s_callbackMap[id], id);
457                     }
458
459                     if (ret != (int)WiFiError.None)
460                     {
461                         Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
462                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
463                     }
464                 }
465                 catch (Exception e)
466                 {
467                     Log.Error(Globals.LogTag, "Exception on ConnectWpsWithoutSsidAsync\n" + e.ToString());
468                     wpsWithoutSsidTask.SetException(e);
469                     wpsWithoutSsidTask = null;
470                     Log.Info(Globals.LogTag, "task is null");
471                 }
472             }, null);
473
474             return wpsWithoutSsidTask.Task;
475         }
476
477         /// <summary>
478         /// Stops ongoing WPS provisioning
479         /// </summary>
480         /// <since_tizen> 5 </since_tizen>
481         /// <feature>http://tizen.org/feature/network.wifi</feature>
482         /// <privilege>http://tizen.org/privilege/network.set</privilege>
483         /// <privilege>http://tizen.org/privilege/network.get</privilege>
484         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
485         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
486         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
487         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
488         public static void CancelWps()
489         {
490             Log.Debug(Globals.LogTag, "CancelWps");
491             int ret = Interop.WiFi.CancelWps(WiFiManagerImpl.Instance.GetSafeHandle());
492             if (ret != (int)WiFiError.None)
493             {
494                 Log.Error(Globals.LogTag, "Failed to cancel Wps, Error - " + (WiFiError)ret);
495                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
496             }
497
498             // Cancel awaiting tasks
499             if (wpsWithoutSsidTask != null)
500             {
501                 Log.Info(Globals.LogTag, "Cancel ConnectWpsWithoutSsidAsync()");
502                 wpsWithoutSsidTask.SetCanceled();
503             }
504             foreach (var item in _wpsTaskMap)
505             {
506                 Log.Info(Globals.LogTag, "Cancel ConnectWpsAsync() by " + item.Key.GetHashCode());
507                 item.Value.SetCanceled();
508             }
509             _wpsTaskMap.Clear();
510
511         }
512
513
514         /// <summary>
515         /// Disconnects the access point asynchronously.
516         /// </summary>
517         /// <since_tizen> 3 </since_tizen>
518         /// <returns> A task indicating whether the disconnect method is done or not.</returns>
519         /// <remarks>
520         /// This method must be called from MainThread.
521         /// </remarks>
522         /// <feature>http://tizen.org/feature/network.wifi</feature>
523         /// <privilege>http://tizen.org/privilege/network.set</privilege>
524         /// <privilege>http://tizen.org/privilege/network.get</privilege>
525         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
526         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
527         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
528         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
529         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
530         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
531         public Task DisconnectAsync()
532         {
533             Log.Debug(Globals.LogTag, "DisconnectAsync");
534             if (_disposed)
535             {
536                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
537             }
538             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
539             IntPtr id;
540             lock (_callback_map)
541             {
542                 id = (IntPtr)_requestId++;
543                 _callback_map[id] = (error, key) =>
544                 {
545                     Log.Info(Globals.LogTag, "DisconnectAsync done");
546                     if (error != (int)WiFiError.None)
547                     {
548                         Log.Error(Globals.LogTag, "Error occurs during WiFi disconnecting, " + (WiFiError)error);
549                         task.SetException(new InvalidOperationException("Error occurs during WiFi disconnecting, " + (WiFiError)error));
550                     }
551                     else
552                     {
553                         task.SetResult(true);
554                     }
555                     lock (_callback_map)
556                     {
557                         _callback_map.Remove(key);
558                     }
559                 };
560             }
561
562             context.Post((x) =>
563             {
564                 Log.Info(Globals.LogTag, "Interop.WiFi.Disconnect");
565                 try
566                 {
567                     int ret = Interop.WiFi.Disconnect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
568                     if (ret != (int)WiFiError.None)
569                     {
570                         Log.Error(Globals.LogTag, "Failed to disconnect wifi, Error - " + (WiFiError)ret);
571                         WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
572                     }
573                 }
574                 catch (Exception e)
575                 {
576                     Log.Error(Globals.LogTag, "Exception on Disconnect\n" + e.ToString());
577                     task.SetException(e);
578                 }
579             }, null);
580
581             return task.Task;
582         }
583
584         /// <summary>
585         /// Deletes the information of a stored access point and disconnects it when the AP is connected.
586         /// 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.
587         /// </summary>
588         /// <since_tizen> 3 </since_tizen>
589         /// <feature>http://tizen.org/feature/network.wifi</feature>
590         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
591         /// <privilege>http://tizen.org/privilege/network.get</privilege>
592         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
593         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
594         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
595         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
596         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
597         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
598         public void ForgetAP()
599         {
600             Log.Debug(Globals.LogTag, "ForgetAP");
601             if (_disposed)
602             {
603                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
604             }
605             int ret = Interop.WiFi.RemoveAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle);
606             if (ret != (int)WiFiError.None)
607             {
608                 Log.Error(Globals.LogTag, "Failed to forget AP, Error - " + (WiFiError)ret);
609                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
610             }
611         }
612
613         /// <summary>
614         /// Update the information of a stored access point.
615         /// When a AP information is changed, the change will not be applied until this method is called.
616         /// </summary>
617         /// <since_tizen> 5 </since_tizen>
618         /// <feature>http://tizen.org/feature/network.wifi</feature>
619         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
620         /// <privilege>http://tizen.org/privilege/network.get</privilege>
621         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
622         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
623         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
624         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
625         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
626         public void Update()
627         {
628             Log.Debug(Globals.LogTag, "Update");
629             if (_disposed)
630             {
631                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
632             }
633             int ret = Interop.WiFi.UpdateAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle);
634             if (ret != (int)WiFiError.None)
635             {
636                 Log.Error(Globals.LogTag, "Failed to update AP, Error - " + (WiFiError)ret);
637                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
638             }
639         }
640    }
641
642     /// <summary>
643     /// An abstract class which is used to represent the WPS information of the access point.
644     /// </summary>
645     /// <since_tizen> 3 </since_tizen>
646     public abstract class WpsInfo
647     {
648     }
649
650     /// <summary>
651     /// A class which is used to represent WPS PBC information of the access point.
652     /// </summary>
653     /// <since_tizen> 3 </since_tizen>
654     public class WpsPbcInfo : WpsInfo
655     {
656     }
657
658     /// <summary>
659     /// A class which is used to represent WPS PIN information of the access point.
660     /// </summary>
661     /// <since_tizen> 3 </since_tizen>
662     public class WpsPinInfo : WpsInfo
663     {
664         private string _pin;
665
666         private WpsPinInfo()
667         {
668         }
669
670         /// <summary>
671         /// A public constructor which instantiates WpsPinInfo class with the given pin.
672         /// </summary>
673         /// <since_tizen> 3 </since_tizen>
674         /// <param name="pin">WPS Pin of the access point.</param>
675         /// <remarks>
676         /// Pin should not be null or empty. It should be of less than 8 characters.
677         /// </remarks>
678         public WpsPinInfo(string pin)
679         {
680             _pin = pin;
681         }
682
683         internal string GetWpsPin()
684         {
685             return _pin;
686         }
687     }
688 }