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