android_frameworks_base/libs/hwui/AnimationContext.h
John Reck ec845a215e Fix race condition
Bug: 17372309

 AnimationContext::startFrame() happens both with and without
 the UI thread lock. Pass the TraversalMode into it so
 that ThreadedRenderer's subclass can correctly decide
 when it is safe to push over mPendingAnimatingRenderNodes, as doing
 so outside of the lock is Very Bad.

Change-Id: Ife5dd3a2b46b0a207cd9234c159a674afdbf5efd
2014-09-05 15:23:38 -07:00

122 lines
3.9 KiB
C++

/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TREEANIMATIONTRACKER_H_
#define TREEANIMATIONTRACKER_H_
#include <cutils/compiler.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
#include "TreeInfo.h"
#include "renderthread/TimeLord.h"
#include "utils/Macros.h"
namespace android {
namespace uirenderer {
class AnimationContext;
class AnimationListener;
class BaseRenderNodeAnimator;
class RenderNode;
/*
* AnimationHandle is several classes merged into one.
* 1: It maintains the reference to the AnimationContext required to run animators.
* 2: It keeps a strong reference to RenderNodes with animators so that
* we don't lose them if they are no longer in the display tree. This is
* required so that we can keep animating them, and properly notify listeners
* of onAnimationFinished.
* 3: It forms a doubly linked list so that we can cheaply move between states.
*/
class AnimationHandle {
PREVENT_COPY_AND_ASSIGN(AnimationHandle);
public:
AnimationContext& context() { return mContext; }
// Called by the RenderNode when it has internally pulsed its own animations
// this frame and does not need to be run again this frame.
void notifyAnimationsRan();
// Stops tracking the RenderNode and destroys the handle. The node must be
// re-attached to the AnimationContext to receive managed animation
// pulses.
void release();
private:
friend class AnimationContext;
AnimationHandle(AnimationContext& context);
AnimationHandle(RenderNode& animatingNode, AnimationContext& context);
~AnimationHandle();
void insertAfter(AnimationHandle* prev);
void removeFromList();
sp<RenderNode> mRenderNode;
AnimationContext& mContext;
AnimationHandle* mPreviousHandle;
AnimationHandle* mNextHandle;
};
class AnimationContext {
PREVENT_COPY_AND_ASSIGN(AnimationContext);
public:
ANDROID_API AnimationContext(renderthread::TimeLord& clock);
ANDROID_API virtual ~AnimationContext();
nsecs_t frameTimeMs() { return mFrameTimeMs; }
bool hasAnimations() {
return mCurrentFrameAnimations.mNextHandle
|| mNextFrameAnimations.mNextHandle;
}
// Will always add to the next frame list, which is swapped when
// startFrame() is called
ANDROID_API void addAnimatingRenderNode(RenderNode& node);
// Marks the start of a frame, which will update the frame time and move all
// next frame animations into the current frame
ANDROID_API virtual void startFrame(TreeInfo::TraversalMode mode);
// Runs any animations still left in mCurrentFrameAnimations that were not run
// as part of the standard RenderNode:prepareTree pass.
ANDROID_API virtual void runRemainingAnimations(TreeInfo& info);
ANDROID_API virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener);
ANDROID_API virtual void destroy();
private:
friend class AnimationHandle;
void addAnimationHandle(AnimationHandle* handle);
renderthread::TimeLord& mClock;
// Animations left to run this frame, at the end of the frame this should
// be null
AnimationHandle mCurrentFrameAnimations;
// Animations queued for next frame
AnimationHandle mNextFrameAnimations;
nsecs_t mFrameTimeMs;
};
} /* namespace uirenderer */
} /* namespace android */
#endif /* TREEANIMATIONTRACKER_H_ */