34fba9fbc2173fbee00cec394b098316208abc41
[platform/core/csapi/tizenfx.git] / src / Tizen.System.Information / RuntimeInfo / RuntimeInformation.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.Tasks;
22 using System.ComponentModel;
23
24 namespace Tizen.System
25 {
26     /// <summary>
27     /// The RuntimeInformation provides functions to obtain runtime information of various system preferences.
28     /// </summary>
29     public static class RuntimeInformation
30     {
31         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_bluetoothEnabled;
32         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_wifiHotspotEnabled;
33         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_bluetoothTetheringEnabled;
34         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_usbTetheringEnabled;
35         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_packetDataEnabled;
36         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_dataRoamingEnabled;
37         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_vibrationEnabled;
38         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_audioJackConnected;
39         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_gpsStatusChanged;
40         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_batteryIsCharging;
41         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_tvOutConnected;
42         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_audioJackConnectorChanged;
43         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_chargerConnected;
44         private static event EventHandler<RuntimeKeyStatusChangedEventArgs> s_autoRotationEnabled;
45
46         private static readonly Interop.RuntimeInfo.RuntimeInformationChangedCallback s_runtimeInfoChangedCallback = (RuntimeInformationKey key, IntPtr userData) =>
47         {
48             RuntimeKeyStatusChangedEventArgs eventArgs = new RuntimeKeyStatusChangedEventArgs()
49             {
50                 Key = key
51             };
52             switch (key)
53             {
54                 case RuntimeInformationKey.Bluetooth:
55                     {
56                         s_bluetoothEnabled?.Invoke(null, eventArgs);
57                         break;
58                     };
59                 case RuntimeInformationKey.WifiHotspot:
60                     {
61                         s_wifiHotspotEnabled?.Invoke(null, eventArgs);
62                         break;
63                     };
64                 case RuntimeInformationKey.BluetoothTethering:
65                     {
66                         s_bluetoothTetheringEnabled?.Invoke(null, eventArgs);
67                         break;
68                     };
69                 case RuntimeInformationKey.UsbTethering:
70                     {
71                         s_usbTetheringEnabled?.Invoke(null, eventArgs);
72                         break;
73                     };
74                 case RuntimeInformationKey.PacketData:
75                     {
76                         s_packetDataEnabled?.Invoke(null, eventArgs);
77                         break;
78                     };
79                 case RuntimeInformationKey.DataRoaming:
80                     {
81                         s_dataRoamingEnabled?.Invoke(null, eventArgs);
82                         break;
83                     };
84                 case RuntimeInformationKey.Vibration:
85                     {
86                         s_vibrationEnabled?.Invoke(null, eventArgs);
87                         break;
88                     };
89                 case RuntimeInformationKey.AudioJack:
90                     {
91                         s_audioJackConnected?.Invoke(null, eventArgs);
92                         break;
93                     };
94                 case RuntimeInformationKey.Gps:
95                     {
96                         s_gpsStatusChanged?.Invoke(null, eventArgs);
97                         break;
98                     };
99                 case RuntimeInformationKey.BatteryIsCharging:
100                     {
101                         s_batteryIsCharging?.Invoke(null, eventArgs);
102                         break;
103                     };
104                 case RuntimeInformationKey.TvOut:
105                     {
106                         s_tvOutConnected?.Invoke(null, eventArgs);
107                         break;
108                     };
109                 case RuntimeInformationKey.AudioJackConnector:
110                     {
111                         s_audioJackConnectorChanged?.Invoke(null, eventArgs);
112                         break;
113                     };
114                 case RuntimeInformationKey.Charger:
115                     {
116                         s_chargerConnected?.Invoke(null, eventArgs);
117                         break;
118                     };
119                 case RuntimeInformationKey.AutoRotation:
120                     {
121                         s_autoRotationEnabled?.Invoke(null, eventArgs);
122                         break;
123                     };
124                 default:
125                     break;
126             };
127         };
128
129         internal static readonly Dictionary<RuntimeInformationKey, Type> s_keyDataTypeMapping = new Dictionary<RuntimeInformationKey, Type>
130         {
131             [RuntimeInformationKey.Bluetooth] = typeof(bool),
132             [RuntimeInformationKey.WifiHotspot] = typeof(bool),
133             [RuntimeInformationKey.BluetoothTethering] = typeof(bool),
134             [RuntimeInformationKey.UsbTethering] = typeof(bool),
135             [RuntimeInformationKey.PacketData] = typeof(bool),
136             [RuntimeInformationKey.DataRoaming] = typeof(bool),
137             [RuntimeInformationKey.Vibration] = typeof(bool),
138             [RuntimeInformationKey.AudioJack] = typeof(bool),
139             [RuntimeInformationKey.BatteryIsCharging] = typeof(bool),
140             [RuntimeInformationKey.TvOut] = typeof(bool),
141             [RuntimeInformationKey.Charger] = typeof(bool),
142             [RuntimeInformationKey.AutoRotation] = typeof(bool),
143             [RuntimeInformationKey.Gps] = typeof(int),
144             [RuntimeInformationKey.AudioJackConnector] = typeof(int)
145         };
146
147         internal static readonly Dictionary<RuntimeInformationKey, int> s_keyTVkeyMapping = new Dictionary<RuntimeInformationKey, int>\r
148         {\r
149             [RuntimeInformationKey.Bluetooth] = 5,
150             [RuntimeInformationKey.WifiHotspot] = 6,
151             [RuntimeInformationKey.BluetoothTethering] = 7,
152             [RuntimeInformationKey.UsbTethering] = 8,
153             [RuntimeInformationKey.PacketData] = 13,
154             [RuntimeInformationKey.DataRoaming] = 14,
155             [RuntimeInformationKey.Vibration] = 16,
156             [RuntimeInformationKey.AudioJack] = 20,
157             [RuntimeInformationKey.BatteryIsCharging] = 22,
158             [RuntimeInformationKey.TvOut] = 18,
159             [RuntimeInformationKey.Charger] = 26,
160             [RuntimeInformationKey.AutoRotation] = 28,
161             [RuntimeInformationKey.Gps] = 21,
162             [RuntimeInformationKey.AudioJackConnector] = 20\r
163         };
164
165         internal static int is_TV_product = -1;
166
167         [EditorBrowsable(EditorBrowsableState.Never)]
168         /// This function is for TV product. It will be removed
169         internal static RuntimeInformationKey ConvertKeyIfTvProduct(RuntimeInformationKey key)\r
170         {\r
171             bool is_key_existed = false;\r
172             string profile;\r
173             int key_TV = -1;
174
175             if (is_TV_product == -1)\r
176             {\r
177                 is_key_existed = SystemInfo.TryGetValue<string>("http://com.samsung/build_config/product_type", out profile);\r
178                 if (is_key_existed && String.Compare(profile, "TV") == 0)\r
179                 {\r
180                     is_TV_product = 1;\r
181                 }\r
182                 else\r
183                 {\r
184                     is_TV_product = 0;\r
185                 }\r
186             }\r
187 \r
188             if (is_TV_product == 0)\r
189             {\r
190                 return key;\r
191             }\r
192             else\r
193             {\r
194                 if (!s_keyTVkeyMapping.TryGetValue(key, out key_TV))\r
195                 {\r
196                     RuntimeInfoErrorFactory.ThrowException((int)RuntimeInfoError.InvalidParameter);\r
197                 }\r
198                 return (RuntimeInformationKey)key_TV;\r
199             }\r
200         }
201
202         [EditorBrowsable(EditorBrowsableState.Never)]
203         internal static object GetStatus(RuntimeInformationKey key)
204         {
205             Type value;
206             if (!s_keyDataTypeMapping.TryGetValue(key, out value))
207             {
208                 RuntimeInfoErrorFactory.ThrowException((int)RuntimeInfoError.InvalidParameter);
209             }
210
211             if (s_keyDataTypeMapping[key] == typeof(int))
212             {
213                 int status;
214                 int ret = Interop.RuntimeInfo.GetValue(ConvertKeyIfTvProduct(key), out status);
215                 if (ret != (int)RuntimeInfoError.None)
216                 {
217                     Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get value for key {0}", key.ToString());
218                     RuntimeInfoErrorFactory.ThrowException(ret);
219                 }
220
221                 return status;
222             }
223             else
224             {
225                 bool status;
226                 int ret = Interop.RuntimeInfo.GetValue(ConvertKeyIfTvProduct(key), out status);
227                 if (ret != (int)RuntimeInfoError.None)
228                 {
229                     Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get value for key {0}", key.ToString());
230                     RuntimeInfoErrorFactory.ThrowException(ret);
231                 }
232
233                 return status;
234             }
235         }
236
237         /// <summary>
238         /// Validates the data type of the status represented by Runtime Key.
239         /// Note that this is a generic method.
240         /// </summary>
241         /// <typeparam name="T">The generic type to validate.</typeparam>
242         /// <param name="key">The runtime information key for which the status type is validated </param>
243         /// <returns>true if the data type matches</returns>.
244         /// <exception cref="ArgumentException">Thrown when the <paramref name="key"/> is invalid.</exception>
245         public static bool Is<T>(RuntimeInformationKey key)
246         {
247             if (!s_keyDataTypeMapping.ContainsKey(key))
248             {
249                 Log.Error(RuntimeInfoErrorFactory.LogTag, "Invalid data type");
250                 throw new ArgumentException("Invalid parameter");
251             }
252
253             return s_keyDataTypeMapping[key] == typeof(T);
254         }
255
256         /// <summary>
257         /// Gets the status of Runtime Key.
258         /// Note that this is a generic method.
259         /// </summary>
260         /// <typeparam name="T">The generic type to return.</typeparam>
261         /// <param name="key">The runtime information key for which the current should be read </param>
262         /// <returns>The current status of the given key</returns>.
263         /// <exception cref="ArgumentException">Thrown when the <paramref name="key"/> is invalid or I/O error is occurred while reading from system.</exception>
264         /// <exception cref="NotSupportedException">Thrown when the feature related <paramref name="key"/> is not supported.</exception>
265         public static T GetStatus<T>(RuntimeInformationKey key)
266         {\r
267             return (T)GetStatus(key);
268         }
269
270         /// <summary>
271         /// Gets system memory information
272         /// </summary>
273         /// <returns>The system memory information structure.</returns>
274         /// <exception cref="ArgumentException">Thrown when I/O error is occurred while reading from system.</exception>
275         public static SystemMemoryInformation GetSystemMemoryInformation()
276         {
277             Interop.RuntimeInfo.MemoryInfo info = new Interop.RuntimeInfo.MemoryInfo();
278             int ret = Interop.RuntimeInfo.GetSystemMemoryInfo(out info);
279             if (ret != (int)RuntimeInfoError.None)
280             {
281                 Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get System memory information");
282                 RuntimeInfoErrorFactory.ThrowException(ret);
283             }
284
285             return new SystemMemoryInformation(info);
286         }
287
288         /// <summary>
289         /// Gets memory information per processes
290         /// </summary>
291         /// <param name="pid">List of unique process ids </param>
292         /// <returns>List of memory information per processes</returns>
293         /// <privilege>http://tizen.org/privilege/systemmonitor</privilege>
294         /// <exception cref="ArgumentException">Thrown when the <paramref name="pid"/> is empty or I/O error is occurred while reading from system or requesting to resource management daemon.</exception>
295         /// <exception cref="OutOfMemoryException">Thrown when the memory is not enough to allocate.</exception>
296         /// <exception cref="UnauthorizedAccessException">Thrown when caller doesn't have a privilege to use this method.</exception>
297         public static IDictionary<int, ProcessMemoryInformation> GetProcessMemoryInformation(IEnumerable<int> pid)
298         {
299             int[] processArray = pid.ToArray<int>();
300             Interop.RuntimeInfo.ProcessMemoryInfo[] processMemoryArray = new Interop.RuntimeInfo.ProcessMemoryInfo[pid.Count<int>()];
301             Dictionary<int, ProcessMemoryInformation> map = new Dictionary<int, ProcessMemoryInformation>();
302             int ret = Interop.RuntimeInfo.GetProcessMemoryInfo(processArray, pid.Count<int>(), out processMemoryArray);
303             if (ret != (int)RuntimeInfoError.None)
304             {
305                 Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get Process memory information");
306                 RuntimeInfoErrorFactory.ThrowException(ret);
307             }
308
309             int idx = 0;
310             foreach (Interop.RuntimeInfo.ProcessMemoryInfo cur in processMemoryArray)
311             {
312                 ProcessMemoryInformation processMemory = new ProcessMemoryInformation(cur);
313                 map.Add(processArray[idx], processMemory);
314                 idx++;
315             }
316
317             return map;
318         }
319
320         /// <summary>
321         /// Gets system CPU usage time
322         /// </summary>
323         /// <returns>The system CPU usage time structure.</returns>
324         /// <exception cref="ArgumentException">Thrown when I/O error is occurred while reading from system.</exception>
325         public static CpuUsage GetCpuUsage()
326         {
327             Interop.RuntimeInfo.CpuUsage usage = new Interop.RuntimeInfo.CpuUsage();
328             int ret = Interop.RuntimeInfo.GetCpuUsage(out usage);
329             if (ret != (int)RuntimeInfoError.None)
330             {
331                 Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get cpu usage");
332                 RuntimeInfoErrorFactory.ThrowException(ret);
333             }
334             return new CpuUsage(usage);
335         }
336
337         /// <summary>
338         /// Gets the CPU usage time per process
339         /// </summary>
340         /// <param name="pid">List of unique process ids </param>
341         /// <returns>List of CPU usage information per processes</returns>
342         /// <privilege>http://tizen.org/privilege/systemmonitor</privilege>
343         /// <exception cref="ArgumentException">Thrown when the <paramref name="pid"/> is empty or I/O error is occurred while reading from system or requesting to resource management daemon.</exception>
344         /// <exception cref="OutOfMemoryException">Thrown when the memory is not enough to allocate.</exception>
345         /// <exception cref="UnauthorizedAccessException">Thrown when caller doesn't have a privilege to use this method.</exception>
346         public static IDictionary<int, ProcessCpuUsage> GetProcessCpuUsage(IEnumerable<int> pid)
347         {
348             int[] processArray = pid.ToArray<int>();
349             Interop.RuntimeInfo.ProcessCpuUsage[] processCpuUsageArray = new Interop.RuntimeInfo.ProcessCpuUsage[pid.Count<int>()];
350             Dictionary<int, ProcessCpuUsage> map = new Dictionary<int, ProcessCpuUsage>();
351             int ret = Interop.RuntimeInfo.GetProcessCpuUsage(processArray, pid.Count<int>(), out processCpuUsageArray);
352             if (ret != (int)RuntimeInfoError.None)
353             {
354                 Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get Process cpu usage");
355                 RuntimeInfoErrorFactory.ThrowException(ret);
356             }
357
358             int idx = 0;
359             foreach (Interop.RuntimeInfo.ProcessCpuUsage cur in processCpuUsageArray)
360             {
361                 ProcessCpuUsage processUsage = new ProcessCpuUsage(cur);
362                 map.Add(processArray[idx], processUsage);
363                 idx++;
364             }
365
366             return map;
367         }
368
369         /// <summary>
370         /// Gets the number of processors
371         /// </summary>
372         /// <value>The number of processors</value>
373         /// <exception cref="ArgumentException">Thrown when I/O error is occurred while reading from system.</exception>
374         public static int ProcessorCount
375         {
376             get
377             {
378                 int count;
379                 int ret = Interop.RuntimeInfo.GetProcessorCount(out count);
380                 if (ret != (int)RuntimeInfoError.None)
381                 {
382                     Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get Processor count");
383                     RuntimeInfoErrorFactory.ThrowException(ret);
384                 }
385
386                 return count;
387             }
388         }
389
390         /// <summary>
391         /// Gets the current frequency of processor
392         /// </summary>
393         /// <param name="coreId">The index (from 0) of CPU core that you want to know the frequency</param>
394         /// <returns>The current frequency(MHz) of processor</returns>
395         /// <exception cref="ArgumentException">Thrown when the <paramref name="coreid"/> is invalid or I/O error is occurred while reading from system.</exception>
396         /// <exception cref="NotSupportedException">Thrown when this system doesn't store CPU current frequency.</exception>
397         public static int GetProcessorCurrentFrequency(int coreId)
398         {
399             int frequency;
400             int ret = Interop.RuntimeInfo.GetProcessorCurrentFrequency(coreId, out frequency);
401             if (ret != (int)RuntimeInfoError.None)
402             {
403                 Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get Processor current frequency");
404                 RuntimeInfoErrorFactory.ThrowException(ret);
405             }
406             return frequency;
407         }
408
409         /// <summary>
410         /// Gets the max frequency of processor
411         /// </summary>
412         /// <param name="coreId">The index (from 0) of CPU core that you want to know the frequency</param>
413         /// <returns>The max frequency(MHz) of processor</returns>
414         /// <exception cref="ArgumentException">Thrown when the <paramref name="coreid"/> is invalid or I/O error is occurred while reading from system.</exception>
415         /// <exception cref="NotSupportedException">Thrown when this system doesn't store CPU max frequency.</exception>
416         public static int GetProcessorMaxFrequency(int coreId)
417         {
418             int frequency;
419             int ret = Interop.RuntimeInfo.GetProcessorMaxFrequency(coreId, out frequency);
420             if (ret != (int)RuntimeInfoError.None)
421             {
422                 Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to get  Processor max frequency");
423                 RuntimeInfoErrorFactory.ThrowException(ret);
424             }
425             return frequency;
426         }
427
428         /// <summary>
429         /// (event) BluetoothEnabled is raised when system preference for bluetooth is changed.
430         /// </summary>
431         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> BluetoothEnabled
432         {
433             add
434             {
435                 if (s_bluetoothEnabled == null)
436                 {
437                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.Bluetooth), s_runtimeInfoChangedCallback, IntPtr.Zero);
438                     if (ret != (int)RuntimeInfoError.None)
439                     {
440                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
441                         RuntimeInfoErrorFactory.ThrowException(ret);
442                     }
443                 }
444                 s_bluetoothEnabled += value;
445             }
446             remove
447             {
448                 s_bluetoothEnabled -= value;
449                 if (s_bluetoothEnabled == null)
450                 {
451                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.Bluetooth));
452                     if (ret != (int)RuntimeInfoError.None)
453                     {
454                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
455                         RuntimeInfoErrorFactory.ThrowException(ret);
456                     }
457                 }
458             }
459         }
460         /// <summary>
461         /// (event) WifiHotspotEnabled is raised when system preference for Wi-Fi is changed.
462         /// </summary>
463         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> WifiHotspotEnabled
464         {
465             add
466             {
467                 if (s_wifiHotspotEnabled == null)
468                 {
469                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.WifiHotspot), s_runtimeInfoChangedCallback, IntPtr.Zero);
470                     if (ret != (int)RuntimeInfoError.None)
471                     {
472                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
473                         RuntimeInfoErrorFactory.ThrowException(ret);
474                     }
475                 }
476                 s_wifiHotspotEnabled += value;
477             }
478             remove
479             {
480                 s_wifiHotspotEnabled -= value;
481                 if (s_wifiHotspotEnabled == null)
482                 {
483                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.WifiHotspot));
484                     if (ret != (int)RuntimeInfoError.None)
485                     {
486                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
487                         RuntimeInfoErrorFactory.ThrowException(ret);
488                     }
489                 }
490             }
491         }
492         /// <summary>
493         /// (event) BluetoothTetheringEnabled is raised when system preference for bluetooth tethering is changed.
494         /// </summary>
495         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> BluetoothTetheringEnabled
496         {
497             add
498             {
499                 if (s_bluetoothTetheringEnabled == null)
500                 {
501                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.BluetoothTethering), s_runtimeInfoChangedCallback, IntPtr.Zero);
502                     if (ret != (int)RuntimeInfoError.None)
503                     {
504                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
505                         RuntimeInfoErrorFactory.ThrowException(ret);
506                     }
507                 }
508                 s_bluetoothTetheringEnabled += value;
509             }
510             remove
511             {
512                 s_bluetoothTetheringEnabled -= value;
513                 if (s_bluetoothTetheringEnabled == null)
514                 {
515                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.BluetoothTethering));
516                     if (ret != (int)RuntimeInfoError.None)
517                     {
518                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
519                         RuntimeInfoErrorFactory.ThrowException(ret);
520                     }
521                 }
522             }
523         }
524         /// <summary>
525         /// (event) UsbTetheringEnabled is raised when system preference for USB tethering is changed.
526         /// </summary>
527         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> UsbTetheringEnabled
528         {
529             add
530             {
531                 if (s_usbTetheringEnabled == null)
532                 {
533                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.UsbTethering), s_runtimeInfoChangedCallback, IntPtr.Zero);
534                     if (ret != (int)RuntimeInfoError.None)
535                     {
536                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
537                         RuntimeInfoErrorFactory.ThrowException(ret);
538                     }
539                 }
540                 s_usbTetheringEnabled += value;
541             }
542             remove
543             {
544                 s_usbTetheringEnabled -= value;
545                 if (s_usbTetheringEnabled == null)
546                 {
547                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.UsbTethering));
548                     if (ret != (int)RuntimeInfoError.None)
549                     {
550                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
551                         RuntimeInfoErrorFactory.ThrowException(ret);
552                     }
553                 }
554             }
555         }
556         /// <summary>
557         /// (event) PacketDataEnabled is raised when system preference for package data through 3G network is changed.
558         /// </summary>
559         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> PacketDataEnabled
560         {
561             add
562             {
563                 if (s_packetDataEnabled == null)
564                 {
565                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.PacketData), s_runtimeInfoChangedCallback, IntPtr.Zero);
566                     if (ret != (int)RuntimeInfoError.None)
567                     {
568                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
569                         RuntimeInfoErrorFactory.ThrowException(ret);
570                     }
571                 }
572                 s_packetDataEnabled += value;
573             }
574             remove
575             {
576                 s_packetDataEnabled -= value;
577                 if (s_packetDataEnabled == null)
578                 {
579                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.PacketData));
580                     if (ret != (int)RuntimeInfoError.None)
581                     {
582                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
583                         RuntimeInfoErrorFactory.ThrowException(ret);
584                     }
585                 }
586             }
587         }
588         /// <summary>
589         /// (event) DataRoamingEnabled is raised when system preference for data roaming is changed.
590         /// </summary>
591         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> DataRoamingEnabled
592         {
593             add
594             {
595                 if (s_dataRoamingEnabled == null)
596                 {
597                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.DataRoaming), s_runtimeInfoChangedCallback, IntPtr.Zero);
598                     if (ret != (int)RuntimeInfoError.None)
599                     {
600                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
601                         RuntimeInfoErrorFactory.ThrowException(ret);
602                     }
603                 }
604                 s_dataRoamingEnabled += value;
605             }
606             remove
607             {
608                 s_dataRoamingEnabled -= value;
609                 if (s_dataRoamingEnabled == null)
610                 {
611                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.DataRoaming));
612                     if (ret != (int)RuntimeInfoError.None)
613                     {
614                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
615                         RuntimeInfoErrorFactory.ThrowException(ret);
616                     }
617                 }
618             }
619         }
620         /// <summary>
621         /// (event) VibrationEnabled is raised when system preference for vibration is changed.
622         /// </summary>
623         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> VibrationEnabled
624         {
625             add
626             {
627                 if (s_vibrationEnabled == null)
628                 {
629                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.Vibration), s_runtimeInfoChangedCallback, IntPtr.Zero);
630                     if (ret != (int)RuntimeInfoError.None)
631                     {
632                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
633                         RuntimeInfoErrorFactory.ThrowException(ret);
634                     }
635                 }
636                 s_vibrationEnabled += value;
637             }
638             remove
639             {
640                 s_vibrationEnabled -= value;
641                 if (s_vibrationEnabled == null)
642                 {
643                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.Vibration));
644                     if (ret != (int)RuntimeInfoError.None)
645                     {
646                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
647                         RuntimeInfoErrorFactory.ThrowException(ret);
648                     }
649                 }
650             }
651         }
652         /// <summary>
653         /// (event) AudioJackConnected is raised when audio jack is connected/disconnected.
654         /// </summary>
655         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> AudioJackConnected
656         {
657             add
658             {
659                 if (s_audioJackConnected == null)
660                 {
661                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.AudioJack), s_runtimeInfoChangedCallback, IntPtr.Zero);
662                     if (ret != (int)RuntimeInfoError.None)
663                     {
664                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
665                         RuntimeInfoErrorFactory.ThrowException(ret);
666                     }
667                 }
668                 s_audioJackConnected += value;
669             }
670             remove
671             {
672                 s_audioJackConnected -= value;
673                 if (s_audioJackConnected == null)
674                 {
675                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.AudioJack));
676                     if (ret != (int)RuntimeInfoError.None)
677                     {
678                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
679                         RuntimeInfoErrorFactory.ThrowException(ret);
680                     }
681                 }
682             }
683         }
684         /// <summary>
685         /// (event) GpsStatusChanged is raised when status of GPS is changed.
686         /// </summary>
687         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> GpsStatusChanged
688         {
689             add
690             {
691                 if (s_gpsStatusChanged == null)
692                 {
693                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.Gps), s_runtimeInfoChangedCallback, IntPtr.Zero);
694                     if (ret != (int)RuntimeInfoError.None)
695                     {
696                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
697                         RuntimeInfoErrorFactory.ThrowException(ret);
698                     }
699                 }
700                 s_gpsStatusChanged += value;
701             }
702             remove
703             {
704                 s_gpsStatusChanged -= value;
705                 if (s_gpsStatusChanged == null)
706                 {
707                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.Gps));
708                     if (ret != (int)RuntimeInfoError.None)
709                     {
710                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
711                         RuntimeInfoErrorFactory.ThrowException(ret);
712                     }
713                 }
714             }
715         }
716         /// <summary>
717         /// (event) BatteryIsCharging is raised battery is currently charging.
718         /// </summary>
719         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> BatteryIsCharging
720         {
721             add
722             {
723                 if (s_batteryIsCharging == null)
724                 {
725                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.BatteryIsCharging), s_runtimeInfoChangedCallback, IntPtr.Zero);
726                     if (ret != (int)RuntimeInfoError.None)
727                     {
728                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
729                         RuntimeInfoErrorFactory.ThrowException(ret);
730                     }
731                 }
732                 s_batteryIsCharging += value;
733             }
734             remove
735             {
736                 s_batteryIsCharging -= value;
737                 if (s_batteryIsCharging == null)
738                 {
739                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.BatteryIsCharging));
740                     if (ret != (int)RuntimeInfoError.None)
741                     {
742                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
743                         RuntimeInfoErrorFactory.ThrowException(ret);
744                     }
745                 }
746             }
747         }
748         /// <summary>
749         /// (event) TvOutConnected is raised when TV out is connected/disconnected.
750         /// </summary>
751         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> TvOutConnected
752         {
753             add
754             {
755                 if (s_tvOutConnected == null)
756                 {
757                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.TvOut), s_runtimeInfoChangedCallback, IntPtr.Zero);
758                     if (ret != (int)RuntimeInfoError.None)
759                     {
760                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
761                         RuntimeInfoErrorFactory.ThrowException(ret);
762                     }
763                 }
764                 s_tvOutConnected += value;
765             }
766             remove
767             {
768                 s_tvOutConnected -= value;
769                 if (s_tvOutConnected == null)
770                 {
771                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.TvOut));
772                     if (ret != (int)RuntimeInfoError.None)
773                     {
774                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
775                         RuntimeInfoErrorFactory.ThrowException(ret);
776                     }
777                 }
778             }
779         }
780         /// <summary>
781         /// (event) AudioJackConnectorChanged is raised when audio jack connection changes.
782         /// </summary>
783         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> AudioJackConnectorChanged
784         {
785             add
786             {
787                 if (s_audioJackConnectorChanged == null)
788                 {
789                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.AudioJackConnector), s_runtimeInfoChangedCallback, IntPtr.Zero);
790                     if (ret != (int)RuntimeInfoError.None)
791                     {
792                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
793                         RuntimeInfoErrorFactory.ThrowException(ret);
794                     }
795                 }
796                 s_audioJackConnectorChanged += value;
797             }
798             remove
799             {
800                 s_audioJackConnectorChanged -= value;
801                 if (s_audioJackConnectorChanged == null)
802                 {
803                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.AudioJackConnector));
804                     if (ret != (int)RuntimeInfoError.None)
805                     {
806                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
807                         RuntimeInfoErrorFactory.ThrowException(ret);
808                     }
809                 }
810             }
811         }
812         /// <summary>
813         /// (event) ChargerConnected is raised when charger is connected/disconnected.
814         /// </summary>
815         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> ChargerConnected
816         {
817             add
818             {
819                 if (s_chargerConnected == null)
820                 {
821                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.Charger), s_runtimeInfoChangedCallback, IntPtr.Zero);
822                     if (ret != (int)RuntimeInfoError.None)
823                     {
824                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
825                         RuntimeInfoErrorFactory.ThrowException(ret);
826                     }
827                 }
828                 s_chargerConnected += value;
829             }
830             remove
831             {
832                 s_chargerConnected -= value;
833                 if (s_chargerConnected == null)
834                 {
835                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.Charger));
836                     if (ret != (int)RuntimeInfoError.None)
837                     {
838                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
839                         RuntimeInfoErrorFactory.ThrowException(ret);
840                     }
841                 }
842             }
843         }
844         /// <summary>
845         /// (event) AutoRotationEnabled is raised when system preference for auto rotation is changed.
846         /// </summary>
847         public static event EventHandler<RuntimeKeyStatusChangedEventArgs> AutoRotationEnabled
848         {
849             add
850             {
851                 if (s_autoRotationEnabled == null)
852                 {
853                     int ret = Interop.RuntimeInfo.SetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.AutoRotation), s_runtimeInfoChangedCallback, IntPtr.Zero);
854                     if (ret != (int)RuntimeInfoError.None)
855                     {
856                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
857                         RuntimeInfoErrorFactory.ThrowException(ret);
858                     }
859                 }
860                 s_autoRotationEnabled += value;
861             }
862             remove
863             {
864                 s_autoRotationEnabled -= value;
865                 if (s_autoRotationEnabled == null)
866                 {
867                     int ret = Interop.RuntimeInfo.UnsetRuntimeInfoChangedCallback(ConvertKeyIfTvProduct(RuntimeInformationKey.AutoRotation));
868                     if (ret != (int)RuntimeInfoError.None)
869                     {
870                         Log.Error(RuntimeInfoErrorFactory.LogTag, "Interop failed to add event handler");
871                         RuntimeInfoErrorFactory.ThrowException(ret);
872                     }
873                 }
874             }
875         }
876     }
877 }