Revert "Remove EGL surface in the update thread"
[platform/core/uifw/dali-adaptor.git] / dali / internal / system / android / timer-impl-android.cpp
1 /*
2  * Copyright (c) 2019 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/system/common/timer-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/adaptor-framework/android/android-framework.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/internal/adaptor/common/adaptor-impl.h>
26 #include <dali/internal/adaptor/common/framework.h>
27 #include <dali/internal/adaptor/android/android-framework-impl.h>
28 #include <dali/public-api/dali-adaptor-common.h>
29
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace Adaptor
38 {
39
40 namespace
41 {
42
43 // Copied from x server
44 static unsigned int GetCurrentMilliSeconds()
45 {
46   struct timeval tv;
47
48   struct timespec tp;
49   static clockid_t clockid;
50
51   if (!clockid)
52   {
53 #ifdef CLOCK_MONOTONIC_COARSE
54     if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
55       (tp.tv_nsec / 1000) <= 1000 && clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
56     {
57       clockid = CLOCK_MONOTONIC_COARSE;
58     }
59     else
60 #endif
61     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
62     {
63       clockid = CLOCK_MONOTONIC;
64     }
65     else
66     {
67       clockid = ~0L;
68     }
69   }
70   if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
71   {
72     return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
73   }
74
75   gettimeofday(&tv, NULL);
76   return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
77 }
78
79 }
80
81 struct Timer::Impl
82 {
83   Impl( unsigned int milliSec )
84   : mInterval( milliSec ),
85     mStartTimestamp( 0 ),
86     mPauseTimestamp( 0 ),
87     mRunning( false ),
88     mId( 0 )
89   {
90   }
91
92   unsigned int mInterval;
93   unsigned int mStartTimestamp;
94   unsigned int mPauseTimestamp;
95   bool mRunning;
96   unsigned int mId;
97 };
98
99 TimerPtr Timer::New( unsigned int milliSec )
100 {
101   TimerPtr timer( new Timer( milliSec ) );
102   return timer;
103 }
104
105 Timer::Timer( unsigned int milliSec )
106 : mImpl( new Impl( milliSec ) )
107 {
108 }
109
110 Timer::~Timer()
111 {
112   Stop();
113   delete mImpl;
114 }
115
116 bool TimerCallback( void *data )
117 {
118   Timer* timer = static_cast<Timer*>( data );
119   if( timer->IsRunning() )
120   {
121     return timer->Tick();
122   }
123
124   return false;
125 }
126
127 void Timer::Start()
128 {
129   // Timer should be used in the event thread
130   DALI_ASSERT_DEBUG( Adaptor::IsAvailable() );
131
132   if( mImpl->mRunning )
133   {
134     Stop();
135   }
136
137   mImpl->mId = AndroidFramework::GetFramework( Dali::Integration::AndroidFramework::Get() ).AddIdle( mImpl->mInterval, this, TimerCallback );
138   mImpl->mRunning = true;
139   mImpl->mStartTimestamp = GetCurrentMilliSeconds();
140 }
141
142 void Timer::Stop()
143 {
144   // Timer should be used in the event thread
145   DALI_ASSERT_DEBUG( Adaptor::IsAvailable() );
146
147   if( mImpl->mId != 0 )
148   {
149     AndroidFramework::GetFramework( Dali::Integration::AndroidFramework::Get() ).RemoveIdle( mImpl->mId );
150     mImpl->mStartTimestamp = 0;
151     mImpl->mPauseTimestamp = 0;
152   }
153
154   ResetTimerData();
155 }
156
157 void Timer::Pause()
158 {
159   // Timer should be used in the event thread
160   DALI_ASSERT_DEBUG( Adaptor::IsAvailable() );
161
162   if( mImpl->mRunning )
163   {
164     mImpl->mPauseTimestamp = GetCurrentMilliSeconds();
165     AndroidFramework::GetFramework( Dali::Integration::AndroidFramework::Get() ).RemoveIdle( mImpl->mId );
166     mImpl->mId = 0;
167   }
168 }
169
170 void Timer::Resume()
171 {
172   // Timer should be used in the event thread
173   DALI_ASSERT_DEBUG( Adaptor::IsAvailable() );
174
175   if( mImpl->mRunning && mImpl->mId == 0 )
176   {
177     unsigned int newInterval = 0;
178     unsigned int runningTime = mImpl->mPauseTimestamp - mImpl->mStartTimestamp;
179     if( mImpl->mInterval > runningTime )
180     {
181       newInterval = mImpl->mInterval - runningTime;
182     }
183
184     mImpl->mStartTimestamp = GetCurrentMilliSeconds() - runningTime;
185     mImpl->mPauseTimestamp = 0;
186     mImpl->mId = AndroidFramework::GetFramework( Dali::Integration::AndroidFramework::Get() ).AddIdle( newInterval, this, TimerCallback );
187   }
188 }
189
190 void Timer::SetInterval( unsigned int interval, bool restart )
191 {
192   // stop existing timer
193   Stop();
194   mImpl->mInterval = interval;
195
196   if( restart )
197   {
198     // start new tick
199     Start();
200   }
201 }
202
203 unsigned int Timer::GetInterval() const
204 {
205   return mImpl->mInterval;
206 }
207
208 bool Timer::Tick()
209 {
210   // Guard against destruction during signal emission
211   Dali::Timer handle( this );
212
213   bool retVal( false );
214
215   // Override with new signal if used
216   if( !mTickSignal.Empty() )
217   {
218     retVal = mTickSignal.Emit();
219
220     // Timer stops if return value is false
221     if (retVal == false)
222     {
223       Stop();
224     }
225     else
226     {
227       retVal = true;   // continue emission
228     }
229   }
230   else // no callbacks registered
231   {
232     // periodic timer is started but nobody listens, continue
233     retVal = true;
234   }
235
236   return retVal;
237 }
238
239 Dali::Timer::TimerSignalType& Timer::TickSignal()
240 {
241   return mTickSignal;
242 }
243
244 void Timer::ResetTimerData()
245 {
246   mImpl->mRunning = false;
247   mImpl->mId = 0;
248 }
249
250 bool Timer::IsRunning() const
251 {
252   return mImpl->mRunning;
253 }
254
255 } // namespace Adaptor
256
257 } // namespace Internal
258
259 } // namespace Dali