38b3821859212e3235bcc22f335a1796d443a4de
[platform/core/csapi/tizenfx.git] / internals / src / Tizen.Inspections / Tizen.Inspections / Inspections.cs
1 /*
2 * Copyright (c) 2020 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 NativeApi = Interop.Inspections;
19
20 namespace Tizen.Inspections
21 {
22     /// <summary>
23     /// The Inspector class is used for requesting client data and receiving inspection events.
24     /// </summary>
25     public static class Inspector
26     {
27         private static NativeApi.NotificationCallback _notificationCallback;
28         private static event EventHandler<EventReceivedEventArgs> _eventReceived;
29
30         /// <summary>
31         /// Event to be invoked when new inspection context arrives.
32         /// </summary>
33         public static event EventHandler<EventReceivedEventArgs> EventReceived
34         {
35             add
36             {
37                 if (_eventReceived == null)
38                     SetNotificationCallback();
39                 _eventReceived += value;
40             }
41             remove
42             {
43                 _eventReceived -= value;
44                 if (_eventReceived == null)
45                     UnsetNotificationCallback();
46             }
47         }
48
49         /// <summary>
50         /// Requests other module (app or service) to provide inspection data.
51         /// </summary>
52         /// <param name="moduleID">An ID of module to request.</param>
53         /// <param name="parameters">Array of request parameters passed to the module.</param>
54         /// <returns>
55         /// The instance of InspectionData.
56         /// </returns>
57         /// <remarks>
58         /// This function is permitted only to an app signed by platform level certificates.
59         /// </remarks>
60         public static InspectionData RequestInspectableData(string moduleID, string[] parameters)
61         {
62             if (parameters is null)
63                 throw new ArgumentNullException(nameof(parameters));
64
65             var ret = NativeApi.RequestClientData(moduleID, parameters, parameters.Length, out IntPtr data);
66             if (ret != NativeApi.InspectionError.None)
67                 throw ExceptionFactory.CreateException(ret);
68
69             return new InspectionData(data);
70         }
71
72         private static void SetNotificationCallback()
73         {
74             _notificationCallback = (IntPtr ctx, IntPtr data) =>
75             {
76                 _eventReceived?.Invoke(null, new EventReceivedEventArgs(new InspectionContext(ctx)));
77             };
78
79             var ret = NativeApi.SetNotificationCb(_notificationCallback, IntPtr.Zero);
80             if (ret != NativeApi.InspectionError.None)
81                 throw ExceptionFactory.CreateException(ret);
82         }
83
84         private static void UnsetNotificationCallback()
85         {
86             NativeApi.UnsetNotificationCb();
87         }
88     }
89
90     /// <summary>
91     /// The InspectionContext class is used for getting data from the context.
92     /// </summary>
93     public class InspectionContext : IDisposable
94     {
95         private IntPtr _handle = IntPtr.Zero;
96         private bool _disposed = false;
97
98         /// <summary>
99         /// The InspectionContext class constructor.
100         /// </summary>
101         /// <param name="handle">Inspection context received in the EventReceived event.</param>
102         internal InspectionContext(IntPtr handle)
103         {
104             _handle = handle;
105
106             var ret = NativeApi.GetClientID(handle, out string clientID);
107             if (ret != NativeApi.InspectionError.None)
108                 throw ExceptionFactory.CreateException(ret);
109
110             ModuleID = clientID;
111         }
112
113         /// <summary>
114         /// Finalizes an instance of the InspectionContext class.
115         /// </summary>
116         ~InspectionContext()
117         {
118             Dispose(false);
119         }
120
121         /// <summary>
122         /// Gets data from the context based on given parameters.
123         /// </summary>
124         /// <param name="parameters">Array of parameters.</param>
125         /// <returns>
126         /// The instance of InspectionData.
127         /// </returns>
128         /// <remarks>
129         /// This function is permitted only to an app signed by platform level certificates.
130         /// </remarks>
131         public InspectionData GetInspectableData(string[] parameters)
132         {
133             if (parameters is null)
134                 throw new ArgumentNullException(nameof(parameters));
135
136             var ret = NativeApi.GetData(_handle, parameters, parameters.Length, out IntPtr data);
137             if (ret != NativeApi.InspectionError.None)
138                 throw ExceptionFactory.CreateException(ret);
139
140             return new InspectionData(data);
141         }
142
143         /// <summary>
144         /// Stores module ID.
145         /// </summary>
146         public string ModuleID { get; internal set; }
147
148         /// <summary>
149         /// Dispose API for closing the internal resources.
150         /// </summary>
151         public void Dispose()
152         {
153             Dispose(true);
154             GC.SuppressFinalize(this);
155         }
156
157         /// <summary>
158         /// Dispose API for closing the internal resources.
159         /// </summary>
160         protected virtual void Dispose(bool disposing)
161         {
162             if (!_disposed)
163             {
164                 if (_handle != IntPtr.Zero)
165                 {
166                     NativeApi.Destroy(_handle);
167                     _handle = IntPtr.Zero;
168                 }
169                 _disposed = true;
170             }
171         }
172     }
173
174     /// <summary>
175     /// The InspectionData class is used for reading inspection data.
176     /// </summary>
177     public class InspectionData : IDisposable
178     {
179         private IntPtr _handle = IntPtr.Zero;
180         private bool _disposed = false;
181
182         /// <summary>
183         /// The InspectionData class constructor.
184         /// </summary>
185         /// <param name="handle">Inspection data handle.</param>
186         internal InspectionData(IntPtr handle)
187         {
188             _handle = handle;
189         }
190
191         /// <summary>
192         /// Finalizes an instance of the InspectionData class.
193         /// </summary>
194         ~InspectionData()
195         {
196             Dispose(false);
197         }
198
199         /// <summary>
200         /// Reads given number of bytes from inspection data.
201         /// </summary>
202         /// <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>
203         /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
204         /// <param name="count">The maximum number of bytes to be read.</param>
205         /// <returns>
206         /// 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.
207         /// </returns>
208         public int Read(byte[] buffer, int offset, int count)
209         {
210             return ReadUnsafe(buffer, offset, count, 0);
211         }
212
213         /// <summary>
214         /// Reads given number of bytes from inspection data.
215         /// </summary>
216         /// <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>
217         /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
218         /// <param name="count">The maximum number of bytes to be read.</param>
219         /// <param name="timeout">Timeout [ms] for reading requested number of bytes.</param>
220         /// <returns>
221         /// 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.
222         /// </returns>
223         public int Read(byte[] buffer, int offset, int count, int timeout)
224         {
225             return ReadUnsafe(buffer, offset, count, timeout);
226         }
227
228         private unsafe int ReadUnsafe(byte[] buffer, int offset, int count, int timeout)
229         {
230             var length = Convert.ToUInt32(count);
231             uint bytes_read = 0;
232
233             if (buffer == null)
234                 throw new ArgumentNullException(nameof(buffer));
235
236             if (offset + count > buffer.Length)
237                 throw new ArgumentException("The sum of offset and count is larger than the buffer length");
238
239             if (offset < 0)
240                 throw new ArgumentOutOfRangeException(nameof(offset));
241
242             if (count < 0)
243                 throw new ArgumentOutOfRangeException(nameof(count));
244
245             fixed (byte* p = &buffer[offset])
246             {
247                 IntPtr ptr = (IntPtr)p;
248                 var ret = NativeApi.DataRead(_handle, ptr, length, timeout, out bytes_read);
249                 if (ret < NativeApi.InspectionError.None)
250                     throw ExceptionFactory.CreateException(ret);
251             }
252
253             return (int)bytes_read;
254         }
255
256         /// <summary>
257         /// Dispose API for closing the internal resources.
258         /// </summary>
259         public void Dispose()
260         {
261             Dispose(true);
262             GC.SuppressFinalize(this);
263         }
264
265         /// <summary>
266         /// Dispose API for closing the internal resources.
267         /// </summary>
268         protected virtual void Dispose(bool disposing)
269         {
270             if (!_disposed)
271             {
272                 if (_handle != IntPtr.Zero)
273                 {
274                     NativeApi.DataDestroy(_handle);
275                     _handle = IntPtr.Zero;
276                 }
277                 _disposed = true;
278             }
279         }
280     }
281 }