[Device] Implementation of system.device module including error handling.
authorjh5.cho <jh5.cho@samsung.com>
Mon, 7 Mar 2016 06:35:44 +0000 (15:35 +0900)
committerPraveen Gattu <gattu.p@samsung.com>
Fri, 29 Apr 2016 08:16:18 +0000 (13:46 +0530)
Change-Id: I34b255c7703cd8d674649d71fbe646ecdb0e3938
Signed-off-by: Praveen Gattu <gattu.p@samsung.com>
15 files changed:
Tizen.System.sln [new file with mode: 0755]
Tizen.System/Device/Battery.cs [new file with mode: 0644]
Tizen.System/Device/DeviceEventArgs.cs [new file with mode: 0644]
Tizen.System/Device/DeviceExceptionFactory.cs [new file with mode: 0644]
Tizen.System/Device/Display.cs [new file with mode: 0644]
Tizen.System/Device/Haptic.cs [new file with mode: 0644]
Tizen.System/Device/Led.cs [new file with mode: 0644]
Tizen.System/Device/Power.cs [new file with mode: 0644]
Tizen.System/Interop/Interop.Device.cs [new file with mode: 0644]
Tizen.System/Properties/AssemblyInfo.cs [new file with mode: 0755]
Tizen.System/Tizen.System.csproj [new file with mode: 0644]
Tizen.System/Tizen.System.snk [new file with mode: 0755]
packaging/csapi-tizen.system.manifest [new file with mode: 0755]
packaging/csapi-tizen.system.pc.in [new file with mode: 0755]
packaging/csapi-tizen.system.spec [new file with mode: 0755]

