[Connection][WiFi] Use TizenSynchronizationContext.Post for asynchronous methods...
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Connection / Tizen.Network.Connection / ConnectionInternalManager.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Linq;
20 using System.Text;
21 using System.Threading;
22 using System.Threading.Tasks;
23 using System.Runtime.InteropServices;
24 using System.Collections;
25 using Tizen.Applications;
26
27 namespace Tizen.Network.Connection
28 {
29     class HandleHolder
30     {
31         private IntPtr Handle;
32         private int _tid;
33
34         public HandleHolder()
35         {
36             _tid = Thread.CurrentThread.ManagedThreadId;
37
38             Log.Info(Globals.LogTag, "PInvoke connection_create for Thread " + _tid);
39             int ret = Interop.Connection.Create(_tid, out Handle);
40             Log.Info(Globals.LogTag, "Handle: " + Handle);
41             if(ret != (int)ConnectionError.None)
42             {
43                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
44                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
45                 ConnectionErrorFactory.ThrowConnectionException(ret);
46             }
47         }
48
49         ~HandleHolder()
50         {
51             Destroy();
52         }
53
54         internal IntPtr GetHandle()
55         {
56             Log.Debug(Globals.LogTag, "handleholder handle = " + Handle);
57             return Handle;
58         }
59
60         private void Destroy()
61         {
62
63             Log.Info(Globals.LogTag, "PInvoke connection_destroy for Thread " + _tid);
64             Interop.Connection.Destroy(_tid, Handle);
65             if (Handle != IntPtr.Zero)
66             {
67                 Handle = IntPtr.Zero;
68             }
69         }
70     }
71
72     internal class ConnectionInternalManager
73     {
74         private static readonly Lazy<ConnectionInternalManager> s_instance =
75             new Lazy<ConnectionInternalManager>(() => new ConnectionInternalManager());
76
77         private EventHandler<ConnectionTypeEventArgs> _ConnectionTypeChanged = null;
78         private EventHandler<AddressEventArgs> _IPAddressChanged = null;
79         private EventHandler<EthernetCableStateEventArgs> _EthernetCableStateChanged = null;
80         private EventHandler<AddressEventArgs> _ProxyAddressChanged = null;
81
82         private Interop.Connection.ConnectionAddressChangedCallback _connectionAddressChangedCallback;
83         private Interop.Connection.ConnectionTypeChangedCallback _connectionTypeChangedCallback;
84         private Interop.Connection.ConnectionAddressChangedCallback _proxyAddressChangedCallback;
85         private Interop.Connection.EthernetCableStateChangedCallback _ethernetCableStateChangedCallback;
86
87         private TizenSynchronizationContext context = new TizenSynchronizationContext();
88
89         internal static ConnectionInternalManager Instance
90         {
91             get
92             {
93                 return s_instance.Value;
94             }
95         }
96
97         private static ThreadLocal<HandleHolder> s_threadName = new ThreadLocal<HandleHolder>(() =>
98         {
99             Log.Info(Globals.LogTag, "In threadlocal delegate");
100             return new HandleHolder();
101         });
102
103         private ConnectionInternalManager()
104         {
105             Log.Info(Globals.LogTag, "ConnectionInternalManager constructor");
106         }
107
108         ~ConnectionInternalManager()
109         {
110             UnregisterEvents();
111         }
112
113         internal IntPtr GetHandle()
114         {
115             return s_threadName.Value.GetHandle();
116         }
117
118         internal event EventHandler<ConnectionTypeEventArgs> ConnectionTypeChanged
119         {
120             add
121             {
122                 context.Post((x) =>
123                 {
124                     if (_ConnectionTypeChanged == null)
125                     {
126                         ConnectionTypeChangedStart();
127                     }
128                     _ConnectionTypeChanged += value;
129                 }, null);
130             }
131             remove
132             {
133                 context.Post((x) =>
134                 {
135                     _ConnectionTypeChanged -= value;
136                     if (_ConnectionTypeChanged == null)
137                     {
138                         ConnectionTypeChangedStop();
139                     }
140                 }, null);
141             }
142         }
143
144         private void ConnectionTypeChangedStart()
145         {
146             Log.Info(Globals.LogTag, "Register ConnectionTypeChanged");
147             _connectionTypeChangedCallback = (ConnectionType type, IntPtr user_data) =>
148             {
149                 if (_ConnectionTypeChanged != null)
150                 {
151                     _ConnectionTypeChanged(null, new ConnectionTypeEventArgs(type));
152                 }
153             };
154
155             int ret = Interop.Connection.SetTypeChangedCallback(GetHandle(), _connectionTypeChangedCallback, IntPtr.Zero);
156             if ((ConnectionError)ret != ConnectionError.None)
157             {
158                 Log.Error(Globals.LogTag, "It failed to register connection type changed callback, " + (ConnectionError)ret);
159                 ConnectionErrorFactory.ThrowConnectionException(ret);
160             }
161         }
162
163         private void ConnectionTypeChangedStop()
164         {
165             Log.Info(Globals.LogTag, "Unregister ConnectionTypeChanged");
166             int ret = Interop.Connection.UnsetTypeChangedCallback(GetHandle());
167             if ((ConnectionError)ret != ConnectionError.None)
168             {
169                 Log.Error(Globals.LogTag, "It failed to unregister connection type changed callback, " + (ConnectionError)ret);
170                 ConnectionErrorFactory.ThrowConnectionException(ret);
171             }
172         }
173
174         internal event EventHandler<EthernetCableStateEventArgs> EthernetCableStateChanged
175         {
176             add
177             {
178                 context.Post((x) =>
179                 {
180                     if (_EthernetCableStateChanged == null)
181                     {
182                         EthernetCableStateChangedStart();
183                     }
184                     _EthernetCableStateChanged += value;
185                 }, null);
186             }
187             remove
188             {
189                 context.Post((x) =>
190                 {
191                     _EthernetCableStateChanged -= value;
192                     if (_EthernetCableStateChanged == null)
193                     {
194                         EthernetCableStateChangedStop();
195                     }
196                 }, null);
197             }
198         }
199
200         private void EthernetCableStateChangedStart()
201         {
202             Log.Info(Globals.LogTag, "Register EthernetCableStateChanged");
203             _ethernetCableStateChangedCallback = (EthernetCableState state, IntPtr user_data) =>
204             {
205                 if (_EthernetCableStateChanged != null)
206                 {
207                     _EthernetCableStateChanged(null, new EthernetCableStateEventArgs(state));
208                 }
209             };
210             int ret = Interop.Connection.SetEthernetCableStateChagedCallback(GetHandle(),
211                     _ethernetCableStateChangedCallback, IntPtr.Zero);
212             if ((ConnectionError)ret != ConnectionError.None)
213             {
214                 Log.Error(Globals.LogTag,
215                         "It failed to register ethernet cable state changed callback, " +
216                         (ConnectionError)ret);
217                 ConnectionErrorFactory.ThrowConnectionException(ret);
218             }
219         }
220
221         private void EthernetCableStateChangedStop()
222         {
223             Log.Info(Globals.LogTag, "Unregister EthernetCableStateChanged");
224             int ret = Interop.Connection.UnsetEthernetCableStateChagedCallback(GetHandle());
225             if ((ConnectionError)ret != ConnectionError.None)
226             {
227                 Log.Error(Globals.LogTag,
228                         "It failed to unregister ethernet cable state changed callback, " + 
229                         (ConnectionError)ret);
230                 ConnectionErrorFactory.ThrowConnectionException(ret);
231             }
232         }
233
234         internal event EventHandler<AddressEventArgs> IPAddressChanged
235         {
236             add
237             {
238                 context.Post((x) =>
239                 {
240                     if (_IPAddressChanged == null)
241                     {
242                         IPAddressChangedStart();
243                     }
244                     _IPAddressChanged += value;
245                 }, null);
246             }
247
248             remove
249             {
250                 context.Post((x) =>
251                 {
252                     _IPAddressChanged -= value;
253                     if (_IPAddressChanged == null)
254                     {
255                         IPAddressChangedStop();
256                     }
257                 }, null);
258             }
259         }
260
261         private void IPAddressChangedStart()
262         {
263             Log.Info(Globals.LogTag, "Register IPAddressChanged");
264             _connectionAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
265             {
266                 if (_IPAddressChanged != null)
267                 {
268                     string ipv4 = Marshal.PtrToStringAnsi(IPv4);
269                     string ipv6 = Marshal.PtrToStringAnsi(IPv6);
270
271                     if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
272                     {
273                         _IPAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
274                     }
275                 }
276             };
277
278             int ret = Interop.Connection.SetIPAddressChangedCallback(GetHandle(), _connectionAddressChangedCallback, IntPtr.Zero);
279             if ((ConnectionError)ret != ConnectionError.None)
280             {
281                 Log.Error(Globals.LogTag, "It failed to register callback for changing IP address, " + (ConnectionError)ret);
282             }
283         }
284
285         private void IPAddressChangedStop()
286         {
287             Log.Info(Globals.LogTag, "Unregister IPAddressChanged");
288             int ret = Interop.Connection.UnsetIPAddressChangedCallback(GetHandle());
289             if ((ConnectionError)ret != ConnectionError.None)
290             {
291                 Log.Error(Globals.LogTag, "It failed to unregister callback for changing IP address, " + (ConnectionError)ret);
292             }
293         }
294
295         internal event EventHandler<AddressEventArgs> ProxyAddressChanged
296         {
297             add
298             {
299                 context.Post((x) =>
300                 {
301                     if (_ProxyAddressChanged == null)
302                     {
303                         ProxyAddressChangedStart();
304                     }
305                     _ProxyAddressChanged += value;
306                 }, null);
307             }
308             remove
309             {
310                 context.Post((x) =>
311                 {
312                     _ProxyAddressChanged -= value;
313                     if (_ProxyAddressChanged == null)
314                     {
315                         ProxyAddressChangedStop();
316                     }
317                 }, null);
318             }
319         }
320
321         private void ProxyAddressChangedStart()
322         {
323             Log.Info(Globals.LogTag, "Register ProxyAddressChanged");
324             _proxyAddressChangedCallback = (IntPtr IPv4, IntPtr IPv6, IntPtr UserData) =>
325             {
326                 if (_ProxyAddressChanged != null)
327                 {
328                     string ipv4 = Marshal.PtrToStringAnsi(IPv4);
329                     string ipv6 = Marshal.PtrToStringAnsi(IPv6);
330
331                     if ((string.IsNullOrEmpty(ipv4) == false) || (string.IsNullOrEmpty(ipv6) == false))
332                     {
333                         _ProxyAddressChanged(null, new AddressEventArgs(ipv4, ipv6));
334                     }
335                 }
336             };
337
338             int ret = Interop.Connection.SetProxyAddressChangedCallback(GetHandle(), _proxyAddressChangedCallback, IntPtr.Zero);
339             if ((ConnectionError)ret != ConnectionError.None)
340             {
341                 Log.Error(Globals.LogTag, "It failed to register callback for changing proxy address, " + (ConnectionError)ret);
342             }
343         }
344
345         private void ProxyAddressChangedStop()
346         {
347             Log.Info(Globals.LogTag, "Unregister ProxyAddressChanged");
348             int ret = Interop.Connection.UnsetProxyAddressChangedCallback(GetHandle());
349             if ((ConnectionError)ret != ConnectionError.None)
350             {
351                 Log.Error(Globals.LogTag, "It failed to unregister callback for changing proxy address, " + (ConnectionError)ret);
352             }
353         }
354
355         private void UnregisterEvents()
356         {
357             if (_ConnectionTypeChanged != null)
358             {
359                 ConnectionTypeChangedStop();
360             }
361             if (_IPAddressChanged != null)
362             {
363                 IPAddressChangedStop();
364             }
365             if (_EthernetCableStateChanged != null)
366             {
367                 EthernetCableStateChangedStop();
368             }
369             if (_ProxyAddressChanged != null)
370             {
371                 ProxyAddressChangedStop();
372             }
373         }
374
375         internal int GetProfileIterator(ProfileListType type, out IntPtr iterator)
376         {
377             return Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
378         }
379
380         internal bool HasNext(IntPtr iterator)
381         {
382             return Interop.Connection.HasNextProfileIterator(iterator);
383         }
384
385         internal int NextProfileIterator(IntPtr iterator, out IntPtr profileHandle)
386         {
387             return Interop.Connection.GetNextProfileIterator(iterator, out profileHandle);
388         }
389
390         internal int DestoryProfileIterator(IntPtr iterator)
391         {
392             return Interop.Connection.DestroyProfileIterator(iterator);
393         }
394
395         internal System.Net.IPAddress GetIPAddress(AddressFamily family)
396         {
397             Log.Info(Globals.LogTag, "GetIPAddress " + family);
398             IntPtr ip;
399             int ret = Interop.Connection.GetIPAddress(GetHandle(), (int)family, out ip);
400             if ((ConnectionError)ret != ConnectionError.None)
401             {
402                 Log.Error(Globals.LogTag, "It failed to get IP address, " + (ConnectionError)ret);
403                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
404                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
405                 ConnectionErrorFactory.ThrowConnectionException(ret);
406             }
407
408             string result = Marshal.PtrToStringAnsi(ip);
409             Interop.Libc.Free(ip);
410             Log.Info(Globals.LogTag, "IPAddress " + result + " (" + result.Length + ")");
411             if (result.Length == 0)
412             {
413                 if (family == AddressFamily.IPv4)
414                     return System.Net.IPAddress.Parse("0.0.0.0");
415                 else
416                     return System.Net.IPAddress.Parse("::");
417             }
418             return System.Net.IPAddress.Parse(result);
419         }
420
421         internal IEnumerable<System.Net.IPAddress> GetAllIPv6Addresses(ConnectionType type)
422         {
423             Log.Debug(Globals.LogTag, "GetAllIPv6Addresses");
424             List<System.Net.IPAddress> ipList = new List<System.Net.IPAddress>();
425             Interop.Connection.IPv6AddressCallback callback = (IntPtr ipv6Address, IntPtr userData) =>
426             {
427                 if (ipv6Address != IntPtr.Zero)
428                 {
429                     string ipv6 = Marshal.PtrToStringAnsi(ipv6Address);
430                     if (ipv6.Length == 0)
431                         ipList.Add(System.Net.IPAddress.Parse("::"));
432                     else
433                         ipList.Add(System.Net.IPAddress.Parse(ipv6));
434                     return true;
435                 }
436                 return false;
437             };
438
439             int ret = Interop.Connection.GetAllIPv6Addresses(GetHandle(), (int)type, callback, IntPtr.Zero);
440             if (ret != (int)ConnectionError.None)
441             {
442                 Log.Error(Globals.LogTag, "Failed to get all IPv6 addresses, Error - " + (ConnectionError)ret);
443                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
444                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
445                 ConnectionErrorFactory.ThrowConnectionException(ret);
446             }
447
448             return ipList;
449         }
450
451         internal string GetProxy(AddressFamily family)
452         {
453             Log.Debug(Globals.LogTag, "GetProxy " + family);
454             IntPtr ip;
455             int ret = Interop.Connection.GetProxy(GetHandle(), (int)family, out ip);
456             if ((ConnectionError)ret != ConnectionError.None)
457             {
458                 Log.Error(Globals.LogTag, "It failed to get proxy, " + (ConnectionError)ret);
459                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
460                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
461                 ConnectionErrorFactory.ThrowConnectionException(ret);
462             }
463
464             string result = Marshal.PtrToStringAnsi(ip);
465             Interop.Libc.Free(ip);
466             return result;
467         }
468
469         internal string GetMacAddress(ConnectionType type)
470         {
471             Log.Info(Globals.LogTag, "GetMacAddress " + type);
472             IntPtr mac;
473             int ret = Interop.Connection.GetMacAddress(GetHandle(), (int)type, out mac);
474             if ((ConnectionError)ret != ConnectionError.None)
475             {
476                 Log.Error(Globals.LogTag, "It failed to get mac address, " + (ConnectionError)ret);
477                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.ethernet");
478                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
479                 ConnectionErrorFactory.ThrowConnectionException(ret);
480             }
481
482             string result = Marshal.PtrToStringAnsi(mac);
483             Interop.Libc.Free(mac);
484             return result;
485         }
486
487         internal long GetStatistics(ConnectionType connectionType, StatisticsType statisticsType)
488         {
489             Log.Debug(Globals.LogTag, "GetStatistics " + connectionType + ", " + statisticsType);
490             long size;
491             int ret = Interop.Connection.GetStatistics(GetHandle(), (int)connectionType,
492                     (int)statisticsType, out size);
493             if ((ConnectionError)ret != ConnectionError.None)
494             {
495                 Log.Error(Globals.LogTag, "It failed to get statistics, " + (ConnectionError)ret);
496                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.telephony");
497                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
498                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
499                 ConnectionErrorFactory.ThrowConnectionException(ret);
500             }
501             return size;
502         }
503
504         internal void ResetStatistics(ConnectionType connectionType, StatisticsType statisticsType)
505         {
506             Log.Debug(Globals.LogTag, "ResetStatistics " + connectionType + ", " + statisticsType);
507             int ret = Interop.Connection.ResetStatistics(GetHandle(), (int)connectionType,
508                     (int)statisticsType);
509             if ((ConnectionError)ret != ConnectionError.None)
510             {
511                 Log.Error(Globals.LogTag, "It failed to reset statistics, " + (ConnectionError)ret);
512                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.telephony");
513                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.set)");
514                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
515                 ConnectionErrorFactory.ThrowConnectionException(ret);
516             }
517         }
518
519         internal void AddRoute(AddressFamily family, string interfaceName, System.Net.IPAddress address, System.Net.IPAddress gateway)
520         {
521             if (interfaceName != null && address != null && gateway != null)
522             {
523                 Log.Debug(Globals.LogTag, "AddRoute " + family + ", " + interfaceName + ", " + address + ", " + gateway);
524                 int ret = Interop.Connection.AddRoute(GetHandle(), family, interfaceName, address.ToString(), gateway.ToString());
525                 if ((ConnectionError)ret != ConnectionError.None)
526                 {
527                     Log.Error(Globals.LogTag, "It failed to add route to the routing table, " + (ConnectionError)ret);
528                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
529                     ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.set)");
530                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
531                     ConnectionErrorFactory.ThrowConnectionException(ret);
532                 }
533             }
534
535             else
536             {
537                 throw new ArgumentNullException("Arguments are null");
538             }
539         }
540
541         internal void RemoveRoute(AddressFamily family, string interfaceName, System.Net.IPAddress address, System.Net.IPAddress gateway)
542         {
543             if (interfaceName != null && address != null && gateway != null)
544             {
545                 Log.Debug(Globals.LogTag, "RemoveRoute " + family + ", " + interfaceName + ", " + address + ", " + gateway);
546                 int ret = Interop.Connection.RemoveRoute(GetHandle(), family, interfaceName, address.ToString(), gateway.ToString());
547                 if ((ConnectionError)ret != ConnectionError.None)
548                 {
549                     Log.Error(Globals.LogTag, "It failed to remove route from the routing table, " + (ConnectionError)ret);
550                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
551                     ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.set)");
552                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
553                     ConnectionErrorFactory.ThrowConnectionException(ret);
554                 }
555             }
556
557             else
558             {
559                 throw new ArgumentNullException("Arguments are null");
560             }
561         }
562
563         internal ConnectionType ConnectionType
564         {
565             get
566             {
567                 Log.Info(Globals.LogTag, "get ConnectionType");
568                 int type = 0;
569                 int ret = Interop.Connection.GetType(GetHandle(), out type);
570                 if ((ConnectionError)ret != ConnectionError.None)
571                 {
572                     Log.Error(Globals.LogTag, "It failed to get connection type, " + (ConnectionError)ret);
573                     ConnectionErrorFactory.ThrowConnectionException(ret);
574                 }
575                 return (ConnectionType)type;
576             }
577         }
578
579         internal CellularState CellularState
580         {
581             get
582             {
583                 Log.Info(Globals.LogTag, "get CellularState");
584                 int type = 0;
585                 int ret = Interop.Connection.GetCellularState(GetHandle(), out type);
586                 if ((ConnectionError)ret != ConnectionError.None)
587                 {
588                     Log.Error(Globals.LogTag, "It failed to get cellular state, " + (ConnectionError)ret);
589                     ConnectionErrorFactory.ThrowConnectionException(ret);
590                 }
591                 return (CellularState)type;
592             }
593         }
594
595         internal ConnectionState WiFiState
596         {
597             get
598             {
599                 Log.Info(Globals.LogTag, "get WiFiState");
600                 int type = 0;
601                 int ret = Interop.Connection.GetWiFiState(GetHandle(), out type);
602                 if ((ConnectionError)ret != ConnectionError.None)
603                 {
604                     Log.Error(Globals.LogTag, "It failed to get wifi state, " + (ConnectionError)ret);
605                     ConnectionErrorFactory.ThrowConnectionException(ret);
606                 }
607                 return (ConnectionState)type;
608             }
609         }
610
611         internal ConnectionState BluetoothState
612         {
613             get
614             {
615                 Log.Info(Globals.LogTag, "get BluetoothState");
616                 int type = 0;
617                 int ret = Interop.Connection.GetBtState(GetHandle(), out type);
618                 if ((ConnectionError)ret != ConnectionError.None)
619                 {
620                     Log.Error(Globals.LogTag, "It failed to get bluetooth state, " + (ConnectionError)ret);
621                     ConnectionErrorFactory.ThrowConnectionException(ret);
622                 }
623                 return (ConnectionState)type;
624             }
625         }
626
627         internal ConnectionState EthernetState
628         {
629             get
630             {
631                 Log.Info(Globals.LogTag, "get ConnectionType");
632                 int type = 0;
633                 int ret = Interop.Connection.GetEthernetState(GetHandle(), out type);
634                 if ((ConnectionError)ret != ConnectionError.None)
635                 {
636                     Log.Error(Globals.LogTag, "It failed to get ethernet state, " + (ConnectionError)ret);
637                     ConnectionErrorFactory.ThrowConnectionException(ret);
638                 }
639                 return (ConnectionState)type;
640             }
641         }
642
643         internal EthernetCableState EthernetCableState
644         {
645             get
646             {
647                 Log.Info(Globals.LogTag, "get EthernetCableState");
648                 int type = 0;
649                 int ret = Interop.Connection.GetEthernetCableState(GetHandle(), out type);
650                 if ((ConnectionError)ret != ConnectionError.None)
651                 {
652                     Log.Error(Globals.LogTag, "It failed to get ethernet cable state, " + (ConnectionError)ret);
653                     ConnectionErrorFactory.ThrowConnectionException(ret);
654                 }
655                 return (EthernetCableState)type;
656             }
657         }
658
659         internal IntPtr CreateCellularProfile(ConnectionProfileType type, string keyword)
660         {
661             Log.Debug(Globals.LogTag, "CreateCellularProfile, " + type + ", " + keyword);
662             if (keyword != null)
663             {
664                 IntPtr handle = IntPtr.Zero;
665                 int ret = Interop.ConnectionProfile.Create((int)type, keyword, out handle);
666                 if ((ConnectionError)ret != ConnectionError.None)
667                 {
668                     Log.Error(Globals.LogTag, "It failed to Create profile, " + (ConnectionError)ret);
669                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.telephony");
670                     ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
671                     ConnectionErrorFactory.ThrowConnectionException(ret);
672                 }
673
674                 return handle;
675             }
676
677             else
678             {
679                 throw new ArgumentNullException("Keyword is null");
680             }
681         }
682
683         internal void AddCellularProfile(CellularProfile profile)
684         {
685
686             Log.Debug(Globals.LogTag, "AddCellularProfile");
687             if (profile != null)
688             {
689                 if (profile.Type == ConnectionProfileType.Cellular)
690                 {
691                     int ret = Interop.Connection.AddProfile(GetHandle(), profile.ProfileHandle);
692                     if ((ConnectionError)ret != ConnectionError.None)
693                     {
694                         Log.Error(Globals.LogTag, "Failed to add cellular profile, " + (ConnectionError)ret);
695                         ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony");
696                         ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.profile)");
697                         ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
698                         ConnectionErrorFactory.ThrowConnectionException(ret);
699                     }
700                 }
701
702                 else
703                 {
704                     throw new ArgumentException("Profile type is not cellular");
705                 }
706             }
707
708             else
709             {
710                 throw new ArgumentNullException("Profile is null");
711             }
712         }
713
714         internal void RemoveProfile(ConnectionProfile profile)
715         {
716             Log.Debug(Globals.LogTag, "RemoveProfile");
717             if (profile != null)
718             {
719                 int ret = Interop.Connection.RemoveProfile(GetHandle(), profile.ProfileHandle);
720                 if ((ConnectionError)ret != ConnectionError.None)
721                 {
722                     Log.Error(Globals.LogTag, "It failed to remove profile, " + (ConnectionError)ret);
723                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.telephony");
724                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
725                     ConnectionErrorFactory.ThrowConnectionException(ret);
726                 }
727             }
728
729             else
730             {
731                 throw new ArgumentNullException("Profile is null");
732             }
733         }
734
735         internal void UpdateProfile(ConnectionProfile profile)
736         {
737             Log.Info(Globals.LogTag, "UpdateProfile");
738             if (profile != null)
739             {
740                 int ret = Interop.Connection.UpdateProfile(GetHandle(), profile.ProfileHandle);
741                 if ((ConnectionError)ret != ConnectionError.None)
742                 {
743                     Log.Error(Globals.LogTag, "It failed to update profile, " + (ConnectionError)ret);
744                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.ethernet");
745                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
746                     ConnectionErrorFactory.ThrowConnectionException(ret);
747                 }
748             }
749
750             else
751             {
752                 throw new ArgumentNullException("Profile is null");
753             }
754         }
755
756         internal ConnectionProfile GetCurrentProfile()
757         {
758             Log.Info(Globals.LogTag, "GetCurrentProfile");
759             IntPtr ProfileHandle;
760             int ret = Interop.Connection.GetCurrentProfile(GetHandle(), out ProfileHandle);
761             if ((ConnectionError)ret != ConnectionError.None)
762             {
763                 if ((ConnectionError)ret == ConnectionError.NoConnection)
764                 {
765                     Log.Error(Globals.LogTag, "No connection " + (ConnectionError)ret);
766                     return null;
767                 }
768                 else
769                 {
770                     Log.Error(Globals.LogTag, "It failed to get current profile, " + (ConnectionError)ret);
771                     ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
772                     ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
773                     ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
774                     ConnectionErrorFactory.ThrowConnectionException(ret);
775                 }
776             }
777
778             ConnectionProfile Profile = new ConnectionProfile(ProfileHandle);
779             return Profile;
780         }
781
782         internal ConnectionProfile GetDefaultCellularProfile(CellularServiceType type)
783         {
784             Log.Debug(Globals.LogTag, "GetDefaultCellularProfile");
785             IntPtr ProfileHandle;
786             int ret = Interop.Connection.GetDefaultCellularServiceProfile(GetHandle(), (int)type, out ProfileHandle);
787             if ((ConnectionError)ret != ConnectionError.None)
788             {
789                 Log.Error(Globals.LogTag, "Error: " + ret);
790                 Log.Error(Globals.LogTag, "It failed to get default cellular profile, " + (ConnectionError)ret);
791                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony");
792                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
793                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
794                 ConnectionErrorFactory.ThrowConnectionException(ret);
795             }
796
797             CellularProfile Profile = new CellularProfile(ProfileHandle);
798             return Profile;
799         }
800
801         internal Task SetDefaultCellularProfile(CellularServiceType type, ConnectionProfile profile)
802         {
803             Log.Info(Globals.LogTag, "SetDefaultCellularProfile");
804             if (profile != null)
805             {
806                 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
807                 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
808                 {
809                     Log.Info(Globals.LogTag, "SetDefaultCellularProfile done " + profile.Name);
810                     if (Result != ConnectionError.None)
811                     {
812                         Log.Error(Globals.LogTag, "Error occurs during set default cellular profile, " + Result);
813                         task.SetException(new InvalidOperationException("Error occurs during set default cellular profile, " + Result));
814                     }
815                     else
816                     {
817                         task.SetResult(true);
818                     }
819                 };
820
821                 context.Post((x) =>
822                 {
823                     Log.Info(Globals.LogTag, "Interop.Connection.SetDefaultCellularServiceProfileAsync " + profile.Name);
824                     int ret = Interop.Connection.SetDefaultCellularServiceProfileAsync(GetHandle(), (int)type, profile.ProfileHandle, Callback, (IntPtr)0);
825                     if ((ConnectionError)ret != ConnectionError.None)
826                     {
827                         Log.Error(Globals.LogTag, "It failed to set default cellular profile, " + (ConnectionError)ret);
828                         ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony");
829                         ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
830                         ConnectionErrorFactory.ThrowConnectionException(ret);
831                     }
832                 }, null);
833
834                 return task.Task;
835             }
836             else
837             {
838                 throw new ArgumentNullException("Profile is null");
839             }
840         }
841
842
843         internal Task<IEnumerable<ConnectionProfile>> GetProfileListAsync(ProfileListType type)
844         {
845             Log.Debug(Globals.LogTag, "GetProfileListAsync");
846             var task = new TaskCompletionSource<IEnumerable<ConnectionProfile>>();
847
848             List<ConnectionProfile> Result = new List<ConnectionProfile>();
849             IntPtr iterator;
850             int ret = Interop.Connection.GetProfileIterator(GetHandle(), (int)type, out iterator);
851             if ((ConnectionError)ret != ConnectionError.None)
852             {
853                 Log.Error(Globals.LogTag, "It failed to get profile iterator, " + (ConnectionError)ret);
854                 ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth " + "http://tizen.org/feature/network.ethernet");
855                 ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.get)");
856                 ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero), "Connection Handle may have been disposed or released");
857                 ConnectionErrorFactory.ThrowConnectionException(ret);
858             }
859
860             while (Interop.Connection.HasNextProfileIterator(iterator))
861             {
862                 IntPtr nextH;
863                 IntPtr profileH;
864                 Interop.Connection.GetNextProfileIterator(iterator, out nextH);
865                 Interop.ConnectionProfile.Clone(out profileH, nextH);
866
867                 int profileType;
868                 Interop.ConnectionProfile.GetType(profileH, out profileType);
869
870                 if ((ConnectionProfileType)profileType == ConnectionProfileType.WiFi)
871                 {
872                     WiFiProfile cur = new WiFiProfile(profileH);
873                     Result.Add(cur);
874                 }
875                 else if ((ConnectionProfileType)profileType == ConnectionProfileType.Cellular)
876                 {
877                     CellularProfile cur = new CellularProfile(profileH);
878                     Result.Add(cur);
879                 }
880                 else {
881                     ConnectionProfile cur = new ConnectionProfile(profileH);
882                     Result.Add(cur);
883                 }
884             }
885             Interop.Connection.DestroyProfileIterator(iterator);
886             task.SetResult(Result);
887             return task.Task;
888         }
889
890         internal Task OpenProfileAsync(ConnectionProfile profile)
891         {
892             Log.Info(Globals.LogTag, "OpenProfileAsync");
893             if (profile != null)
894             {
895                 Log.Debug(Globals.LogTag, "OpenProfileAsync " + profile.Name);
896                 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
897                 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
898                 {
899                     Log.Info(Globals.LogTag, "OpenProfileAsync done " + profile.Name);
900                     if (Result != ConnectionError.None)
901                     {
902                         Log.Error(Globals.LogTag, "Error occurs during connecting profile, " + Result);
903                         task.SetException(new InvalidOperationException("Error occurs during connecting profile, " + Result));
904                     }
905                     else
906                     {
907                         task.SetResult(true);
908                     }
909                 };
910
911                 context.Post((x) =>
912                 {
913                     Log.Info(Globals.LogTag, "Interop.Connection.OpenProfile " + profile.Name);
914                     int ret = Interop.Connection.OpenProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
915                     if ((ConnectionError)ret != ConnectionError.None)
916                     {
917                         Log.Error(Globals.LogTag, "It failed to connect profile, " + (ConnectionError)ret);
918                         ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth");
919                         ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
920                         ConnectionErrorFactory.ThrowConnectionException(ret);
921                     }
922                 }, null);
923
924                 return task.Task;
925             }
926
927             else
928             {
929                 throw new ArgumentNullException("Profile is null");
930             }
931         }
932
933         internal Task CloseProfileAsync(ConnectionProfile profile)
934         {
935             Log.Info(Globals.LogTag, "CloseProfileAsync");
936             if (profile != null)
937             {
938                 Log.Info(Globals.LogTag, "CloseProfileAsync " + profile.Name);
939                 TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
940                 Interop.Connection.ConnectionCallback Callback = (ConnectionError Result, IntPtr Data) =>
941                 {
942                     Log.Info(Globals.LogTag, "CloseProfileAsync done " + profile.Name);
943                     if (Result != ConnectionError.None)
944                     {
945                         Log.Error(Globals.LogTag, "Error occurs during disconnecting profile, " + Result);
946                         task.SetException(new InvalidOperationException("Error occurs during disconnecting profile, " + Result));
947                     }
948                     else
949                     {
950                         task.SetResult(true);
951                     }
952                 };
953
954                 context.Post((x) =>
955                 {
956                     Log.Info(Globals.LogTag, "Interop.Connection.CloseProfile " + profile.Name);
957                     int ret = Interop.Connection.CloseProfile(GetHandle(), profile.ProfileHandle, Callback, IntPtr.Zero);
958                     if ((ConnectionError)ret != ConnectionError.None)
959                     {
960                         Log.Error(Globals.LogTag, "It failed to disconnect profile, " + (ConnectionError)ret);
961                         ConnectionErrorFactory.CheckFeatureUnsupportedException(ret, "http://tizen.org/feature/network.telephony " + "http://tizen.org/feature/network.wifi " + "http://tizen.org/feature/network.tethering.bluetooth");
962                         ConnectionErrorFactory.CheckPermissionDeniedException(ret, "(http://tizen.org/privilege/network.set)");
963                         ConnectionErrorFactory.CheckHandleNullException(ret, (GetHandle() == IntPtr.Zero || profile.ProfileHandle == IntPtr.Zero), "Connection or Profile Handle may have been disposed or released");
964                         ConnectionErrorFactory.ThrowConnectionException(ret);
965                     }
966                 }, null);
967
968                 return task.Task;
969             }
970
971             else
972             {
973                 throw new ArgumentNullException("Profile is null");
974             }
975         }
976     }
977 }