Fix Coverity issues
[platform/core/uifw/dali-adaptor.git] / adaptors / tizen / tilt-sensor-impl-tizen.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
18 // CLASS HEADER
19 #include <tizen/tilt-sensor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/integration-api/debug.h>
25
26 // INTERNAL INCLUDES
27 #include <singleton-service-impl.h>
28
29 namespace // unnamed namespace
30 {
31 const char* const SIGNAL_TILTED = "tilted";
32
33 const float MAX_ORIENTATION_ROLL_VALUE = 90.f;
34 const float MAX_ORIENTATION_PITCH_VALUE = 180.f;
35 const float MAX_ACCELEROMETER_VALUE = 9.8f;
36
37 // Type Registration
38 Dali::BaseHandle Create()
39 {
40   return Dali::Internal::Adaptor::TiltSensor::Get();
41 }
42
43 Dali::TypeRegistration typeRegistration( typeid(Dali::TiltSensor), typeid(Dali::BaseHandle), Create );
44
45 Dali::SignalConnectorType signalConnector1( typeRegistration, SIGNAL_TILTED, Dali::Internal::Adaptor::TiltSensor::DoConnectSignal );
46
47 } // unnamed namespace
48
49 namespace Dali
50 {
51
52 namespace Internal
53 {
54
55 namespace Adaptor
56 {
57
58 #ifdef SENSOR_ENABLED
59 static void sensor_changed_cb (sensor_h sensor, sensor_event_s *event, void *user_data)
60 {
61   TiltSensor* tiltSensor = reinterpret_cast< TiltSensor* >( user_data );
62
63   if(tiltSensor)
64   {
65     tiltSensor->Update(event);
66   }
67
68   return;
69 }
70
71 static std::string get_sensor_error_string(int errorValue)
72 {
73   std::string ret;
74
75   switch(errorValue)
76   {
77     case SENSOR_ERROR_IO_ERROR:
78       ret = "SENSOR_ERROR_IO_ERROR";
79       break;
80     case SENSOR_ERROR_INVALID_PARAMETER:
81       ret = "SENSOR_ERROR_INVALID_PARAMETER";
82       break;
83     case SENSOR_ERROR_NOT_SUPPORTED:
84       ret = "SENSOR_ERROR_NOT_SUPPORTED";
85       break;
86     case SENSOR_ERROR_PERMISSION_DENIED:
87       ret = "SENSOR_ERROR_PERMISSION_DENIED";
88       break;
89     case SENSOR_ERROR_OUT_OF_MEMORY:
90       ret = "SENSOR_ERROR_OUT_OF_MEMORY";
91       break;
92     case SENSOR_ERROR_NOT_NEED_CALIBRATION:
93       ret = "SENSOR_ERROR_NOT_NEED_CALIBRATION";
94       break;
95     case SENSOR_ERROR_OPERATION_FAILED:
96       ret = "SENSOR_ERROR_OPERATION_FAILED";
97       break;
98   }
99
100   return ret;
101 }
102 #endif
103
104 Dali::TiltSensor TiltSensor::New()
105 {
106   Dali::TiltSensor sensor = Dali::TiltSensor(new TiltSensor());
107
108   return sensor;
109 }
110
111 Dali::TiltSensor TiltSensor::Get()
112 {
113   Dali::TiltSensor sensor;
114
115   Dali::SingletonService service( SingletonService::Get() );
116
117   if ( service )
118   {
119     // Check whether the keyboard focus manager is already created
120     Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::TiltSensor ) );
121     if(handle)
122     {
123       // If so, downcast the handle of singleton to keyboard focus manager
124       sensor = Dali::TiltSensor( dynamic_cast< TiltSensor* >( handle.GetObjectPtr() ) );
125     }
126     else
127     {
128       // Create a singleton instance
129       sensor = TiltSensor::New();
130       service.Register( typeid( sensor ), sensor );
131       handle = sensor;
132     }
133   }
134
135   return sensor;
136 }
137
138 TiltSensor::~TiltSensor()
139 {
140   Disconnect();
141 }
142
143 bool TiltSensor::Connect()
144 {
145 #ifdef SENSOR_ENABLED
146   if(mState != DISCONNECTED)
147   {
148     Stop();
149     Disconnect();
150   }
151
152   const int interval = 1000/mFrequencyHertz;
153
154   int ret = 0;
155   bool isSupported = false;
156
157   // try to use Orientation sensor at first for less power consumption.
158   ret = sensor_is_supported(SENSOR_ORIENTATION, &isSupported);
159
160   if(ret < 0)
161   {
162     DALI_LOG_ERROR("sensor_is_supported() failed : %s\n", get_sensor_error_string(ret).c_str());
163     return false;
164   }
165
166   if(isSupported == true)
167   {
168     mSensorType = SENSOR_ORIENTATION;
169   }
170   else
171   {
172     DALI_LOG_ERROR("sensor does not support SENSOR_ORIENTATION\n");
173
174     ret = sensor_is_supported(SENSOR_ACCELEROMETER, &isSupported);
175
176     if(ret < 0)
177     {
178       DALI_LOG_ERROR("sensor_is_supported() failed : %s\n", get_sensor_error_string(ret).c_str());
179       return false;
180     }
181
182     if(isSupported == false)
183     {
184       DALI_LOG_ERROR("sensor does not support both SENSOR_ORIENTATION and SENSOR_ACCELEROMETER\n");
185       return false;
186     }
187
188     mSensorType = SENSOR_ACCELEROMETER;
189   }
190
191   ret = sensor_get_default_sensor(mSensorType, &mSensor); /* mSensor should not be deleted */
192
193   if(ret < 0)
194   {
195     DALI_LOG_ERROR("sensor_get_default_sensor() failed : %s\n", get_sensor_error_string(ret).c_str());
196     return false;
197   }
198
199   sensor_create_listener(mSensor, &mSensorListener);
200   sensor_listener_set_event_cb(mSensorListener, interval, sensor_changed_cb, this);
201   sensor_listener_set_interval(mSensorListener, interval);
202
203   sensor_listener_set_option(mSensorListener, SENSOR_OPTION_DEFAULT /* Not receive data when LCD is off and in power save mode */);
204
205   mState = CONNECTED;
206
207   return true;
208 #endif
209
210   return false;
211 }
212
213 void TiltSensor::Disconnect()
214 {
215   if(mSensorListener)
216   {
217     if(mState == STARTED)
218     {
219       Stop();
220     }
221
222     if(mState == STOPPED || mState == CONNECTED)
223     {
224 #ifdef SENSOR_ENABLED
225       sensor_listener_unset_event_cb(mSensorListener);
226       sensor_listener_stop(mSensorListener);
227       sensor_destroy_listener(mSensorListener);
228 #endif
229       mSensor = NULL;
230       mSensorListener = NULL;
231       mState = DISCONNECTED;
232     }
233   }
234 }
235
236 bool TiltSensor::Start()
237 {
238   if( mSensorListener && ( mState == CONNECTED || mState == STOPPED ) )
239   {
240 #ifdef SENSOR_ENABLED
241     int ret = 0;
242     ret = sensor_listener_start(mSensorListener);
243     if(ret != SENSOR_ERROR_NONE)
244     {
245       DALI_LOG_ERROR("sensor_listener_start() failed : %s\n", get_sensor_error_string(ret).c_str());
246       Disconnect();
247       return false;
248     }
249
250     mState = STARTED;
251     return true;
252 #endif
253   }
254   else
255   {
256     if( mState == STARTED )
257     {
258       DALI_LOG_ERROR("TiltSensor is already started. Current state [%d]\n", mState);
259     }
260     else
261     {
262       // mState is DISCONNECTED
263       DALI_LOG_ERROR("TiltSensor is disconnected. Current state [%d]\n", mState);
264     }
265     return false;
266   }
267   return false;
268 }
269
270 void TiltSensor::Stop()
271 {
272 #ifdef SENSOR_ENABLED
273   if(mSensorListener && mState == STARTED)
274   {
275     sensor_listener_stop( mSensorListener );
276     mState = STOPPED;
277   }
278 #endif
279 }
280
281 bool TiltSensor::IsStarted() const
282 {
283   return ( mSensorListener && mState == STARTED );
284 }
285
286 float TiltSensor::GetRoll() const
287 {
288   return mRoll;
289 }
290
291 float TiltSensor::GetPitch() const
292 {
293   return mPitch;
294 }
295
296 Quaternion TiltSensor::GetRotation() const
297 {
298   return mRotation;
299 }
300
301 TiltSensor::TiltedSignalType& TiltSensor::TiltedSignal()
302 {
303   return mTiltedSignal;
304 }
305
306 void TiltSensor::SetUpdateFrequency( float frequencyHertz )
307 {
308   DALI_ASSERT_ALWAYS( frequencyHertz > 0.0f && "Frequency must have a positive value" );
309
310   if ( fabsf(mFrequencyHertz - frequencyHertz) >= GetRangedEpsilon(mFrequencyHertz, frequencyHertz) )
311   {
312     mFrequencyHertz = frequencyHertz;
313
314 #ifdef SENSOR_ENABLED
315     if(mSensorListener)
316     {
317       const int interval = 1000/mFrequencyHertz;
318       sensor_listener_set_interval(mSensorListener, interval);
319     }
320 #endif
321   }
322 }
323
324 float TiltSensor::GetUpdateFrequency() const
325 {
326   return mFrequencyHertz;
327 }
328
329 void TiltSensor::SetRotationThreshold(Radian rotationThreshold)
330 {
331   mRotationThreshold = rotationThreshold;
332 }
333
334 Radian TiltSensor::GetRotationThreshold() const
335 {
336   return mRotationThreshold;
337 }
338
339 bool TiltSensor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
340 {
341   bool connected( true );
342   TiltSensor* sensor = dynamic_cast<TiltSensor*>( object );
343
344   if( sensor && SIGNAL_TILTED == signalName )
345   {
346     sensor->TiltedSignal().Connect( tracker, functor );
347   }
348   else
349   {
350     // signalName does not match any signal
351     connected = false;
352   }
353
354   return connected;
355 }
356
357 TiltSensor::TiltSensor()
358 : mState(DISCONNECTED),
359   mFrequencyHertz( Dali::TiltSensor::DEFAULT_UPDATE_FREQUENCY ),
360   mSensor( NULL ),
361   mSensorListener( NULL ),
362   mRoll( 0.0f ),
363   mPitch( 0.0f ),
364   mRotation( Radian(0.0f), Vector3::YAXIS ),
365   mRotationThreshold( 0.0f )
366 {
367   // connect sensor
368   Connect();
369 }
370
371 #ifdef SENSOR_ENABLED
372 void TiltSensor::Update(sensor_event_s *event)
373 {
374   Radian newRoll( 0.0f );
375   Radian newPitch( 0.0f );
376   Quaternion newRotation;
377
378   if(mSensorType == SENSOR_ORIENTATION)
379   {
380     newRoll  = Clamp( float(event->values[2]  / MAX_ORIENTATION_ROLL_VALUE)  /* -90 < roll < 90 */, -1.0f/*min*/, 1.0f/*max*/ );
381     newPitch = Clamp( float(event->values[1] / MAX_ORIENTATION_PITCH_VALUE) /* -180 < pitch < 180 */, -1.0f/*min*/, 1.0f/*max*/ );
382   }
383   else if(mSensorType == SENSOR_ACCELEROMETER)
384   {
385     newRoll  = Clamp( float(event->values[0] / MAX_ACCELEROMETER_VALUE), -1.0f/*min*/, 1.0f/*max*/ );
386     newPitch = Clamp( float(event->values[1] / MAX_ACCELEROMETER_VALUE), -1.0f/*min*/, 1.0f/*max*/ );
387   }
388   else
389   {
390     DALI_LOG_ERROR("Invalid sensor type\n");
391     return;
392   }
393
394   newRotation = Quaternion( Radian( newRoll * Math::PI * -0.5f ), Vector3::YAXIS ) *
395               Quaternion( Radian( newPitch * Math::PI * -0.5f ), Vector3::XAXIS );
396
397   Radian angle(Quaternion::AngleBetween(newRotation, mRotation));
398
399   // If the change in value is more than the threshold then emit tilted signal.
400   if( angle >= mRotationThreshold )
401   {
402     mRoll = newRoll;
403     mPitch = newPitch;
404     mRotation = newRotation;
405
406     // emit signal
407     if ( !mTiltedSignal.Empty() )
408     {
409       Dali::TiltSensor handle( this );
410       mTiltedSignal.Emit( handle );
411     }
412   }
413 }
414 #endif // SENSOR_ENABLED
415
416 } // namespace Adaptor
417
418 } // namespace Internal
419
420 } // namespace Dali