[Internal] Add Tizen.Inspections internal API (#1933)
authorkkuchciak <k.kuchciak@samsung.com>
Wed, 2 Sep 2020 08:14:21 +0000 (10:14 +0200)
committerGitHub <noreply@github.com>
Wed, 2 Sep 2020 08:14:21 +0000 (17:14 +0900)
Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
internals/src/Tizen.Inspections/Interop/Interop.Inspections.cs [new file with mode: 0644]
internals/src/Tizen.Inspections/Interop/Interop.Libraries.cs [new file with mode: 0644]
internals/src/Tizen.Inspections/Tizen.Inspections.csproj [new file with mode: 0644]
internals/src/Tizen.Inspections/Tizen.Inspections.sln [new file with mode: 0644]
internals/src/Tizen.Inspections/Tizen.Inspections/EventReceivedEventArgs.cs [new file with mode: 0644]
internals/src/Tizen.Inspections/Tizen.Inspections/ExceptionFactory.cs [new file with mode: 0644]
internals/src/Tizen.Inspections/Tizen.Inspections/Inspections.cs [new file with mode: 0644]

diff --git a/internals/src/Tizen.Inspections/Interop/Interop.Inspections.cs b/internals/src/Tizen.Inspections/Interop/Interop.Inspections.cs
new file mode 100644 (file)
index 0000000..0d87539
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Runtime.InteropServices;
+using Tizen.Internals;
+
+internal static partial class Interop
+{
+    internal static partial class Inspections
+    {
+        internal static string LogTag = "Tizen.Inspections";
+
+        internal enum InspectionError
+        {
+            None = Tizen.Internals.Errors.ErrorCode.None,
+            InvalidParameter = Tizen.Internals.Errors.ErrorCode.InvalidParameter,
+            IoError = Tizen.Internals.Errors.ErrorCode.IoError,
+            OutOfMemory = Tizen.Internals.Errors.ErrorCode.OutOfMemory,
+            ResourceBusy = Tizen.Internals.Errors.ErrorCode.ResourceBusy,
+            TimedOut = Tizen.Internals.Errors.ErrorCode.TimedOut,
+            NotSupported = Tizen.Internals.Errors.ErrorCode.NotSupported,
+            TryAgain = Tizen.Internals.Errors.ErrorCode.TryAgain,
+            PermissionDenied = Tizen.Internals.Errors.ErrorCode.PermissionDenied
+        };
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void NotificationCallback(IntPtr ctx, IntPtr data);
+
+        [DllImport(Libraries.Diagnostics, EntryPoint = "diagnostics_set_notification_cb")]
+        internal static extern InspectionError SetNotificationCb(NotificationCallback callback, IntPtr data);
+
+        [DllImport(Libraries.Diagnostics, EntryPoint = "diagnostics_unset_notification_cb")]
+        internal static extern InspectionError UnsetNotificationCb();
+
+        [DllImport(Libraries.Diagnostics, EntryPoint = "diagnostics_request_client_data")]
+        internal static extern InspectionError RequestClientData(string client_id, string[] parameters, int params_size, out IntPtr data);
+
+        [DllImport(Libraries.Diagnostics, EntryPoint = "diagnostics_data_read")]
+        internal static extern InspectionError DataRead(IntPtr data, IntPtr buf, uint count, int timeout_ms, out uint bytes_read);
+
+        [DllImport(Libraries.Diagnostics, EntryPoint = "diagnostics_data_destroy")]
+        internal static extern void DataDestroy(IntPtr data);
+
+        [DllImport(Libraries.Diagnostics, EntryPoint = "diagnostics_get_client_id")]
+        internal static extern InspectionError GetClientID(IntPtr ctx, out string client_id);
+
+        [DllImport(Libraries.Diagnostics, EntryPoint = "diagnostics_get_data")]
+        internal static extern InspectionError GetData(IntPtr ctx, string[] parameters, int params_size, out IntPtr data);
+
+        [DllImport(Libraries.Diagnostics, EntryPoint = "diagnostics_destroy")]
+        internal static extern void Destroy(IntPtr data);
+    }
+}
diff --git a/internals/src/Tizen.Inspections/Interop/Interop.Libraries.cs b/internals/src/Tizen.Inspections/Interop/Interop.Libraries.cs
new file mode 100644 (file)
index 0000000..46d3429
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+internal static partial class Interop
+{
+    internal static partial class Libraries
+    {
+        public const string Diagnostics = "libdiagnostics.so.1.0.0";
+    }
+}
\ No newline at end of file
diff --git a/internals/src/Tizen.Inspections/Tizen.Inspections.csproj b/internals/src/Tizen.Inspections/Tizen.Inspections.csproj
new file mode 100644 (file)
index 0000000..459fe88
--- /dev/null
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\src\Tizen\Tizen.csproj" />
+    <ProjectReference Include="..\..\..\src\Tizen.Log\Tizen.Log.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/internals/src/Tizen.Inspections/Tizen.Inspections.sln b/internals/src/Tizen.Inspections/Tizen.Inspections.sln
new file mode 100644 (file)
index 0000000..8a15b7d
--- /dev/null
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tizen.Inspections", "Tizen.Inspections.csproj", "{1292876E-3C29-4AD8-BC89-83BA1842E837}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Any CPU = Debug|Any CPU
+               Debug|x64 = Debug|x64
+               Debug|x86 = Debug|x86
+               Release|Any CPU = Release|Any CPU
+               Release|x64 = Release|x64
+               Release|x86 = Release|x86
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Debug|x64.ActiveCfg = Debug|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Debug|x64.Build.0 = Debug|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Debug|x86.Build.0 = Debug|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Release|Any CPU.Build.0 = Release|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Release|x64.ActiveCfg = Release|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Release|x64.Build.0 = Release|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Release|x86.ActiveCfg = Release|Any CPU
+               {1292876E-3C29-4AD8-BC89-83BA1842E837}.Release|x86.Build.0 = Release|Any CPU
+       EndGlobalSection
+EndGlobal
diff --git a/internals/src/Tizen.Inspections/Tizen.Inspections/EventReceivedEventArgs.cs b/internals/src/Tizen.Inspections/Tizen.Inspections/EventReceivedEventArgs.cs
new file mode 100644 (file)
index 0000000..9257111
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using NativeApi = Interop.Inspections;
+
+namespace Tizen.Inspections
+{
+    /// <summary>
+    /// EventReceivedEventArgs is an extended EventArgs class.
+    /// This class contains event arguments for the EventReceived event from the Inspection class.
+    /// </summary>
+    public class EventReceivedEventArgs : EventArgs
+    {
+        internal EventReceivedEventArgs(InspectionContext ctx)
+        {
+            Context = ctx;
+        }
+
+        /// <summary>
+        /// The inspection context, related to specific crash (or potentially other abnormality).
+        /// </summary>
+        public InspectionContext Context { get; internal set; }
+    }
+}
diff --git a/internals/src/Tizen.Inspections/Tizen.Inspections/ExceptionFactory.cs b/internals/src/Tizen.Inspections/Tizen.Inspections/ExceptionFactory.cs
new file mode 100644 (file)
index 0000000..a26aae6
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+
+namespace Tizen.Inspections
+{
+    internal static class ExceptionFactory
+    {
+        internal static Exception CreateException(Interop.Inspections.InspectionError err)
+        {
+            Tizen.Log.Error(Interop.Inspections.LogTag, $"Error {err}");
+
+            switch (err)
+            {
+                case Interop.Inspections.InspectionError.InvalidParameter:
+                    return new ArgumentException("Invalid parameters provided");
+
+                case Interop.Inspections.InspectionError.IoError:
+                    return new InvalidOperationException("I/O Error occured");
+
+                case Interop.Inspections.InspectionError.OutOfMemory:
+                    return new InvalidOperationException("Invalid operation");
+
+                case Interop.Inspections.InspectionError.ResourceBusy:
+                    return new InvalidOperationException("Resource is busy");
+
+                case Interop.Inspections.InspectionError.TimedOut:
+                    return new InvalidOperationException("Timed out");
+
+                case Interop.Inspections.InspectionError.NotSupported:
+                    return new NotSupportedException("Not supported");
+
+                case Interop.Inspections.InspectionError.TryAgain:
+                    return new InvalidOperationException("Try again");
+
+                case Interop.Inspections.InspectionError.PermissionDenied:
+                    return new InvalidOperationException("Permission denied");
+
+                default:
+                    return new Exception("");
+            }
+        }
+    }
+}
diff --git a/internals/src/Tizen.Inspections/Tizen.Inspections/Inspections.cs b/internals/src/Tizen.Inspections/Tizen.Inspections/Inspections.cs
new file mode 100644 (file)
index 0000000..38b3821
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using NativeApi = Interop.Inspections;
+
+namespace Tizen.Inspections
+{
+    /// <summary>
+    /// The Inspector class is used for requesting client data and receiving inspection events.
+    /// </summary>
+    public static class Inspector
+    {
+        private static NativeApi.NotificationCallback _notificationCallback;
+        private static event EventHandler<EventReceivedEventArgs> _eventReceived;
+
+        /// <summary>
+        /// Event to be invoked when new inspection context arrives.
+        /// </summary>
+        public static event EventHandler<EventReceivedEventArgs> EventReceived
+        {
+            add
+            {
+                if (_eventReceived == null)
+                    SetNotificationCallback();
+                _eventReceived += value;
+            }
+            remove
+            {
+                _eventReceived -= value;
+                if (_eventReceived == null)
+                    UnsetNotificationCallback();
+            }
+        }
+
+        /// <summary>
+        /// Requests other module (app or service) to provide inspection data.
+        /// </summary>
+        /// <param name="moduleID">An ID of module to request.</param>
+        /// <param name="parameters">Array of request parameters passed to the module.</param>
+        /// <returns>
+        /// The instance of InspectionData.
+        /// </returns>
+        /// <remarks>
+        /// This function is permitted only to an app signed by platform level certificates.
+        /// </remarks>
+        public static InspectionData RequestInspectableData(string moduleID, string[] parameters)
+        {
+            if (parameters is null)
+                throw new ArgumentNullException(nameof(parameters));
+
+            var ret = NativeApi.RequestClientData(moduleID, parameters, parameters.Length, out IntPtr data);
+            if (ret != NativeApi.InspectionError.None)
+                throw ExceptionFactory.CreateException(ret);
+
+            return new InspectionData(data);
+        }
+
+        private static void SetNotificationCallback()
+        {
+            _notificationCallback = (IntPtr ctx, IntPtr data) =>
+            {
+                _eventReceived?.Invoke(null, new EventReceivedEventArgs(new InspectionContext(ctx)));
+            };
+
+            var ret = NativeApi.SetNotificationCb(_notificationCallback, IntPtr.Zero);
+            if (ret != NativeApi.InspectionError.None)
+                throw ExceptionFactory.CreateException(ret);
+        }
+
+        private static void UnsetNotificationCallback()
+        {
+            NativeApi.UnsetNotificationCb();
+        }
+    }
+
+    /// <summary>
+    /// The InspectionContext class is used for getting data from the context.
+    /// </summary>
+    public class InspectionContext : IDisposable
+    {
+        private IntPtr _handle = IntPtr.Zero;
+        private bool _disposed = false;
+
+        /// <summary>
+        /// The InspectionContext class constructor.
+        /// </summary>
+        /// <param name="handle">Inspection context received in the EventReceived event.</param>
+        internal InspectionContext(IntPtr handle)
+        {
+            _handle = handle;
+
+            var ret = NativeApi.GetClientID(handle, out string clientID);
+            if (ret != NativeApi.InspectionError.None)
+                throw ExceptionFactory.CreateException(ret);
+
+            ModuleID = clientID;
+        }
+
+        /// <summary>
+        /// Finalizes an instance of the InspectionContext class.
+        /// </summary>
+        ~InspectionContext()
+        {
+            Dispose(false);
+        }
+
+        /// <summary>
+        /// Gets data from the context based on given parameters.
+        /// </summary>
+        /// <param name="parameters">Array of parameters.</param>
+        /// <returns>
+        /// The instance of InspectionData.
+        /// </returns>
+        /// <remarks>
+        /// This function is permitted only to an app signed by platform level certificates.
+        /// </remarks>
+        public InspectionData GetInspectableData(string[] parameters)
+        {
+            if (parameters is null)
+                throw new ArgumentNullException(nameof(parameters));
+
+            var ret = NativeApi.GetData(_handle, parameters, parameters.Length, out IntPtr data);
+            if (ret != NativeApi.InspectionError.None)
+                throw ExceptionFactory.CreateException(ret);
+
+            return new InspectionData(data);
+        }
+
+        /// <summary>
+        /// Stores module ID.
+        /// </summary>
+        public string ModuleID { get; internal set; }
+
+        /// <summary>
+        /// Dispose API for closing the internal resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Dispose API for closing the internal resources.
+        /// </summary>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (_handle != IntPtr.Zero)
+                {
+                    NativeApi.Destroy(_handle);
+                    _handle = IntPtr.Zero;
+                }
+                _disposed = true;
+            }
+        }
+    }
+
+    /// <summary>
+    /// The InspectionData class is used for reading inspection data.
+    /// </summary>
+    public class InspectionData : IDisposable
+    {
+        private IntPtr _handle = IntPtr.Zero;
+        private bool _disposed = false;
+
+        /// <summary>
+        /// The InspectionData class constructor.
+        /// </summary>
+        /// <param name="handle">Inspection data handle.</param>
+        internal InspectionData(IntPtr handle)
+        {
+            _handle = handle;
+        }
+
+        /// <summary>
+        /// Finalizes an instance of the InspectionData class.
+        /// </summary>
+        ~InspectionData()
+        {
+            Dispose(false);
+        }
+
+        /// <summary>
+        /// Reads given number of bytes from inspection data.
+        /// </summary>
+        /// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source.</param>
+        /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
+        /// <param name="count">The maximum number of bytes to be read.</param>
+        /// <returns>
+        /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
+        /// </returns>
+        public int Read(byte[] buffer, int offset, int count)
+        {
+            return ReadUnsafe(buffer, offset, count, 0);
+        }
+
+        /// <summary>
+        /// Reads given number of bytes from inspection data.
+        /// </summary>
+        /// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source.</param>
+        /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
+        /// <param name="count">The maximum number of bytes to be read.</param>
+        /// <param name="timeout">Timeout [ms] for reading requested number of bytes.</param>
+        /// <returns>
+        /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
+        /// </returns>
+        public int Read(byte[] buffer, int offset, int count, int timeout)
+        {
+            return ReadUnsafe(buffer, offset, count, timeout);
+        }
+
+        private unsafe int ReadUnsafe(byte[] buffer, int offset, int count, int timeout)
+        {
+            var length = Convert.ToUInt32(count);
+            uint bytes_read = 0;
+
+            if (buffer == null)
+                throw new ArgumentNullException(nameof(buffer));
+
+            if (offset + count > buffer.Length)
+                throw new ArgumentException("The sum of offset and count is larger than the buffer length");
+
+            if (offset < 0)
+                throw new ArgumentOutOfRangeException(nameof(offset));
+
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            fixed (byte* p = &buffer[offset])
+            {
+                IntPtr ptr = (IntPtr)p;
+                var ret = NativeApi.DataRead(_handle, ptr, length, timeout, out bytes_read);
+                if (ret < NativeApi.InspectionError.None)
+                    throw ExceptionFactory.CreateException(ret);
+            }
+
+            return (int)bytes_read;
+        }
+
+        /// <summary>
+        /// Dispose API for closing the internal resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Dispose API for closing the internal resources.
+        /// </summary>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (_handle != IntPtr.Zero)
+                {
+                    NativeApi.DataDestroy(_handle);
+                    _handle = IntPtr.Zero;
+                }
+                _disposed = true;
+            }
+        }
+    }
+}