1 /* 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 */ 7 8 #pragma once 9 10 #include <ABI49_0_0ReactCommon/ABI49_0_0RuntimeExecutor.h> 11 #include <ABI49_0_0butter/ABI49_0_0set.h> 12 #include <ABI49_0_0React/renderer/animations/ABI49_0_0LayoutAnimationCallbackWrapper.h> 13 #include <ABI49_0_0React/renderer/animations/ABI49_0_0primitives.h> 14 #include <ABI49_0_0React/renderer/core/ABI49_0_0RawValue.h> 15 #include <ABI49_0_0React/renderer/debug/ABI49_0_0flags.h> 16 #include <ABI49_0_0React/renderer/mounting/ABI49_0_0MountingOverrideDelegate.h> 17 #include <ABI49_0_0React/renderer/mounting/ABI49_0_0MountingTransaction.h> 18 #include <ABI49_0_0React/renderer/mounting/ABI49_0_0ShadowViewMutation.h> 19 #include <ABI49_0_0React/renderer/uimanager/ABI49_0_0LayoutAnimationStatusDelegate.h> 20 #include <ABI49_0_0React/renderer/uimanager/ABI49_0_0UIManagerAnimationDelegate.h> 21 22 #include <optional> 23 24 namespace ABI49_0_0facebook { 25 namespace ABI49_0_0React { 26 27 #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING 28 void PrintMutationInstruction( 29 std::string message, 30 ShadowViewMutation const &mutation); 31 void PrintMutationInstructionRelative( 32 std::string message, 33 ShadowViewMutation const &mutation, 34 ShadowViewMutation const &relativeMutation); 35 #else 36 #define PrintMutationInstruction(a, b) 37 #define PrintMutationInstructionRelative(a, b, c) 38 #endif 39 40 class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, 41 public MountingOverrideDelegate { 42 public: 43 LayoutAnimationKeyFrameManager( 44 RuntimeExecutor runtimeExecutor, 45 ContextContainer::Shared &contextContainer, 46 LayoutAnimationStatusDelegate *delegate); 47 48 #pragma mark - UIManagerAnimationDelegate methods 49 50 void uiManagerDidConfigureNextLayoutAnimation( 51 jsi::Runtime &runtime, 52 RawValue const &config, 53 const jsi::Value &successCallbackValue, 54 const jsi::Value &failureCallbackValue) const override; 55 56 void setComponentDescriptorRegistry(SharedComponentDescriptorRegistry const & 57 componentDescriptorRegistry) override; 58 59 void setReduceDeleteCreateMutation(bool reduceDeleteCreateMutation) override; 60 61 // TODO: add SurfaceId to this API as well 62 bool shouldAnimateFrame() const override; 63 64 void stopSurface(SurfaceId surfaceId) override; 65 66 #pragma mark - MountingOverrideDelegate methods 67 68 bool shouldOverridePullTransaction() const override; 69 70 // This is used to "hijack" the diffing process to figure out which mutations 71 // should be animated. The mutations returned by this function will be 72 // executed immediately. 73 std::optional<MountingTransaction> pullTransaction( 74 SurfaceId surfaceId, 75 MountingTransaction::Number number, 76 TransactionTelemetry const &telemetry, 77 ShadowViewMutationList mutations) const override; 78 79 // Exposed for testing. 80 void uiManagerDidConfigureNextLayoutAnimation( 81 LayoutAnimation layoutAnimation) const; 82 83 // LayoutAnimationStatusDelegate - this is for the platform to get 84 // signal when animations start and complete. Setting and resetting this 85 // delegate is protected by a mutex; ALL method calls into this delegate are 86 // also protected by the mutex! The only way to set this without a mutex is 87 // via a constructor. 88 void setLayoutAnimationStatusDelegate( 89 LayoutAnimationStatusDelegate *delegate) const; 90 91 void setClockNow(std::function<uint64_t()> now); 92 93 protected: 94 SharedComponentDescriptorRegistry componentDescriptorRegistry_; 95 mutable std::optional<LayoutAnimation> currentAnimation_{}; 96 mutable std::mutex currentAnimationMutex_; 97 98 /** 99 * All mutations of inflightAnimations_ are thread-safe as long as 100 * we keep the contract of: only mutate it within the context of 101 * `pullTransaction`. If that contract is held, this is implicitly protected 102 * by the MountingCoordinator's mutex. 103 */ 104 mutable std::vector<LayoutAnimation> inflightAnimations_{}; 105 106 bool hasComponentDescriptorForShadowView(ShadowView const &shadowView) const; 107 ComponentDescriptor const &getComponentDescriptorForShadowView( 108 ShadowView const &shadowView) const; 109 110 /** 111 * Given a `progress` between 0 and 1, a mutation and LayoutAnimation config, 112 * return a ShadowView with mutated props and/or LayoutMetrics. 113 * 114 * @param progress 115 * @param layoutAnimation 116 * @param animatedMutation 117 * @return 118 */ 119 ShadowView createInterpolatedShadowView( 120 Float progress, 121 ShadowView const &startingView, 122 ShadowView const &finalView) const; 123 124 void callCallback(const LayoutAnimationCallbackWrapper &callback) const; 125 126 virtual void animationMutationsForFrame( 127 SurfaceId surfaceId, 128 ShadowViewMutation::List &mutationsList, 129 uint64_t now) const = 0; 130 131 /** 132 * Queue (and potentially synthesize) final mutations for a finished keyframe. 133 * Keyframe animation may have timed-out, or be canceled due to a conflict. 134 */ 135 void queueFinalMutationsForCompletedKeyFrame( 136 AnimationKeyFrame const &keyframe, 137 ShadowViewMutation::List &mutationsList, 138 bool interrupted, 139 const std::string &logPrefix) const; 140 141 private: 142 RuntimeExecutor runtimeExecutor_; 143 ContextContainer::Shared contextContainer_; 144 145 mutable std::mutex layoutAnimationStatusDelegateMutex_; 146 mutable LayoutAnimationStatusDelegate *layoutAnimationStatusDelegate_{}; 147 mutable std::mutex surfaceIdsToStopMutex_; 148 mutable butter::set<SurfaceId> surfaceIdsToStop_{}; 149 bool reduceDeleteCreateMutation_{false}; 150 151 // Function that returns current time in milliseconds 152 std::function<uint64_t()> now_; 153 154 void adjustImmediateMutationIndicesForDelayedMutations( 155 SurfaceId surfaceId, 156 ShadowViewMutation &mutation, 157 bool skipLastAnimation = false, 158 bool lastAnimationOnly = false) const; 159 160 void adjustDelayedMutationIndicesForMutation( 161 SurfaceId surfaceId, 162 ShadowViewMutation const &mutation, 163 bool skipLastAnimation = false) const; 164 165 void getAndEraseConflictingAnimations( 166 SurfaceId surfaceId, 167 ShadowViewMutationList const &mutations, 168 std::vector<AnimationKeyFrame> &conflictingAnimations) const; 169 170 /* 171 * Removes animations from `inflightAnimations_` for stopped surfaces. 172 */ 173 void deleteAnimationsForStoppedSurfaces() const; 174 175 void simulateImagePropsMemoryAccess( 176 ShadowViewMutationList const &mutations) const; 177 }; 178 179 } // namespace ABI49_0_0React 180 } // namespace ABI49_0_0facebook 181