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