Bridge.prepareThread();
try {
/* FIXME: The ANIMATION_FRAME message no longer exists. Instead, the
* animation timing loop is completely based on a Choreographer objects
* that schedules animation and drawing frames. The animation handler is
* no longer even a handler; it is just a Runnable enqueued on the Choreographer.
Handler_Delegate.setCallback(new IHandlerCallback() {
@Override
public void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) {
if (msg.what == ValueAnimator.ANIMATION_START ||
msg.what == ValueAnimator.ANIMATION_FRAME) {
mQueue.add(new MessageBundle(handler, msg, uptimeMillis));
} else {
// just ignore.
}
}
});
*/
// call out to the pre-animation work, which should start an animation or more.
Result result = preAnimation();
if (result.isSuccess() == false) {
mListener.done(result);
}
// loop the animation
RenderSession session = mSession.getSession();
do {
// check early.
if (mListener.isCanceled()) {
break;
}
// get the next message.
MessageBundle bundle = mQueue.poll();
if (bundle == null) {
break;
}
// sleep enough for this bundle to be on time
long currentTime = System.currentTimeMillis();
if (currentTime < bundle.mUptimeMillis) {
try {
sleep(bundle.mUptimeMillis - currentTime);
} catch (InterruptedException e) {
// FIXME log/do something/sleep again?
e.printStackTrace();
}
}
// check after sleeping.
if (mListener.isCanceled()) {
break;
}
// ready to do the work, acquire the scene.
result = mSession.acquire(250);
if (result.isSuccess() == false) {
mListener.done(result);
return;
}
// process the bundle. If the animation is not finished, this will enqueue
// the next message, so mQueue will have another one.
try {
// check after acquiring in case it took a while.
if (mListener.isCanceled()) {
break;
}
bundle.mTarget.handleMessage(bundle.mMessage);
if (mSession.render(false /*freshRender*/).isSuccess()) {
mListener.onNewFrame(session);
}
} finally {
mSession.release();
}
} while (mListener.isCanceled() == false && mQueue.size() > 0);
mListener.done(Status.SUCCESS.createResult());
} catch (Throwable throwable) {
// can't use Bridge.getLog() as the exception might be thrown outside
// of an acquire/release block.
mListener.done(Status.ERROR_UNKNOWN.createResult("Error playing animation", throwable));
} finally {
postAnimation();
Handler_Delegate.setCallback(null);
Bridge.cleanupThread();
}