[Sensor] Sync with API7 branch (#1303)
[platform/core/csapi/tizenfx.git] / src / Tizen.Sensor / Tizen.Sensor / Sensor.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 Tizen.System;
19
20 namespace Tizen.Sensor
21 {
22     internal static class Globals
23     {
24         internal const string LogTag = "Tizen.Sensor";
25     }
26
27     /// <summary>
28     /// The Sensor class is used for storing the hardware information about a particular sensor.
29     /// </summary>
30     /// <since_tizen> 3 </since_tizen>
31     public abstract class Sensor : IDisposable
32     {
33         private string _name;
34         private string _vendor;
35         private float _minValue;
36         private float _maxValue;
37         private float _resolution;
38         private int _minInterval;
39         private int _fifoCount;
40         private int _maxBatchCount;
41         private bool _isSensing = false;
42         private bool _disposed = false;
43         private TimeSpan _timeSpan;
44         private uint _interval = 0;
45         private uint _maxBatchLatency = 0;
46         private SensorPausePolicy _pausePolicy = SensorPausePolicy.None;
47         private IntPtr _sensorHandle = IntPtr.Zero;
48         private IntPtr _listenerHandle = IntPtr.Zero;
49
50         /// <summary>
51         /// Read a sensor data synchronously.
52         /// </summary>
53         internal abstract void ReadData();
54         internal abstract SensorType GetSensorType();
55         internal abstract void EventListenStart();
56         internal abstract void EventListenStop();
57
58         internal Sensor(uint index)
59         {
60             SensorType type = GetSensorType();
61             GetHandleList(type, index);
62             if (CheckSensorHandle())
63             {
64                 CreateListener();
65                 GetProperty();
66             }
67         }
68
69         /// <summary>
70         /// Destroy the Sensor object.
71         /// </summary>
72         ~Sensor()
73         {
74             Dispose(false);
75         }
76
77         /// <summary>
78         /// Property: Gets the name of the sensor.
79         /// </summary>
80         /// <since_tizen> 3 </since_tizen>
81         /// <value> The name of the sensor. </value>
82         public string Name
83         {
84             get
85             {
86                 Log.Info(Globals.LogTag, "Getting the sensor name");
87                 return _name;
88             }
89         }
90
91         /// <summary>
92         /// Property: Gets the vendor.
93         /// </summary>
94         /// <since_tizen> 3 </since_tizen>
95         /// <value> The vendor name of the sensor. </value>
96         public string Vendor
97         {
98             get
99             {
100                 Log.Info(Globals.LogTag, "Getting the sensor vendor name");
101                 return _vendor;
102             }
103         }
104
105         /// <summary>
106         /// Property: Gets the minimum value of the range of the sensor data.
107         /// </summary>
108         /// <since_tizen> 3 </since_tizen>
109         /// <value> The lower bound of the range of the sensor reading. </value>
110         public float MinValue
111         {
112             get
113             {
114                 Log.Info(Globals.LogTag, "Getting the min value of the sensor");
115                 return _minValue;
116             }
117         }
118
119         /// <summary>
120         /// Property: Gets the maximum value of the range of the sensor data.
121         /// </summary>
122         /// <since_tizen> 3 </since_tizen>
123         /// <value> The upper bound of the range of the sensor reading. </value>
124         public float MaxValue
125         {
126             get
127             {
128                 Log.Info(Globals.LogTag, "Getting the max value of the sensor");
129                 return _maxValue;
130             }
131         }
132
133         /// <summary>
134         /// Property: Gets the resolution.
135         /// </summary>
136         /// <since_tizen> 3 </since_tizen>
137         /// <value> The resolution. </value>
138         public float Resolution
139         {
140             get
141             {
142                 Log.Info(Globals.LogTag, "Getting the resolution of the sensor");
143                 return _resolution;
144             }
145         }
146
147         /// <summary>
148         /// Property: Gets the minimum interval.
149         /// </summary>
150         /// <since_tizen> 3 </since_tizen>
151         /// <value> The minimum update interval. </value>
152         public int MinInterval
153         {
154             get
155             {
156                 Log.Info(Globals.LogTag, "Getting the min interval for the sensor");
157                 return _minInterval;
158             }
159         }
160
161         /// <summary>
162         /// Property: Gets the FIFO count.
163         /// </summary>
164         /// <since_tizen> 3 </since_tizen>
165         /// <value> The size of the hardware FIFO. </value>
166         public int FifoCount
167         {
168             get
169             {
170                 Log.Info(Globals.LogTag, "Getting the fifo count of the sensor");
171                 return _fifoCount;
172             }
173         }
174
175         /// <summary>
176         /// Property: Gets the maximum batch count.
177         /// </summary>
178         /// <since_tizen> 3 </since_tizen>
179         /// <value> The maximum batch count. </value>
180         public int MaxBatchCount
181         {
182             get
183             {
184                 Log.Info(Globals.LogTag, "Getting the max batch count of the sensor");
185                 return _maxBatchCount;
186             }
187         }
188
189         /// <summary>
190         /// Sets the interval of the sensor for the sensor data event.
191         /// Callbacks will be called at the frequency of this interval.
192         /// </summary>
193         /// <since_tizen> 3 </since_tizen>
194         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
195         /// <value> The interval of the sensor. </value>
196         public uint Interval
197         {
198             set
199             {
200                 Log.Info(Globals.LogTag, "Setting the interval of the sensor");
201                 _interval = value;
202                 SetInterval();
203             }
204             get
205             {
206                 Log.Info(Globals.LogTag, "Getting the interval of the sensor");
207                 return _interval;
208             }
209         }
210
211         /// <summary>
212         /// Sets the maximum batch latency for the sensor corresponding to the sensor data event.
213         /// </summary>
214         /// <since_tizen> 3 </since_tizen>
215         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
216         /// <value> The maximum batch latency. </value>
217         public uint MaxBatchLatency
218         {
219             set
220             {
221                 Log.Info(Globals.LogTag, "Setting the max batch latency of the sensor");
222                 _maxBatchLatency = value;
223                 SetMaxBatchLatency();
224             }
225             get
226             {
227                 Log.Info(Globals.LogTag, "Getting the max batch latency of the sensor");
228                 return _maxBatchLatency;
229             }
230         }
231
232         /// <summary>
233         /// Sets the pause policy of the sensor.
234         /// </summary>
235         /// <since_tizen> 3 </since_tizen>
236         /// <value>The pause policy.</value>
237         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
238         /// <value> The pause policy. </value>
239         public SensorPausePolicy PausePolicy
240         {
241             set
242             {
243                 Log.Info(Globals.LogTag, "Setting the pause policy of the sensor");
244                 _pausePolicy = value;
245                 SetAttribute(SensorAttribute.PausePolicy, (int)_pausePolicy);
246             }
247             get
248             {
249                 Log.Info(Globals.LogTag, "Getting the pause policy of the sensor");
250                 return _pausePolicy;
251             }
252         }
253
254         /// <summary>
255         /// Gets or sets the time span.
256         /// </summary>
257         /// <since_tizen> 3 </since_tizen>
258         /// <value> The time span. </value>
259         public TimeSpan TimeSpan
260         {
261             set
262             {
263                 Log.Info(Globals.LogTag, "Setting the timespan of the sensor values");
264                 _timeSpan = value;
265             }
266             get
267             {
268                 Log.Info(Globals.LogTag, "Getting the timespan of the sensor values");
269                 return _timeSpan;
270             }
271         }
272
273         /// <summary>
274         /// Indicates whether this sensor is sensing.
275         /// </summary>
276         /// <since_tizen> 3 </since_tizen>
277         /// <value><c>true</c> if this sensor is sensing; otherwise <c>false</c>.</value>
278         public bool IsSensing
279         {
280             get
281             {
282                 Log.Info(Globals.LogTag, "Checking if the sensor is started");
283                 return _isSensing;
284             }
285         }
286
287         internal IntPtr ListenerHandle
288         {
289             get
290             {
291                 return _listenerHandle;
292             }
293         }
294
295         internal static bool CheckIfSupported(SensorType type, String key)
296         {
297             bool isSupported = false;
298             bool error = Information.TryGetValue(key, out isSupported);
299
300             if (!error || !isSupported)
301             {
302                 Log.Error(Globals.LogTag, "Error checking if sensor is supported(systeminfo)");
303                 return false;
304             }
305
306             int ret = Interop.SensorManager.SensorIsSupported(type, out isSupported);
307             if (ret != (int)SensorError.None)
308             {
309                 Log.Error(Globals.LogTag, "Error checking if sensor is supported");
310                 isSupported = false;
311             }
312
313             return isSupported;
314         }
315
316         /// <summary>
317         /// Starts the sensor.
318         /// After this, event handlers will start receiving events.
319         /// </summary>
320         /// <since_tizen> 3 </since_tizen>
321         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
322         public void Start()
323         {
324             Log.Info(Globals.LogTag, "Starting the sensor");
325             if (CheckListenerHandle())
326             {
327                 int error = Interop.SensorListener.StartListener(_listenerHandle);
328                 if (error != (int)SensorError.None)
329                 {
330                     Log.Error(Globals.LogTag, "Error starting sensor");
331                     throw SensorErrorFactory.CheckAndThrowException(error, "Unable to Start Sensor Listener");
332                 }
333                 ReadData();
334                 EventListenStart();
335                 _isSensing = true;
336                 Log.Info(Globals.LogTag, "Sensor started");
337             }
338         }
339
340         /// <summary>
341         /// Stops the sensor.
342         /// After this, event handlers will stop receiving events.
343         /// </summary>
344         /// <since_tizen> 3 </since_tizen>
345         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
346         public void Stop()
347         {
348             Log.Info(Globals.LogTag, "Stopping the sensor");
349             if (_isSensing)
350             {
351                 int error = Interop.SensorListener.StopListener(_listenerHandle);
352                 if (error != (int)SensorError.None)
353                 {
354                     Log.Error(Globals.LogTag, "Error stopping the sensor");
355                     throw SensorErrorFactory.CheckAndThrowException(error, "Unable to Stop Sensor Listener");
356                 }
357                 EventListenStop();
358                 _isSensing = false;
359                 Log.Info(Globals.LogTag, "Sensor stopped");
360             }
361         }
362
363         /// <summary>
364         /// Destroy the current object.
365         /// </summary>
366         /// <since_tizen> 3 </since_tizen>
367         public void Dispose()
368         {
369             Dispose(true);
370             GC.SuppressFinalize(this);
371         }
372
373         /// <summary>
374         /// Releases all resources currently used by this instance.
375         /// </summary>
376         /// <param name="disposing">
377         /// true if managed resources should be disposed
378         /// otherwise, false.
379         /// </param>
380         /// <since_tizen> 3 </since_tizen>
381         protected virtual void Dispose(bool disposing)
382         {
383             if (_disposed)
384                 return;
385
386             DestroyHandles();
387             _disposed = true;
388         }
389
390         internal void SetAttribute(SensorAttribute attribute, int option)
391         {
392             if (CheckListenerHandle())
393             {
394                 int error = Interop.SensorListener.SetAttribute(_listenerHandle, attribute, option);
395                 if (error != (int)SensorError.None)
396                 {
397                     Log.Error(Globals.LogTag, "Error setting sensor pause policy");
398                     throw SensorErrorFactory.CheckAndThrowException(error, "Setting Sensor.PausePolicy Failed");
399                 }
400             }
401         }
402
403         private void GetHandleList(SensorType type, uint index)
404         {
405             IntPtr list;
406             IntPtr[] sensorList;
407             int count;
408             int error = Interop.SensorManager.GetSensorList(type, out list, out count);
409             if (error != (int)SensorError.None)
410             {
411                 Log.Error(Globals.LogTag, "Error getting sensor list");
412                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.GetSensorList Failed");
413             }
414             sensorList = Interop.IntPtrToIntPtrArray(list, count);
415             _sensorHandle = sensorList[index];
416             Interop.Libc.Free(list);
417         }
418
419         private void GetProperty()
420         {
421             int error = (int)SensorError.None;
422
423             error = Interop.Sensor.GetName(_sensorHandle, out _name);
424             if (error != (int)SensorError.None)
425             {
426                 Log.Error(Globals.LogTag, "Error getting sensor name");
427                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.Name Failed");
428             }
429
430             error = Interop.Sensor.GetVendor(_sensorHandle, out _vendor);
431             if (error != (int)SensorError.None)
432             {
433                 Log.Error(Globals.LogTag, "Error getting sensor vendor name");
434                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.Vendor Failed");
435             }
436
437             error = Interop.Sensor.GetMinRange(_sensorHandle, out _minValue);
438             if (error != (int)SensorError.None)
439             {
440                 Log.Error(Globals.LogTag, "Error getting sensor min value");
441                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.MinValue Failed");
442             }
443
444             error = Interop.Sensor.GetMaxRange(_sensorHandle, out _maxValue);
445             if (error != (int)SensorError.None)
446             {
447                 Log.Error(Globals.LogTag, "Error getting sensor max value");
448                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.MaxValue Failed");
449             }
450
451             error = Interop.Sensor.GetResolution(_sensorHandle, out _resolution);
452             if (error != (int)SensorError.None)
453             {
454                 Log.Error(Globals.LogTag, "Error getting sensor resolution");
455                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.Resolution Failed");
456             }
457
458             error = Interop.Sensor.GetMinInterval(_sensorHandle, out _minInterval);
459             if (error != (int)SensorError.None)
460             {
461                 Log.Error(Globals.LogTag, "Error getting sensor min interval");
462                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.MinInterval Failed");
463             }
464
465             error = Interop.Sensor.GetFifoCount(_sensorHandle, out _fifoCount);
466             if (error != (int)SensorError.None)
467             {
468                 Log.Error(Globals.LogTag, "Error getting sensor fifo count");
469                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.FifoCount Failed");
470             }
471
472             error = Interop.Sensor.GetMaxBatchCount(_sensorHandle, out _maxBatchCount);
473             if (error != (int)SensorError.None)
474             {
475                 Log.Error(Globals.LogTag, "Error getting sensor max batch count");
476                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.MaxBatchCount Failed");
477             }
478         }
479
480         private void CreateListener()
481         {
482             int error = Interop.SensorListener.CreateListener(_sensorHandle, out _listenerHandle);
483             if (error != (int)SensorError.None)
484             {
485                 Log.Error(Globals.LogTag, "Error cerating sensor listener handle");
486                 throw SensorErrorFactory.CheckAndThrowException(error, "Sensor.CreateListener Failed");
487             }
488         }
489
490         private void SetInterval()
491         {
492             if (CheckListenerHandle())
493             {
494                 if (_isSensing)
495                 {
496                     int error = Interop.SensorListener.SetInterval(_listenerHandle, _interval);
497                     if (error != (int)SensorError.None)
498                     {
499                         Log.Error(Globals.LogTag, "Error setting sensor interval");
500                         throw SensorErrorFactory.CheckAndThrowException(error, "Setting Sensor.SetInterval Failed");
501                     }
502                 }
503             }
504         }
505
506         private void SetMaxBatchLatency()
507         {
508             if (CheckListenerHandle())
509             {
510                 int error = Interop.SensorListener.SetMaxBatchLatency(_listenerHandle, _maxBatchLatency);
511                 if (error != (int)SensorError.None)
512                 {
513                     Log.Error(Globals.LogTag, "Error setting max batch latency");
514                     throw SensorErrorFactory.CheckAndThrowException(error, "Setting Sensor.MaxBatchLatency Failed");
515                 }
516             }
517         }
518
519         private bool CheckListenerHandle()
520         {
521             bool result = false;
522             if (_listenerHandle != IntPtr.Zero)
523             {
524                 result = true;
525             }
526             else
527             {
528                 Log.Error(Globals.LogTag, "Sensor listener handle is null");
529                 throw new ArgumentException("Invalid Parameter: Sensor is null");
530             }
531             return result;
532         }
533
534         private bool CheckSensorHandle()
535         {
536             bool result = false;
537             if (_sensorHandle != IntPtr.Zero)
538             {
539                 result = true;
540             }
541             else
542             {
543                 Log.Error(Globals.LogTag, "Sensor handle is null");
544                 throw new ArgumentException("Invalid Parameter: Sensor is null");
545             }
546             return result;
547         }
548
549         private void DestroyHandles()
550         {
551             Interop.SensorListener.DestroyListener(_listenerHandle);
552         }
553     }
554 }