LayoutAnimations: stopSurface

Summary:
Implementing stopSurface to stop ongoing animations.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D23382974

fbshipit-source-id: 478e0b1ad443ceeb771b03bd1689ec2bdbe02979
This commit is contained in:
Joshua Gross
2020-08-27 19:37:06 -07:00
committed by Facebook GitHub Bot
parent 6a3c866b6a
commit fe7ff13fcf
6 changed files with 58 additions and 0 deletions
@@ -316,6 +316,11 @@ bool LayoutAnimationKeyFrameManager::shouldOverridePullTransaction() const {
return shouldAnimateFrame();
}
void LayoutAnimationKeyFrameManager::stopSurface(SurfaceId surfaceId) {
std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
surfaceIdsToStop_.push_back(surfaceId);
}
bool LayoutAnimationKeyFrameManager::shouldAnimateFrame() const {
// There is potentially a race here between getting and setting
// `currentMutation_`. We don't want to lock around this because then we're
@@ -780,6 +785,35 @@ LayoutAnimationKeyFrameManager::pullTransaction(
bool inflightAnimationsExistInitially = !inflightAnimations_.empty();
// Execute stopSurface on any ongoing animations
if (inflightAnimationsExistInitially) {
std::vector<SurfaceId> surfaceIdsToStop{};
{
std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
surfaceIdsToStop = surfaceIdsToStop_;
surfaceIdsToStop_ = {};
}
for (auto it = inflightAnimations_.begin();
it != inflightAnimations_.end();) {
const auto &animation = *it;
if (std::find(
surfaceIdsToStop.begin(),
surfaceIdsToStop.end(),
animation.surfaceId) != surfaceIdsToStop.end()) {
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
LOG(ERROR)
<< "LayoutAnimations: stopping animation due to stopSurface on "
<< surfaceId;
#endif
it = inflightAnimations_.erase(it);
} else {
it++;
}
}
}
if (!mutations.empty()) {
#ifdef RN_SHADOW_TREE_INTROSPECTION
{
@@ -184,6 +184,8 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate,
bool shouldOverridePullTransaction() const override;
void stopSurface(SurfaceId surfaceId) override;
// This is used to "hijack" the diffing process to figure out which mutations
// should be animated. The mutations returned by this function will be
// executed immediately.
@@ -227,6 +229,9 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate,
ShadowViewMutationList &mutations,
bool deletesOnly = false) const;
mutable std::mutex surfaceIdsToStopMutex_;
mutable std::vector<SurfaceId> surfaceIdsToStop_{};
protected:
bool mutatedViewIsVirtual(ShadowViewMutation const &mutation) const;
@@ -246,6 +246,9 @@ void Scheduler::renderTemplateToSurface(
void Scheduler::stopSurface(SurfaceId surfaceId) const {
SystraceSection s("Scheduler::stopSurface");
// Stop any ongoing animations.
uiManager_->stopSurfaceForAnimationDelegate(surfaceId);
// Note, we have to do in inside `visit` function while the Shadow Tree
// is still being registered.
uiManager_->getShadowTreeRegistry().visit(
@@ -336,6 +336,12 @@ void UIManager::setAnimationDelegate(UIManagerAnimationDelegate *delegate) {
animationDelegate_ = delegate;
}
void UIManager::stopSurfaceForAnimationDelegate(SurfaceId surfaceId) {
if (animationDelegate_ != nullptr) {
animationDelegate_->stopSurface(surfaceId);
}
}
void UIManager::animationTick() {
if (animationDelegate_ != nullptr &&
animationDelegate_->shouldAnimateFrame()) {
@@ -50,6 +50,11 @@ class UIManager final : public ShadowTreeDelegate {
*/
void setAnimationDelegate(UIManagerAnimationDelegate *delegate);
/**
* Execute stopSurface on any UIMAnagerAnimationDelegate.
*/
void stopSurfaceForAnimationDelegate(SurfaceId surfaceId);
void animationTick();
/*
@@ -41,6 +41,11 @@ class UIManagerAnimationDelegate {
* Only needed on Android to drive animations.
*/
virtual bool shouldAnimateFrame() const = 0;
/**
* Drop any animations for a given surface.
*/
virtual void stopSurface(SurfaceId surfaceId) = 0;
};
} // namespace react