diff --git a/Tizen.System.sln b/Tizen.System.sln
new file mode 100755 (executable)
index 0000000..521b44c
--- /dev/null
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 14 for Windows Desktop
+VisualStudioVersion = 14.0.24720.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tizen.System", "Tizen.System\Tizen.System.csproj", "{A5C7AB61-87F1-4707-BBF4-322D682E223E}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Any CPU = Debug|Any CPU
+               Release|Any CPU = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {A5C7AB61-87F1-4707-BBF4-322D682E223E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {A5C7AB61-87F1-4707-BBF4-322D682E223E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {A5C7AB61-87F1-4707-BBF4-322D682E223E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {A5C7AB61-87F1-4707-BBF4-322D682E223E}.Release|Any CPU.Build.0 = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/Tizen.System/Device/Battery.cs b/Tizen.System/Device/Battery.cs
new file mode 100644 (file)
index 0000000..40f0ad9
--- /dev/null
@@ -0,0 +1,272 @@
+using System;
+
+namespace Tizen.System
+{
+    /// <summary>
+    /// Enumeration for the battery level.
+    /// </summary>
+    public enum BatteryLevelStatus
+    {
+        /// <summary>
+        /// The battery goes empty.
+        /// Prepare for the safe termination of the application,
+        /// because the device starts a shutdown process soon
+        /// after entering this level.
+        /// </summary>
+        Empty = 0,
+        /// <summary>
+        /// The battery charge is at a critical state.
+        /// You may have to stop using multimedia features,
+        /// because they are not guaranteed to work correctly
+        /// at this battery status.
+        /// </summary>
+        Critical,
+        /// <summary>
+        /// The battery has little charge left.
+        /// </summary>
+        Low,
+        /// <summary>
+        /// The battery status is not to be careful.
+        /// </summary>
+        High,
+        /// <summary>
+        /// The battery status is full.
+        /// </summary>
+        Full
+    }
+
+    /// <summary>
+    /// The Battery API provides functions to get information about the battery.
+    /// </summary>
+    /// <remarks>
+    /// The Battery API provides the way to get the current battery capacity value,
+    /// battery state and charging state. It also supports the API for an application
+    /// to receive the battery events from the system. To receive the battery event
+    /// it should be described by the callback function.
+    /// </remarks>
+    public static class Battery
+    {
+        private static readonly object s_lock = new object();
+        /// <summary>
+        /// Gets the battery charge percentage.
+        /// </summary>
+        /// <value>It returns an integer value from 0 to 100 that indicates remaining
+        /// battery charge as a percentage of the maximum level.</value>
+        public static int Capacity
+        {
+            get
+            {
+                int percent = 0;
+                DeviceError res = (DeviceError) Interop.Device.DeviceBatteryGetPercent(out percent);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get battery percentage.");
+                }
+                return percent;
+            }
+        }
+        /// <summary>
+        /// Gets the battery level.
+        /// </summary>
+        public static BatteryLevelStatus Level
+        {
+            get
+            {
+                int level = 0;
+                DeviceError res = (DeviceError) Interop.Device.DeviceBatteryGetLevelStatus(out level);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get battery status.");
+                }
+                return (BatteryLevelStatus)level;
+            }
+        }
+        /// <summary>
+        /// Gets the charging state.
+        /// </summary>
+        public static bool IsCharging
+        {
+            get
+            {
+                bool charging;
+                DeviceError res = (DeviceError) Interop.Device.DeviceBatteryIsCharging(out charging);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get battery charging state.");
+                }
+                return charging;
+            }
+        }
+
+        private static EventHandler<BatteryCapacityChangedEventArgs> s_capacityChanged;
+        /// <summary>
+        /// CapacityChanged is triggered when the battery charge percentage is changed
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e">A BatteryCapacityChangedEventArgs object that contains changed battery capacity</param>
+
+        public static event EventHandler<BatteryCapacityChangedEventArgs> CapacityChanged
+        {
+            add
+            {
+                lock (s_lock)
+                {
+                    if (s_capacityChanged == null)
+                    {
+                        EventListenerStart(EventType.BatteryCapacity);
+                    }
+                    s_capacityChanged += value;
+                }
+            }
+            remove
+            {
+                lock (s_lock)
+                {
+                    s_capacityChanged -= value;
+                    if (s_capacityChanged == null)
+                    {
+                        EventListenerStop(EventType.BatteryCapacity);
+                    }
+                }
+            }
+        }
+
+        private static event EventHandler<BatteryLevelChangedEventArgs> s_levelChanged;
+
+        /// <summary>
+        /// LevelChanged is triggered when the battery level is changed
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e">A BatteryLevelChangedEventArgs object that contains changed battery level </param>
+        public static event EventHandler<BatteryLevelChangedEventArgs> LevelChanged
+        {
+            add
+            {
+                lock (s_lock)
+                {
+                    if (s_levelChanged == null)
+                    {
+                        EventListenerStart(EventType.BatteryLevel);
+                    }
+                    s_levelChanged += value;
+                }
+            }
+            remove
+            {
+                lock (s_lock)
+                {
+                    s_levelChanged -= value;
+                    if (s_levelChanged == null)
+                    {
+                        EventListenerStop(EventType.BatteryLevel);
+                    }
+                }
+            }
+        }
+
+        private static event EventHandler<BatteryChargingStateChangedEventArgs> s_chargingStateChanged;
+        /// <summary>
+        /// ChargingStatusChanged is triggered when the battery charging status is changed
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e">A BatteryChargingStateChangedEventArgs object that contains changed battery charging state</param>
+
+        public static event EventHandler<BatteryChargingStateChangedEventArgs> ChargingStatusChanged
+        {
+            add
+            {
+                lock (s_lock)
+                {
+                    if (s_chargingStateChanged == null)
+                    {
+                        EventListenerStart(EventType.BatteryCharging);
+                    }
+                    s_chargingStateChanged += value;
+                }
+            }
+            remove
+            {
+                lock (s_lock)
+                {
+                    s_chargingStateChanged -= value;
+                    if (s_chargingStateChanged == null)
+                    {
+                        EventListenerStop(EventType.BatteryCharging);
+                    }
+                }
+            }
+        }
+
+        private static Interop.Device.deviceCallback s_cpacityHandler;
+        private static Interop.Device.deviceCallback s_levelHandler;
+        private static Interop.Device.deviceCallback s_chargingHandler;
+
+        private static void EventListenerStart(EventType eventType)
+        {
+            switch (eventType)
+            {
+                case EventType.BatteryCapacity:
+                    s_cpacityHandler = (int type, IntPtr value, IntPtr data) =>
+                    {
+                        int val = value.ToInt32();
+                        BatteryCapacityChangedEventArgs e = new BatteryCapacityChangedEventArgs()
+                        {
+                            Capacity = val
+                        };
+                        s_capacityChanged?.Invoke(null, e);
+                        return true;
+                    };
+
+                    Interop.Device.DeviceAddCallback(eventType, s_cpacityHandler, IntPtr.Zero);
+                    break;
+
+                case EventType.BatteryLevel:
+                    s_levelHandler = (int type, IntPtr value, IntPtr data) =>
+                    {
+                        int val = value.ToInt32();
+                        BatteryLevelChangedEventArgs e = new BatteryLevelChangedEventArgs()
+                        {
+                            Level = (BatteryLevelStatus)val
+                        };
+                        s_levelChanged?.Invoke(null, e);
+                        return true;
+                    };
+
+                    Interop.Device.DeviceAddCallback(eventType, s_levelHandler, IntPtr.Zero);
+                    break;
+
+                case EventType.BatteryCharging:
+                    s_chargingHandler = (int type, IntPtr value, IntPtr data) =>
+                    {
+                        bool val = (value.ToInt32() == 1);
+                        BatteryChargingStateChangedEventArgs e = new BatteryChargingStateChangedEventArgs()
+                        {
+                            Charging = val
+                        };
+                        s_chargingStateChanged?.Invoke(null, e);
+                        return true;
+                    };
+                    Interop.Device.DeviceAddCallback(eventType, s_chargingHandler, IntPtr.Zero);
+                    break;
+            }
+        }
+
+        private static void EventListenerStop(EventType eventType)
+        {
+            switch (eventType)
+            {
+                case EventType.BatteryCapacity:
+                    Interop.Device.DeviceRemoveCallback(eventType, s_cpacityHandler);
+                    break;
+
+                case EventType.BatteryLevel:
+                    Interop.Device.DeviceRemoveCallback(eventType, s_levelHandler);
+                    break;
+
+                case EventType.BatteryCharging:
+                    Interop.Device.DeviceRemoveCallback(eventType, s_chargingHandler);
+                    break;
+            }
+        }
+    }
+}
diff --git a/Tizen.System/Device/DeviceEventArgs.cs b/Tizen.System/Device/DeviceEventArgs.cs
new file mode 100644 (file)
index 0000000..1e2d94d
--- /dev/null
@@ -0,0 +1,48 @@
+using System;
+
+namespace Tizen.System
+{
+    // Battery
+    public class BatteryCapacityChangedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// The current capacity of the battery.
+        /// Capacity is an integer value from 0 to 100, that indicates remaining battery charge as a percentage of the maximum level.
+        /// </summary>
+        public int Capacity { get; internal set; }
+    }
+
+    public class BatteryLevelChangedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Level indicates the Current battery level status which is of type BatteryLevelStatus.
+        /// </summary>
+        public BatteryLevelStatus Level { get; internal set; }
+    }
+
+    public class BatteryChargingStateChangedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// The charging state of the battery. Charging is of type boolean which indicates true/false based on currrent charging status.
+        /// </summary>
+        public bool Charging { get; internal set; }
+    }
+
+    // Display
+    public class DisplayStateChangedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// State indicates the current display state of the device which is an enum of type DisplayState.
+        /// </summary>
+        public DisplayState State { get; internal set; }
+    }
+
+    // Led
+    public class LedBrightnessChangedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Brightness indicates the current brightness level of the display as an integer.
+        /// </summary>
+        public int Brightness { get; internal set; }
+    }
+}
diff --git a/Tizen.System/Device/DeviceExceptionFactory.cs b/Tizen.System/Device/DeviceExceptionFactory.cs
new file mode 100644 (file)
index 0000000..3512432
--- /dev/null
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Tizen.System
+{
+    internal enum DeviceError
+    {
+        None = Tizen.Internals.Errors.ErrorCode.None,
+        InvalidParameter = Tizen.Internals.Errors.ErrorCode.InvalidParameter,
+        PermissionDenied = Tizen.Internals.Errors.ErrorCode.PermissionDenied,
+        InvalidOperation = Tizen.Internals.Errors.ErrorCode.InvalidOperation,
+        AlreadyInProgress = Tizen.Internals.Errors.ErrorCode.NowInProgress,
+        NotSupported = Tizen.Internals.Errors.ErrorCode.NotSupported,
+        ResourceBusy = Tizen.Internals.Errors.ErrorCode.ResourceBusy,
+        OperationFailed = -0x01140000 | 0x01,
+        NotInitialized = -0x01140000 | 0x02
+    };
+
+    class DeviceExceptionFactory
+    {
+        internal const string LogTag = "Tizen.System.Device";
+
+        internal static Exception CreateException(DeviceError err, string msg)
+        {
+            Exception exp;
+            switch (err)
+            {
+                case DeviceError.InvalidParameter:
+                    exp =  new ArgumentException(msg);
+                    break;
+                case DeviceError.AlreadyInProgress:
+                    //fall through
+                case DeviceError.NotSupported:
+                    //fall through
+                case DeviceError.ResourceBusy:
+                    //fall through
+                case DeviceError.OperationFailed:
+                    //fall through
+                case DeviceError.NotInitialized:
+                    //fall through
+                case DeviceError.PermissionDenied:
+                    //fall through
+                case DeviceError.InvalidOperation:
+                    exp = new InvalidOperationException(msg);
+                    break;
+                default:
+                    exp = new InvalidOperationException("Unknown error occured.");
+                    break;
+            }
+            return exp;
+        }
+    }
+}
diff --git a/Tizen.System/Device/Display.cs b/Tizen.System/Device/Display.cs
new file mode 100644 (file)
index 0000000..ae60a19
--- /dev/null
@@ -0,0 +1,187 @@
+using System;
+using System.Collections.Generic;
+
+namespace Tizen.System
+{
+    /// <summary>
+    /// Enumeration for the available display states.
+    /// An application cannot put the device into the power off state or the suspend state.
+    /// </summary>
+    public enum DisplayState
+    {
+        /// <summary>
+        /// Normal state
+        /// </summary>
+        Normal = 0,
+        /// <summary>
+        /// Screen dim state
+        /// </summary>
+        Dim,
+        /// <summary>
+        /// Screen off state
+        /// </summary>
+        Off
+    }
+
+    /// <summary>
+    /// The Display class provides properties and methods to control the display status and brightness.
+    /// </summary>
+    public class Display
+    {
+        private readonly int _displayId;
+        private static readonly Dictionary<int, Display> s_displays = new Dictionary<int, Display>();
+        private static readonly object s_lock = new object();
+        private Display(int deviceNumber)
+        {
+            _displayId = deviceNumber;
+        }
+
+        /// <summary>
+        /// The number of display devices.
+        /// </summary>
+        public static int NumberOfDisplays
+        {
+            get
+            {
+                int number = 0;
+                DeviceError res = (DeviceError)Interop.Device.DeviceDisplayGetNumbers(out number);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get number of displays.");
+                }
+                return number;
+            }
+        }
+
+        /// <summary>
+        /// The maximum brightness value that can be set.
+        /// </summary>
+        public int MaxBrightness
+        {
+            get
+            {
+                int max = 0;
+                DeviceError res = (DeviceError) Interop.Device.DeviceDisplayGetMaxBrightness(_displayId, out max);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get max brightness.");
+                }
+                return max;
+            }
+        }
+
+        /// <summary>
+        /// The display brightness value.
+        /// </summary>
+        public int Brightness
+        {
+            get
+            {
+                int brightness = 0;
+                DeviceError res = (DeviceError) Interop.Device.DeviceDisplayGetBrightness(_displayId, out brightness);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get brightness.");
+                }
+                return brightness;
+            }
+            set
+            {
+                //TODO: Check for maximum throw exception..
+                DeviceError res = (DeviceError) Interop.Device.DeviceDisplaySetBrightness(_displayId, value);
+                if (res != DeviceError.None)
+                {
+                    throw DeviceExceptionFactory.CreateException(res, "unable to set brightness value");
+                }
+            }
+        }
+        /// <summary>
+        /// Get the Display instance for the given display index.
+        /// </summary>
+        /// <param name="deviceNumber"> The index of the display.
+        /// It can be greater than or equal to 0 and less than the number of display devices </param>
+        public static Display GetDisplay(int deviceNumber)
+        {
+            //TODO: throw an exception for invalid display Id.
+            if(deviceNumber < 0 || deviceNumber >= NumberOfDisplays)
+            {
+                throw DeviceExceptionFactory.CreateException(DeviceError.InvalidParameter, "invalid display number");
+            }
+            if (!s_displays.ContainsKey(deviceNumber))
+            {
+                s_displays.Add(deviceNumber, new Display(deviceNumber));
+            }
+            return s_displays[deviceNumber];
+        }
+        /// <summary>
+        /// The current display state.
+        /// </summary>
+        public static DisplayState State
+        {
+            get
+            {
+                int state = 0;
+                DeviceError res = (DeviceError) Interop.Device.DeviceDisplayGetState(out state);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get Display state.");
+                }
+                return (DisplayState)state;
+            }
+        }
+
+        private static event EventHandler<DisplayStateChangedEventArgs> s_stateChanged;
+        /// <summary>
+        /// StateChanged is raised when the state of the display is changed
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e">An DisplayStateChangedEventArgs object that contains the changed state</param>
+
+        public static event EventHandler<DisplayStateChangedEventArgs> StateChanged
+        {
+            add
+            {
+                lock (s_lock)
+                {
+                    if (s_stateChanged == null)
+                    {
+                        EventListenerStart();
+                    }
+                    s_stateChanged += value;
+                }
+            }
+            remove
+            {
+                lock (s_lock)
+                {
+                    s_stateChanged -= value;
+                    if (s_stateChanged == null)
+                    {
+                        EventListenerStop();
+                    }
+                }
+            }
+        }
+
+        private static Interop.Device.deviceCallback s_handler;
+        private static void EventListenerStart()
+        {
+            s_handler = (int type, IntPtr value, IntPtr data) =>
+            {
+                int val = value.ToInt32();
+                DisplayStateChangedEventArgs e = new DisplayStateChangedEventArgs()
+                {
+                    State = (DisplayState)val
+                };
+                s_stateChanged?.Invoke(null, e);
+                return true;
+            };
+            Interop.Device.DeviceAddCallback(EventType.DisplayState, s_handler, IntPtr.Zero);
+        }
+
+        private static void EventListenerStop()
+        {
+            Interop.Device.DeviceRemoveCallback(EventType.DisplayState, s_handler);
+        }
+    }
+}
diff --git a/Tizen.System/Device/Haptic.cs b/Tizen.System/Device/Haptic.cs
new file mode 100644 (file)
index 0000000..6af4d7e
--- /dev/null
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+
+namespace Tizen.System
+{
+    /// <summary>
+    /// The Haptic class provides properties and methods to control a vibrator.
+    /// </summary>
+    public class Vibrator : IDisposable
+    {
+        private readonly int _vibratorId;
+        private static readonly Dictionary<int, Vibrator> s_vibrators = new Dictionary<int, Vibrator>();
+        private IntPtr _hapticHandle;
+        private bool _disposedValue = false;
+        private Vibrator(int id)
+        {
+            _vibratorId = id;
+            DeviceError res = (DeviceError) Interop.Device.DeviceHapticOpen(_vibratorId, out _hapticHandle);
+            if (res != DeviceError.None)
+            {
+                throw DeviceExceptionFactory.CreateException(res, "unable to create Vibrator for given Id");
+            }
+        }
+
+        ~Vibrator()
+        {
+            Dispose(false);
+        }
+
+        /// <summary>
+        /// Get the Vibrator instance for the given vibrator index.
+        /// </summary>
+        /// <param name="deviceId"> The index of the vibrator.
+        /// It can be greater than or equal to 0 and less than the number of vibrators. </param>
+        public static Vibrator GetVibrator(int deviceNumber)
+        {
+            if (deviceNumber < 0 || deviceNumber >= NumberOfVibrators)
+            {
+                throw DeviceExceptionFactory.CreateException(DeviceError.InvalidParameter, "invalid vibrator number");
+            }
+            if (!s_vibrators.ContainsKey(deviceNumber))
+            {
+                s_vibrators.Add(deviceNumber, new Vibrator(deviceNumber));
+            }
+            return s_vibrators[deviceNumber];
+        }
+        /// <summary>
+        /// Gets the number of vibrators.
+        /// </summary>
+        public static int NumberOfVibrators
+        {
+            get
+            {
+                int count = 0;
+                DeviceError res = (DeviceError) Interop.Device.DeviceHapticGetCount(out count);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get Vibrators count.");
+                }
+                return count;
+            }
+        }
+        /// <summary>
+        /// Vibrates during the specified time with a constant intensity.
+        /// This function can be used to start monotonous vibration for the specified time.
+        /// </summary>
+        /// <param name="duration">The play duration in milliseconds </param>
+        /// <param name="feedback">The amount of the intensity variation (0 ~ 100) </param>
+        public void Vibrate(int duration, int feedback)
+        {
+            IntPtr effect;
+            DeviceError res = DeviceError.None;
+            if (_hapticHandle == IntPtr.Zero)
+            {
+                res = (DeviceError) Interop.Device.DeviceHapticOpen(_vibratorId, out _hapticHandle);
+                if (res != DeviceError.None)
+                {
+                    throw DeviceExceptionFactory.CreateException(res, "unable to get vibrator.");
+                }
+            }
+
+            res = (DeviceError) Interop.Device.DeviceHapticVibrate(_hapticHandle, duration, feedback, out effect);
+            if (res != DeviceError.None)
+            {
+                throw DeviceExceptionFactory.CreateException(res, "unable to vibrate the current vibrator.");
+            }
+        }
+        /// <summary>
+        /// Stops all vibration effects which are being played.
+        /// This function can be used to stop all effects started by Vibrate().
+        /// </summary>
+        public void Stop()
+        {
+            if (_hapticHandle != IntPtr.Zero)
+            {
+                DeviceError res = (DeviceError)Interop.Device.DeviceHapticStop(_hapticHandle, IntPtr.Zero);
+                if (res != DeviceError.None)
+                {
+                    throw DeviceExceptionFactory.CreateException(res, "unable to stop the current vibrator.");
+                }
+            }
+        }
+        /// <summary>
+        /// Dispose API for closing the internal resources.
+        /// This function can be used to stop all effects started by Vibrate().
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!_disposedValue)
+            {
+                if (_hapticHandle != IntPtr.Zero)
+                {
+                    Interop.Device.DeviceHapticClose(_hapticHandle);
+                    _hapticHandle = IntPtr.Zero;
+                }
+                _disposedValue = true;
+            }
+        }
+    }
+}
diff --git a/Tizen.System/Device/Led.cs b/Tizen.System/Device/Led.cs
new file mode 100644 (file)
index 0000000..d0b18bd
--- /dev/null
@@ -0,0 +1,135 @@
+using System;
+
+namespace Tizen.System
+{
+    /// <summary>
+    /// The Led class provides properties and methods to control the attached led device.
+    /// </summary>
+    public static class Led
+    {
+        /// <summary>
+        /// Gets the max brightness value of a LED that is located next to the camera.
+        /// </summary>
+        public static int MaxBrightness
+        {
+            get
+            {
+                int max = 0;
+                DeviceError res = (DeviceError) Interop.Device.DeviceFlashGetMaxBrightness(out max);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get max brightness value.");
+                }
+                return max;
+            }
+        }
+
+        private static readonly object s_lock = new object();
+
+        /// <summary>
+        /// Gets the brightness value of a LED that is located next to the camera.
+        /// </summary>
+        public static int Brightness
+        {
+            get
+            {
+                int brightness = 0;
+                DeviceError res = (DeviceError) Interop.Device.DeviceFlashGetBrightness(out brightness);
+                if (res != DeviceError.None)
+                {
+                    Log.Warn(DeviceExceptionFactory.LogTag, "unable to get brightness value.");
+                }
+                return brightness;
+            }
+            set
+            {
+                Interop.Device.DeviceFlashSetBrightness(value);
+            }
+        }
+
+        /// <summary>
+        /// Plays the LED that is located to the front of a device.
+        /// </summary>
+        /// <param name="on">Turn on time in milliseconds </param>
+        /// <param name="off">Turn off time in milliseconds </param>
+        /// <param name="color">
+        /// The Color value
+        /// The first byte means opaque and the other 3 bytes are RGB values.
+        /// </param>
+        public static void Play(int on, int off, uint color)
+        {
+            //looks like only blink option is supported. So hard coded to default blink option.
+            DeviceError res = (DeviceError)Interop.Device.DeviceLedPlayCustom(on, off, color, 1);
+            if (res != DeviceError.None)
+            {
+                throw DeviceExceptionFactory.CreateException(DeviceError.InvalidParameter, "failed to play Led.");
+            }
+        }
+
+        /// <summary>
+        /// Stops the LED that is located to the front of a device.
+        /// </summary>
+        public static void Stop()
+        {
+            DeviceError res = (DeviceError) Interop.Device.DeviceLedStopCustom();
+            if(res != DeviceError.None)
+            {
+                throw DeviceExceptionFactory.CreateException(DeviceError.InvalidParameter, "failed to stop Led.");
+            }
+        }
+
+
+        private static EventHandler<LedBrightnessChangedEventArgs> s_brightnessChanged;
+        /// <summary>
+        /// StateChanged is raised when the LED state is changed
+        /// </summary>
+        /// <param name="sender">The source of the event.</param>
+        /// <param name="e">An LedBrightnessChangedEventArgs object that contains the changed brightness.</param>
+        public static event EventHandler<LedBrightnessChangedEventArgs> BrightnessChanged
+        {
+            add
+            {
+                lock (s_lock)
+                {
+                    if (s_brightnessChanged == null)
+                    {
+                        EventListenerStart();
+                    }
+                    s_brightnessChanged += value;
+                }
+            }
+            remove
+            {
+                lock (s_lock)
+                {
+                    s_brightnessChanged -= value;
+                    if (s_brightnessChanged == null)
+                    {
+                        EventListenerStop();
+                    }
+                }
+            }
+        }
+
+        private static Interop.Device.deviceCallback s_handler;
+        private static void EventListenerStart()
+        {
+            s_handler = (int type, IntPtr value, IntPtr data) =>
+            {
+                int val = value.ToInt32();
+                LedBrightnessChangedEventArgs e = new LedBrightnessChangedEventArgs()
+                {
+                    Brightness = val
+                };
+                s_brightnessChanged?.Invoke(null, e);
+                return true;
+            };
+            Interop.Device.DeviceAddCallback(EventType.FlashBrightness, s_handler, IntPtr.Zero);
+        }
+
+        private static void EventListenerStop()
+        {
+            Interop.Device.DeviceRemoveCallback(EventType.FlashBrightness, s_handler);
+        }
+    }
+}
diff --git a/Tizen.System/Device/Power.cs b/Tizen.System/Device/Power.cs
new file mode 100644 (file)
index 0000000..a1b5efa
--- /dev/null
@@ -0,0 +1,39 @@
+using System;
+
+namespace Tizen.System
+{
+    /// <summary>
+    /// The Power class provides methods to control the power service.
+    /// </summary>
+    public static class Power
+    {
+        /// <summary>
+        /// Locks the CPU for a specified time.
+        /// After the given timeout (in milliseconds), unlock the given lock state automatically.
+        /// </summary>
+        /// <param name="timeout">
+        /// The positive number in milliseconds or 0 for permanent lock
+        /// So you must release the permanent lock of power state with ReleaseCpuLock() if timeout_ms is zero.
+        /// </param>
+        public static void RequestCpuLock(int timeout)
+        {
+            DeviceError res = (DeviceError) Interop.Device.DevicePowerRequestLock(0, timeout);
+            if (res != DeviceError.None)
+            {
+                throw DeviceExceptionFactory.CreateException(res, "unable to acquire power lock.");
+            }
+        }
+
+        /// <summary>
+        /// Releases the CPU lock state.
+        /// </summary>
+        public static void ReleaseCpuLock()
+        {
+            DeviceError res = (DeviceError) Interop.Device.DevicePowerReleaseLock(0);
+            if (res != DeviceError.None)
+            {
+                throw DeviceExceptionFactory.CreateException(res, "unable to release power lock.");
+            }
+        }
+    }
+}
diff --git a/Tizen.System/Interop/Interop.Device.cs b/Tizen.System/Interop/Interop.Device.cs
new file mode 100644 (file)
index 0000000..e9b8f89
--- /dev/null
@@ -0,0 +1,89 @@
+/// Copyright 2016 by Samsung Electronics, Inc.,
+///
+/// This software is the confidential and proprietary information
+/// of Samsung Electronics, Inc. ("Confidential Information"). You
+/// shall not disclose such Confidential Information and shall use
+/// it only in accordance with the terms of the license agreement
+/// you entered into with Samsung.
+
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Tizen.System
+{
+    internal enum EventType
+    {
+        BatteryCapacity,
+        BatteryLevel,
+        BatteryCharging,
+        DisplayState,
+        FlashBrightness
+    }
+}
+
+internal static class Interop
+{
+    internal static partial class Device
+    {
+        // Battery
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_battery_get_percent", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceBatteryGetPercent(out int percent);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_battery_is_charging", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceBatteryIsCharging(out bool charging);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_battery_get_level_status", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceBatteryGetLevelStatus(out int status);
+
+        // Display
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_display_get_numbers", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceDisplayGetNumbers(out int device_number);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_display_get_max_brightness", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceDisplayGetMaxBrightness(int index, out int max_brightness);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_display_get_brightness", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceDisplayGetBrightness(int index, out int status);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_display_set_brightness", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceDisplaySetBrightness(int index, int brightness);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_display_get_state", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceDisplayGetState(out int state);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_display_change_state", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceDisplayChangeState(int state);
+
+        // Haptic
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_haptic_get_count", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceHapticGetCount(out int device_number);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_haptic_open", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceHapticOpen(int index, out IntPtr handle);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_haptic_close", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceHapticClose(IntPtr handle);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_haptic_vibrate", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceHapticVibrate(IntPtr handle, int duration, int feedback, out IntPtr effect);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_haptic_stop", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceHapticStop(IntPtr handle, IntPtr effect);
+
+        // Led
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_flash_get_max_brightness", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceFlashGetMaxBrightness(out int max_brightness);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_flash_get_brightness", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceFlashGetBrightness(out int brightness);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_flash_set_brightness", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceFlashSetBrightness(int brightness);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_led_play_custom", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceLedPlayCustom(int on, int off, uint color, uint flags);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_led_stop_custom", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceLedStopCustom();
+
+        // Power
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_power_request_lock", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DevicePowerRequestLock(int type, int timeout_ms);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_power_release_lock", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DevicePowerReleaseLock(int type);
+
+        // Callback
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate bool deviceCallback(int type, IntPtr value, IntPtr data);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_add_callback", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceAddCallback(Tizen.System.EventType type, deviceCallback cb, IntPtr data);
+        [DllImport("libcapi-system-device.so.0", EntryPoint = "device_remove_callback", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int DeviceRemoveCallback(Tizen.System.EventType type, deviceCallback cb);
+    }
+}
diff --git a/Tizen.System/Properties/AssemblyInfo.cs b/Tizen.System/Properties/AssemblyInfo.cs
new file mode 100755 (executable)
index 0000000..489d73e
--- /dev/null
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tizen.System")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Samsung Electronics")]
+[assembly: AssemblyProduct("Tizen.System")]
+[assembly: AssemblyCopyright("Copyright (c) 2016 Samsung Electronics Co., Ltd")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a5c7ab61-87f1-4707-bbf4-322d682e223e")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Tizen.System/Tizen.System.csproj b/Tizen.System/Tizen.System.csproj
new file mode 100644 (file)
index 0000000..1811f03
--- /dev/null
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{A5C7AB61-87F1-4707-BBF4-322D682E223E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Tizen.System</RootNamespace>
+    <AssemblyName>Tizen.System</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>
+    </DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>Tizen.System.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+    <Reference Include="Tizen">
+      <HintPath>..\..\tizen\Tizen\bin\Debug\Tizen.dll</HintPath>
+    </Reference>
+    <Reference Include="Tizen.Internals">
+      <HintPath>..\..\tizen\Tizen.Internals\bin\Debug\Tizen.Internals.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Device\Battery.cs" />
+    <Compile Include="Device\DeviceExceptionFactory.cs" />
+    <Compile Include="Device\Display.cs" />
+    <Compile Include="Device\Haptic.cs" />
+    <Compile Include="Device\Led.cs" />
+    <Compile Include="Device\Power.cs" />
+    <Compile Include="Device\DeviceEventArgs.cs" />
+    <Compile Include="Interop\Interop.Device.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packaging\csapi-tizen.system.manifest" />
+    <None Include="packaging\csapi-tizen.system.pc.in" />
+    <None Include="packaging\csapi-tizen.system.spec" />
+    <None Include="Tizen.System.snk" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/Tizen.System/Tizen.System.snk b/Tizen.System/Tizen.System.snk
new file mode 100755 (executable)
index 0000000..7627568
Binary files /dev/null and b/Tizen.System/Tizen.System.snk differ
diff --git a/packaging/csapi-tizen.system.manifest b/packaging/csapi-tizen.system.manifest
new file mode 100755 (executable)
index 0000000..75b0fa5
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+    <request>
+        <domain name="_"/>
+    </request>
+</manifest>
diff --git a/packaging/csapi-tizen.system.pc.in b/packaging/csapi-tizen.system.pc.in
new file mode 100755 (executable)
index 0000000..961ea53
--- /dev/null
@@ -0,0 +1,5 @@
+Name: csapi-tizen.system
+Description: Tizen System API for C#
+Version: @version@
+Libs: -r:@dllpath@/@dllname@
+Requires:
\ No newline at end of file
diff --git a/packaging/csapi-tizen.system.spec b/packaging/csapi-tizen.system.spec
new file mode 100755 (executable)
index 0000000..c7cb90c
--- /dev/null
@@ -0,0 +1,87 @@
+%define dllpath %{_libdir}/mono/tizen
+%define dllname Tizen.System.dll
+
+Name:       csapi-tizen.system
+Summary:    Tizen System API for C#
+Version:    1.0.0
+Release:    1
+Group:      Development/Libraries
+License:    Apache-2.0
+URL:        https://www.tizen.org
+Source0:    %{name}-%{version}.tar.gz
+Source1:    %{name}.manifest
+Source2:    %{name}.pc.in
+
+# TODO: replace mono-compiler, mono-devel to mcs, mono-shlib-cop
+BuildRequires: mono-compiler
+BuildRequires: mono-devel
+# TODO: replace mono-core to gacutil.
+#       mono-core should provide the symbol 'gacutil'
+Requires(post): mono-core
+Requires(postun): mono-core
+
+# P/Invoke Dependencies
+BuildRequires: pkgconfig(capi-system-device)
+
+# P/Invoke Runtime Dependencies
+# TODO: It should be removed after fix tizen-rpm-config
+Requires: capi-system-device
+# DLL Dependencies
+#BuildRequires: ...
+
+%description
+Tizen System Device API for C#
+
+%package devel
+Summary:    Development package for %{name}
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+Development package for %{name}
+
+%prep
+%setup -q
+
+cp %{SOURCE1} .
+
+%build
+# build dll
+mcs -target:library -out:%{dllname} -keyfile:Tizen.System/Tizen.System.snk \
+  Tizen.System/Properties/AssemblyInfo.cs \
+  Tizen.System/System.cs \
+  Tizen.System/Device/EventArgs.cs \
+  Tizen.System/Device/Battery.cs \
+  Tizen.System/Device/Display.cs \
+  Tizen.System/Device/Haptic.cs \
+  Tizen.System/Device/Led.cs \
+  Tizen.System/Device/Power.cs \
+  Tizen.System/Interop/Interop.Device.cs
+
+# check p/invoke
+if [ -x %{dllname} ]; then
+  RET=`mono-shlib-cop %{dllname}`; \
+  CNT=`echo $RET | grep -E "^error:" | wc -l`; \
+  if [ $CNT -gt 0 ]; then exit 1; fi
+fi
+
+%install
+# copy dll
+mkdir -p %{buildroot}%{dllpath}
+install -p -m 644 %{dllname} %{buildroot}%{dllpath}
+
+# generate pkgconfig
+mkdir -p %{buildroot}%{_libdir}/pkgconfig
+sed -e "s#@version@#%{version}#g" \
+    -e "s#@dllpath@#%{dllpath}#g" \
+    -e "s#@dllname@#%{dllname}#g" \
+    %{SOURCE2} > %{buildroot}%{_libdir}/pkgconfig/%{name}.pc
+
+%post
+gacutil -i %{dllpath}/%{dllname}
+
+%files
+%{dllpath}/%{dllname}
+
+%files devel
+%{_libdir}/pkgconfig/%{name}.pc