Merge "Changed DllIport entry point for new system-settings API for callback."
[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 System.ComponentModel;
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         /// <summary>
40         /// The network information of the access point (AP).
41         /// </summary>
42         /// <since_tizen> 3 </since_tizen>
43         /// <value>The WiFiNetwork instance containing the network information of the AP.</value>
44         public WiFiNetwork NetworkInformation
45         {
46             get
47             {
48                 return _network;
49             }
50         }
51
52         /// <summary>
53         /// The security information of the access point (AP).
54         /// </summary>
55         /// <since_tizen> 3 </since_tizen>
56         /// <value>The WiFiSecurity instance containing security information of the AP.</value>
57         public WiFiSecurity SecurityInformation
58         {
59             get
60             {
61                 return _security;
62             }
63         }
64
65         internal WiFiAP(IntPtr handle)
66         {
67             Log.Debug(Globals.LogTag, "New WiFiAP. Handle: " + handle);
68             _apHandle = handle;
69             Initialize();
70         }
71
72         /// <summary>
73         /// Creates an object for the access point.
74         /// </summary>
75         /// <since_tizen> 3 </since_tizen>
76         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
77         /// <feature>http://tizen.org/feature/network.wifi</feature>
78         /// <privilege>http://tizen.org/privilege/network.get</privilege>
79         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
80         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
81         /// <exception cref="ArgumentNullException">Thrown when the ESSID is passed as null.</exception>
82         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
83         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
84         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
85         public WiFiAP(string essid)
86         {
87             Log.Debug(Globals.LogTag, "New WiFiAP. Essid: " + essid);
88             createHandle(essid, true);
89             Initialize();
90         }
91
92         /// <summary>
93         /// Creates an object for the hidden access point.
94         /// </summary>
95         /// <since_tizen> 3 </since_tizen>
96         /// <param name="essid">The Extended Service Set Identifier of the access point.</param>
97         /// <param name="hidden">The value to set a hidden AP.</param>
98         /// <feature>http://tizen.org/feature/network.wifi</feature>
99         /// <privilege>http://tizen.org/privilege/network.get</privilege>
100         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
101         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
102         /// <exception cref="ArgumentNullException">Thrown when the ESSID is passed as null.</exception>
103         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
104         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
105         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
106         public WiFiAP(string essid, bool hidden)
107         {
108             createHandle(essid, hidden);
109             Initialize();
110         }
111
112         /// <summary>
113         /// Destroy the WiFiAP object
114         /// </summary>
115         ~WiFiAP()
116         {
117             Dispose(false);
118         }
119
120         /// <summary>
121         /// A method to destroy the managed WiFiAP objects.
122         /// </summary>
123         /// <since_tizen> 3 </since_tizen>
124         public void Dispose()
125         {
126             Dispose(true);
127             GC.SuppressFinalize(this);
128         }
129
130         private void Dispose(bool disposing)
131         {
132             if (_disposed)
133                 return;
134
135             if (disposing)
136             {
137                 Interop.WiFi.AP.Destroy(_apHandle);
138                 _apHandle = IntPtr.Zero;
139             }
140             _disposed = true;
141         }
142
143         private void createHandle(string id, bool hidden)
144         {
145             int ret = -1;
146             if (id == null)
147             {
148                 throw new ArgumentNullException("Essid is null");
149             }
150
151             if (hidden)
152             {
153                 ret = Interop.WiFi.AP.CreateHiddenAP(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
154             }
155
156             else
157             {
158                 ret = Interop.WiFi.AP.Create(WiFiManagerImpl.Instance.GetSafeHandle(), id, out _apHandle);
159             }
160
161             if (ret != (int)WiFiError.None)
162             {
163                 Log.Error(Globals.LogTag, "Failed to create handle, Error - " + (WiFiError)ret);
164                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
165             }
166         }
167
168         private void Initialize()
169         {
170             Interop.WiFi.SafeWiFiAPHandle apHandle = new Interop.WiFi.SafeWiFiAPHandle(_apHandle);
171             _network = new WiFiNetwork(apHandle);
172             _security = new WiFiSecurity(apHandle);
173         }
174
175         /// <summary>
176         /// Refreshes the access point information.
177         /// </summary>
178         /// <since_tizen> 3 </since_tizen>
179         /// <feature>http://tizen.org/feature/network.wifi</feature>
180         /// <privilege>http://tizen.org/privilege/network.get</privilege>
181         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
182         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
183         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
184         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
185         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
186         public void Refresh()
187         {
188             Log.Debug(Globals.LogTag, "Refresh");
189             if (_disposed)
190             {
191                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
192             }
193             int ret = Interop.WiFi.AP.Refresh(_apHandle);
194             if (ret != (int)WiFiError.None)
195             {
196                 Log.Error(Globals.LogTag, "Failed to refresh ap handle, Error - " + (WiFiError)ret);
197                 WiFiErrorFactory.ThrowWiFiException(ret, _apHandle, "http://tizen.org/privilege/network.get");
198             }
199         }
200
201         /// <summary>
202         /// Connects the access point asynchronously.
203         /// </summary>
204         /// <since_tizen> 3 </since_tizen>
205         /// <returns> A task indicating whether the connect method is done or not.</returns>
206         /// <feature>http://tizen.org/feature/network.wifi</feature>
207         /// <privilege>http://tizen.org/privilege/network.set</privilege>
208         /// <privilege>http://tizen.org/privilege/network.get</privilege>
209         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
210         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
211         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
212         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
213         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
214         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
215         public Task ConnectAsync()
216         {
217             Log.Debug(Globals.LogTag, "ConnectAsync");
218             if (_disposed)
219             {
220                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
221             }
222             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
223             IntPtr id;
224             lock (_callback_map)
225             {
226                 id = (IntPtr)_requestId++;
227                 _callback_map[id] = (error, key) =>
228                 {
229                     Log.Debug(Globals.LogTag, "Connecting finished : " + (WiFiError)error);
230                     if (error != (int)WiFiError.None)
231                     {
232                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
233                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
234                     }
235                     else
236                     {
237                         task.SetResult(true);
238                     }
239                     lock (_callback_map)
240                     {
241                         _callback_map.Remove(key);
242                     }
243                 };
244             }
245
246             int ret = Interop.WiFi.Connect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
247             if (ret != (int)WiFiError.None)
248             {
249                 Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
250                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
251             }
252
253             return task.Task;
254         }
255
256         /// <summary>
257         /// Connects the access point with the WPS asynchronously.
258         /// </summary>
259         /// <since_tizen> 3 </since_tizen>
260         /// <param name="info">A WpsInfo instance which is type of WpsPbcInfo or WpsPinInfo.</param>
261         /// <returns>A task indicating whether the ConnectWps method is done or not.</returns>
262         /// <feature>http://tizen.org/feature/network.wifi</feature>
263         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
264         /// <privilege>http://tizen.org/privilege/network.get</privilege>
265         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
266         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
267         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
268         /// <exception cref="ArgumentNullException">Thrown when the WpsPinInfo object is constructed with a null pin.</exception>
269         /// <exception cref="ArgumentOutOfRangeException">Thrown when the WpsPinInfo object is constructed with a pin which is an empty string or more than 7 characters.</exception>
270         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
271         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
272         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
273         public Task ConnectWpsAsync(WpsInfo info)
274         {
275             Log.Debug(Globals.LogTag, "ConnectWpsAsync");
276             if (_disposed)
277             {
278                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
279             }
280             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
281             IntPtr id;
282             lock (_callback_map)
283             {
284                 id = (IntPtr)_requestId++;
285                 _callback_map[id] = (error, key) =>
286                 {
287                     Log.Debug(Globals.LogTag, "Connecting by WPS finished");
288                     if (error != (int)WiFiError.None)
289                     {
290                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
291                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
292                     }
293                     else
294                     {
295                         task.SetResult(true);
296                     }
297                     lock (_callback_map)
298                     {
299                         _callback_map.Remove(key);
300                     }
301                 };
302             }
303
304             int ret = -1;
305             if (info.GetType() == typeof(WpsPbcInfo))
306             {
307                 ret = Interop.WiFi.ConnectByWpsPbc(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
308             }
309
310             else if (info.GetType() == typeof(WpsPinInfo))
311             {
312                 WpsPinInfo pinInfo = (WpsPinInfo)info;
313                 if (pinInfo.GetWpsPin() == null)
314                 {
315                     throw new ArgumentNullException("Wps pin should not be null");
316                 }
317
318                 if (pinInfo.GetWpsPin().Length == 0 || pinInfo.GetWpsPin().Length > 8)
319                 {
320                     throw new ArgumentOutOfRangeException("Wps pin should not be empty or more than 7 characters");
321                 }
322
323                 ret = Interop.WiFi.ConnectByWpsPin(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, pinInfo.GetWpsPin(), _callback_map[id], id);
324             }
325
326             if (ret != (int)WiFiError.None)
327             {
328                 Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
329                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
330             }
331
332             return task.Task;
333         }
334
335         /// <summary>
336         /// Connects the access point with WPS without SSID asynchronously.
337         /// </summary>
338         /// <since_tizen> 3 </since_tizen>
339         /// <param name="info">A WpsInfo instance which is of type WpsPbcInfo or WpsPinInfo.</param>
340         /// <returns>A task which contains Connected access point information.</returns>
341         /// <remarks>
342         /// If WpsPinInfo is used, its object has to be constructed with a pin which must be 4 or 8 characters long.
343         /// </remarks>
344         /// <feature>http://tizen.org/feature/network.wifi</feature>
345         /// <privilege>http://tizen.org/privilege/network.set</privilege>
346         /// <privilege>http://tizen.org/privilege/network.get</privilege>
347         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
348         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
349         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
350         /// <exception cref="ArgumentNullException">Thrown when the WpsPinInfo object is constructed with a null pin.</exception>
351         /// <exception cref="ArgumentOutOfRangeException">Thrown when the WpsPinInfo object is constructed with a pin which is not of 4 or 8 characters long.</exception>
352         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
353         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
354         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
355         public static Task<WiFiAP> ConnectWpsWithoutSsidAsync(WpsInfo info)
356         {
357             TaskCompletionSource<WiFiAP> task = new TaskCompletionSource<WiFiAP>();
358             IntPtr id;
359             lock (s_callbackMap)
360             {
361                 id = (IntPtr)s_requestId++;
362                 s_callbackMap[id] = (error, key) =>
363                 {
364                     Log.Debug(Globals.LogTag, "Connecting by WPS finished");
365                     if (error != (int)WiFiError.None)
366                     {
367                         Log.Error(Globals.LogTag, "Error occurs during WiFi connecting, " + (WiFiError)error);
368                         task.SetException(new InvalidOperationException("Error occurs during WiFi connecting, " + (WiFiError)error));
369                     }
370                     else
371                     {
372                         WiFiAP ap = WiFiManagerImpl.Instance.GetConnectedAP();
373                         task.SetResult(ap);
374                     }
375                     lock (s_callbackMap)
376                     {
377                         s_callbackMap.Remove(key);
378                     }
379                 };
380             }
381
382             int ret = -1;
383             if (info.GetType() == typeof(WpsPbcInfo))
384             {
385                 ret = Interop.WiFi.ConnectByWpsPbcWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), s_callbackMap[id], id);   
386             }
387
388             else if (info.GetType() == typeof(WpsPinInfo))
389             {
390                 WpsPinInfo pinInfo = (WpsPinInfo)info;
391                 if (pinInfo.GetWpsPin() == null)
392                 {
393                     throw new ArgumentNullException("Wps pin should not be null");
394                 }
395
396                 if (pinInfo.GetWpsPin().Length != 4 && pinInfo.GetWpsPin().Length != 8)
397                 {
398                     throw new ArgumentOutOfRangeException("Wps pin should be of 4 or 8 characters long");
399                 }
400
401                 ret = Interop.WiFi.ConnectByWpsPinWithoutSsid(WiFiManagerImpl.Instance.GetSafeHandle(), pinInfo.GetWpsPin(), s_callbackMap[id], id);
402             }
403
404             if (ret != (int)WiFiError.None)
405             {
406                 Log.Error(Globals.LogTag, "Failed to connect wifi, Error - " + (WiFiError)ret);
407                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle());
408             }
409
410             return task.Task;
411         }
412
413         /// <summary>
414         /// Disconnects the access point asynchronously.
415         /// </summary>
416         /// <since_tizen> 3 </since_tizen>
417         /// <returns> A task indicating whether the disconnect method is done or not.</returns>
418         /// <feature>http://tizen.org/feature/network.wifi</feature>
419         /// <privilege>http://tizen.org/privilege/network.set</privilege>
420         /// <privilege>http://tizen.org/privilege/network.get</privilege>
421         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
422         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
423         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
424         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
425         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
426         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
427         public Task DisconnectAsync()
428         {
429             Log.Debug(Globals.LogTag, "DisconnectAsync");
430             if (_disposed)
431             {
432                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
433             }
434             TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
435             IntPtr id;
436             lock (_callback_map)
437             {
438                 id = (IntPtr)_requestId++;
439                 _callback_map[id] = (error, key) =>
440                 {
441                     Log.Debug(Globals.LogTag, "Disconnecting finished");
442                     if (error != (int)WiFiError.None)
443                     {
444                         Log.Error(Globals.LogTag, "Error occurs during WiFi disconnecting, " + (WiFiError)error);
445                         task.SetException(new InvalidOperationException("Error occurs during WiFi disconnecting, " + (WiFiError)error));
446                     }
447                     else
448                     {
449                         task.SetResult(true);
450                     }
451                     lock (_callback_map)
452                     {
453                         _callback_map.Remove(key);
454                     }
455                 };
456             }
457             int ret = Interop.WiFi.Disconnect(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle, _callback_map[id], id);
458             if (ret != (int)WiFiError.None)
459             {
460                 Log.Error(Globals.LogTag, "Failed to disconnect wifi, Error - " + (WiFiError)ret);
461                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
462             }
463             return task.Task;
464         }
465
466         /// <summary>
467         /// Deletes the information of a stored access point and disconnects it when the AP is connected.
468         /// 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.
469         /// </summary>
470         /// <since_tizen> 3 </since_tizen>
471         /// <feature>http://tizen.org/feature/network.wifi</feature>
472         /// <privilege>http://tizen.org/privilege/network.profile</privilege>
473         /// <privilege>http://tizen.org/privilege/network.get</privilege>
474         /// <exception cref="NotSupportedException">Thrown when the Wi-Fi is not supported.</exception>
475         /// <exception cref="UnauthorizedAccessException">Thrown when permission is denied.</exception>
476         /// <exception cref="ObjectDisposedException">Thrown when the object instance is disposed or released.</exception>
477         /// <exception cref="OutOfMemoryException">Thrown when the system is out of memory.</exception>
478         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
479         /// <exception cref="InvalidOperationException">Thrown when the method failed due to an invalid operation.</exception>
480         public void ForgetAP()
481         {
482             Log.Debug(Globals.LogTag, "ForgetAP");
483             if (_disposed)
484             {
485                 throw new ObjectDisposedException("Invalid AP instance (Object may have been disposed or released)");
486             }
487             int ret = Interop.WiFi.RemoveAP(WiFiManagerImpl.Instance.GetSafeHandle(), _apHandle);
488             if (ret != (int)WiFiError.None)
489             {
490                 Log.Error(Globals.LogTag, "Failed to forget AP, Error - " + (WiFiError)ret);
491                 WiFiErrorFactory.ThrowWiFiException(ret, WiFiManagerImpl.Instance.GetSafeHandle().DangerousGetHandle(), _apHandle);
492             }
493         }
494    }
495
496     /// <summary>
497     /// An abstract class which is used to represent the WPS information of the access point.
498     /// </summary>
499     /// <since_tizen> 3 </since_tizen>
500     public abstract class WpsInfo
501     {
502     }
503
504     /// <summary>
505     /// A class which is used to represent WPS PBC information of the access point.
506     /// </summary>
507     /// <since_tizen> 3 </since_tizen>
508     public class WpsPbcInfo : WpsInfo
509     {
510     }
511
512     /// <summary>
513     /// A class which is used to represent WPS PIN information of the access point.
514     /// </summary>
515     /// <since_tizen> 3 </since_tizen>
516     public class WpsPinInfo : WpsInfo
517     {
518         private string _pin;
519
520         private WpsPinInfo()
521         {
522         }
523
524         /// <summary>
525         /// A public constructor which instantiates WpsPinInfo class with the given pin.
526         /// </summary>
527         /// <since_tizen> 3 </since_tizen>
528         /// <param name="pin">WPS Pin of the access point.</param>
529         /// <remarks>
530         /// Pin should not be null or empty. It should be of less than 8 characters.
531         /// </remarks>
532         public WpsPinInfo(string pin)
533         {
534             _pin = pin;
535         }
536
537         internal string GetWpsPin()
538         {
539             return _pin;
540         }
541     }
542 }