From 15cc5f0a64ddcf5c3b26cfc24607d296eb09f1b9 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 13 Oct 2026 07:53:04 -0700 Subject: [PATCH 1/2] Deprecate legacy Android UIManager surface APIs Summary: The View-based `UIManager` lifecycle predates `ReactHost` and `ReactSurface` and is no longer used by the supported architecture. Deprecate these methods before their planned removal and point callers to `ReactHost.createSurface(...)` and `ReactSurface.start()` or `stop()`. Changelog: [Android][Deprecated] - Deprecate the legacy View-based surface lifecycle methods in `UIManager`. Differential Revision: D124990160 --- .../com/facebook/react/bridge/UIManager.kt | 29 ++++++++++++++++--- .../react/fabric/FabricUIManager.java | 14 ++++++++- .../facebook/testutils/fakes/FakeUIManager.kt | 2 ++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.kt index cdc8be7862de..7587d9cc7a89 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.kt @@ -16,14 +16,29 @@ import com.facebook.react.uimanager.events.EventDispatcher @OptIn(UnstableReactNativeAPI::class) public interface UIManager : PerformanceCounter { - /** Registers a new root view. @Deprecated call startSurface instead */ + /** + * Registers a new root view. + * + * @deprecated Use `ReactHost.createSurface(...)` and `ReactSurface.start()` instead. + */ @UiThread @ThreadConfined(ThreadConfined.UI) - @Deprecated("") + @Deprecated( + "This legacy surface API will be removed in a future release. " + + "Use ReactHost.createSurface(...) and ReactSurface.start() instead." + ) public fun addRootView(rootView: T, initialProps: WritableMap?): Int - /** Registers a new root view with width and height. */ + /** + * Registers a new root view with width and height. + * + * @deprecated Use `ReactHost.createSurface(...)` and `ReactSurface.start()` instead. + */ @AnyThread + @Deprecated( + "This legacy surface API will be removed in a future release. " + + "Use ReactHost.createSurface(...) and ReactSurface.start() instead." + ) public fun startSurface( rootView: T, moduleName: String, @@ -35,8 +50,14 @@ public interface UIManager : PerformanceCounter { /** * Stop a surface from running in JS and clears up native memory usage. Assumes that the native * View hierarchy has already been cleaned up. Fabric-only. + * + * @deprecated Use `ReactSurface.stop()` instead. */ - @AnyThread public fun stopSurface(surfaceId: Int) + @AnyThread + @Deprecated( + "This legacy surface API will be removed in a future release. Use ReactSurface.stop() instead." + ) + public fun stopSurface(surfaceId: Int) /** * Updates the layout specs of the RootShadowNode based on the Measure specs received by diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index a3cca69f4bfd..97de9935b8cf 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -262,6 +262,9 @@ public FabricUIManager( mReactApplicationContext.registerComponentCallbacks(viewManagerRegistry); } + /** + * @deprecated Use {@code ReactHost.createSurface(...)} and {@code ReactSurface.start()} instead. + */ @Override @UiThread @ThreadConfined(UI) @@ -271,7 +274,8 @@ public int addRootView( ReactSoftExceptionLogger.logSoftException( TAG, new IllegalViewOperationException( - "Do not call addRootView in Fabric; it is unsupported. Call startSurface instead.")); + "Do not call addRootView in Fabric; it is unsupported. Use ReactHost.createSurface(...)" + + " and ReactSurface.start() instead.")); ReactRoot reactRootView = (ReactRoot) rootView; final int rootTag = reactRootView.getRootViewTag(); @@ -341,6 +345,10 @@ public int addRootView( return mBinding != null ? mBinding.getRelativeAncestorList(rootTag, childTag) : null; } + /** + * @deprecated Use {@code ReactHost.createSurface(...)} and {@code ReactSurface.start()} instead. + */ + @Deprecated @Override @AnyThread @ThreadConfined(ANY) @@ -430,6 +438,10 @@ public void onRequestEventBeat() { mEventDispatcher.dispatchAllEvents(); } + /** + * @deprecated Use {@code ReactSurface.stop()} instead. + */ + @Deprecated @AnyThread @ThreadConfined(ANY) @Override diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/testutils/fakes/FakeUIManager.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/testutils/fakes/FakeUIManager.kt index 057006764a20..e1e708edcd1b 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/testutils/fakes/FakeUIManager.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/testutils/fakes/FakeUIManager.kt @@ -34,6 +34,7 @@ class FakeUIManager : UIManager, UIBlockViewResolver { error("Not yet implemented") } + @Deprecated("") override fun startSurface( rootView: T, moduleName: String, @@ -44,6 +45,7 @@ class FakeUIManager : UIManager, UIBlockViewResolver { error("Not yet implemented") } + @Deprecated("") override fun stopSurface(surfaceId: Int) { error("Not yet implemented") } From 4f760662bdf9993ee2e76f218137f48cc6a22386 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 13 Oct 2026 08:43:40 -0700 Subject: [PATCH 2/2] Remove obsolete Android Fabric surface paths (#59036) Summary: Pull Request resolved: https://github.com/react/react-native/pull/59036 ReactInstanceManager can no longer initialise the legacy bridge, so the bridge+Fabric surface lifecycle JNI entry points are unreachable. Remove those methods while retaining the existing UIManager signatures as explicit unsupported/no-op compatibility overrides, and simplify native surface tracking to weak Java-owned SurfaceHandlers. Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D124979204 --- .../react/fabric/FabricUIManager.java | 107 +------ .../react/fabric/FabricUIManagerBinding.kt | 35 --- .../react/fabric/FabricUIManagerBinding.cpp | 274 +----------------- .../jni/react/fabric/FabricUIManagerBinding.h | 39 +-- .../react/fabric/FabricUIManagerTest.kt | 14 + 5 files changed, 30 insertions(+), 439 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 97de9935b8cf..76556860259f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -9,8 +9,6 @@ import static com.facebook.infer.annotation.ThreadConfined.ANY; import static com.facebook.infer.annotation.ThreadConfined.UI; -import static com.facebook.react.fabric.mounting.LayoutMetricsConversions.getMaxSize; -import static com.facebook.react.fabric.mounting.LayoutMetricsConversions.getMinSize; import static com.facebook.react.fabric.mounting.LayoutMetricsConversions.getYogaMeasureMode; import static com.facebook.react.fabric.mounting.LayoutMetricsConversions.getYogaSize; import static com.facebook.react.uimanager.UIManagerHelper.PADDING_BOTTOM_INDEX; @@ -20,7 +18,6 @@ import android.annotation.SuppressLint; import android.content.Context; -import android.graphics.Point; import android.os.SystemClock; import android.view.View; import android.view.accessibility.AccessibilityEvent; @@ -38,7 +35,6 @@ import com.facebook.react.bridge.GuardedRunnable; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.NativeArray; -import com.facebook.react.bridge.NativeMap; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactMarker; @@ -73,14 +69,11 @@ import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags; import com.facebook.react.internal.interop.InteropEventEmitter; import com.facebook.react.modules.core.ReactChoreographer; -import com.facebook.react.modules.i18nmanager.I18nUtil; import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.GuardedFrameCallback; -import com.facebook.react.uimanager.IllegalViewOperationException; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ReactRoot; import com.facebook.react.uimanager.ReactRootViewTagGenerator; -import com.facebook.react.uimanager.RootViewUtil; import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.UIManagerHelper; @@ -271,26 +264,7 @@ public FabricUIManager( @Deprecated public int addRootView( final T rootView, final @Nullable WritableMap initialProps) { - ReactSoftExceptionLogger.logSoftException( - TAG, - new IllegalViewOperationException( - "Do not call addRootView in Fabric; it is unsupported. Use ReactHost.createSurface(...)" - + " and ReactSurface.start() instead.")); - - ReactRoot reactRootView = (ReactRoot) rootView; - final int rootTag = reactRootView.getRootViewTag(); - - ThemedReactContext reactContext = - new ThemedReactContext( - mReactApplicationContext, rootView.getContext(), reactRootView.getSurfaceID(), rootTag); - mMountingManager.startSurface(rootTag, reactContext, rootView); - String moduleName = reactRootView.getJSModuleName(); - if (ReactNativeFeatureFlags.enableFabricLogs()) { - FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag); - } - Assertions.assertNotNull(mBinding, "Binding in FabricUIManager is null"); - mBinding.startSurface(rootTag, moduleName, (NativeMap) initialProps); - return rootTag; + throw new UnsupportedOperationException("FabricUIManager.addRootView is unsupported."); } /** @@ -358,36 +332,8 @@ public int startSurface( final @Nullable WritableMap initialProps, int widthMeasureSpec, int heightMeasureSpec) { - final int rootTag = ((ReactRoot) rootView).getRootViewTag(); - Context context = rootView.getContext(); - ThemedReactContext reactContext = - new ThemedReactContext(mReactApplicationContext, context, moduleName, rootTag); - if (ReactNativeFeatureFlags.enableFabricLogs()) { - FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag); - } - mMountingManager.startSurface(rootTag, reactContext, rootView); - - // If startSurface is executed in the UIThread then, it uses the ViewportOffset from the View, - // Otherwise Fabric relies on calling {@link Binding#setConstraints} method to update the - // ViewportOffset during measurement or onLayout. - @SuppressLint("WrongThread") - Point viewportOffset = - UiThreadUtil.isOnUiThread() ? RootViewUtil.getViewportOffset(rootView) : new Point(0, 0); - - Assertions.assertNotNull(mBinding, "Binding in FabricUIManager is null"); - mBinding.startSurfaceWithConstraints( - rootTag, - moduleName, - (NativeMap) initialProps, - getMinSize(widthMeasureSpec), - getMaxSize(widthMeasureSpec), - getMinSize(heightMeasureSpec), - getMaxSize(heightMeasureSpec), - viewportOffset.x, - viewportOffset.y, - I18nUtil.getInstance().isRTL(context), - I18nUtil.getInstance().doLeftAndRightSwapInRTL(context)); - return rootTag; + throw new UnsupportedOperationException( + "FabricUIManager.startSurface(View, ...) is unsupported."); } public void startSurface( @@ -446,14 +392,7 @@ public void onRequestEventBeat() { @ThreadConfined(ANY) @Override public void stopSurface(final int surfaceID) { - // Mark surfaceId as dead, stop executing mounting instructions - mMountingManager.stopSurface(surfaceID); - - // Communicate stopSurface to Cxx - causes an empty ShadowTree to be committed, - // but all mounting instructions will be ignored because stopSurface was called - // on the MountingManager - Assertions.assertNotNull(mBinding, "Binding in FabricUIManager is null"); - mBinding.stopSurface(surfaceID); + throw new UnsupportedOperationException("FabricUIManager.stopSurface(int) is unsupported."); } @Override @@ -1130,43 +1069,7 @@ public void updateRootLayoutSpecs( final int widthMeasureSpec, final int heightMeasureSpec, final int offsetX, - final int offsetY) { - - if (ReactNativeFeatureFlags.enableFabricLogs()) { - FLog.d(TAG, "Updating Root Layout Specs for [%d]", surfaceId); - } - - SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId); - - // TODO T83615646: make this a hard-crash in the future. - if (surfaceMountingManager == null) { - ReactSoftExceptionLogger.logSoftException( - TAG, - new IllegalViewOperationException( - "Cannot updateRootLayoutSpecs on surfaceId that does not exist: " + surfaceId)); - return; - } - - Context context = surfaceMountingManager.getContext(); - boolean isRTL = false; - boolean doLeftAndRightSwapInRTL = false; - if (context != null) { - isRTL = I18nUtil.getInstance().isRTL(context); - doLeftAndRightSwapInRTL = I18nUtil.getInstance().doLeftAndRightSwapInRTL(context); - } - - Assertions.assertNotNull(mBinding, "Binding in FabricUIManager is null"); - mBinding.setConstraints( - surfaceId, - getMinSize(widthMeasureSpec), - getMaxSize(widthMeasureSpec), - getMinSize(heightMeasureSpec), - getMaxSize(heightMeasureSpec), - offsetX, - offsetY, - isRTL, - doLeftAndRightSwapInRTL); - } + final int offsetY) {} @Override public @Nullable View resolveView(int reactTag) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerBinding.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerBinding.kt index b1b3f12f50c2..c139660406f6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerBinding.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerBinding.kt @@ -10,11 +10,9 @@ package com.facebook.react.fabric import android.annotation.SuppressLint import com.facebook.jni.HybridClassBase import com.facebook.proguard.annotations.DoNotStripAny -import com.facebook.react.bridge.NativeMap import com.facebook.react.bridge.RuntimeExecutor import com.facebook.react.bridge.RuntimeScheduler import com.facebook.react.fabric.events.EventBeatManager -import com.facebook.react.uimanager.PixelUtil.getDisplayMetricDensity @DoNotStripAny @SuppressLint("MissingNativeLoadLibrary") @@ -33,22 +31,6 @@ internal class FabricUIManagerBinding : HybridClassBase() { componentsRegistry: ComponentFactory, ) - external fun startSurface(surfaceId: Int, moduleName: String, initialProps: NativeMap?) - - external fun startSurfaceWithConstraints( - surfaceId: Int, - moduleName: String, - initialProps: NativeMap?, - minWidth: Float, - maxWidth: Float, - minHeight: Float, - maxHeight: Float, - offsetX: Float, - offsetY: Float, - isRTL: Boolean, - doLeftAndRightSwapInRTL: Boolean, - ) - external fun startSurfaceWithSurfaceHandler( surfaceId: Int, surfaceHandler: SurfaceHandlerBinding, @@ -59,24 +41,8 @@ internal class FabricUIManagerBinding : HybridClassBase() { external fun getRelativeAncestorList(rootTag: Int, childTag: Int): IntArray - external fun stopSurface(surfaceId: Int) - external fun stopSurfaceWithSurfaceHandler(surfaceHandler: SurfaceHandlerBinding) - external fun setPixelDensity(pointScaleFactor: Float) - - external fun setConstraints( - surfaceId: Int, - minWidth: Float, - maxWidth: Float, - minHeight: Float, - maxHeight: Float, - offsetX: Float, - offsetY: Float, - isRTL: Boolean, - doLeftAndRightSwapInRTL: Boolean, - ) - external fun driveCxxAnimations() external fun driveAnimationBackend(frameTimeNanos: Long) @@ -105,7 +71,6 @@ internal class FabricUIManagerBinding : HybridClassBase() { eventBeatManager, componentFactory, ) - setPixelDensity(getDisplayMetricDensity()) } private external fun uninstallFabricUIManager() diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp index d5c154f1e6f1..b49e418ad3da 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp @@ -47,10 +47,6 @@ std::shared_ptr FabricUIManagerBinding::getScheduler() { return scheduler_; } -void FabricUIManagerBinding::setPixelDensity(float pointScaleFactor) { - pointScaleFactor_ = pointScaleFactor; -} - void FabricUIManagerBinding::driveCxxAnimations() { auto scheduler = getScheduler(); if (!scheduler) { @@ -89,19 +85,11 @@ void FabricUIManagerBinding::reportMount(SurfaceId surfaceId) { std::shared_lock lock(surfaceHandlerRegistryMutex_); auto iterator = surfaceHandlerRegistry_.find(surfaceId); if (iterator != surfaceHandlerRegistry_.end()) { - const auto* surfaceHandler = - std::get_if(&iterator->second); - if (surfaceHandler == nullptr) { - auto javaSurfaceHandler = - std::get>( - iterator->second) - .lockLocal(); - if (javaSurfaceHandler) { - surfaceHandler = &javaSurfaceHandler->cthis()->getSurfaceHandler(); - } - } - if (surfaceHandler != nullptr) { - auto mountingCoordinator = surfaceHandler->getMountingCoordinator(); + auto javaSurfaceHandler = iterator->second.lockLocal(); + if (javaSurfaceHandler) { + const auto& surfaceHandler = + javaSurfaceHandler->cthis()->getSurfaceHandler(); + auto mountingCoordinator = surfaceHandler.getMountingCoordinator(); if (mountingCoordinator != nullptr) { mountingCoordinator->didPerformAsyncTransactions(); } @@ -130,19 +118,11 @@ void FabricUIManagerBinding::pullAndExecuteTransaction(SurfaceId surfaceId) { if (iterator == surfaceHandlerRegistry_.end()) { return; } - const auto* surfaceHandler = std::get_if(&iterator->second); - jni::local_ref javaSurfaceHandler; - if (surfaceHandler == nullptr) { - javaSurfaceHandler = - std::get>( - iterator->second) - .lockLocal(); - if (javaSurfaceHandler) { - surfaceHandler = &javaSurfaceHandler->cthis()->getSurfaceHandler(); - } - } - if (surfaceHandler != nullptr) { - mountingCoordinator = surfaceHandler->getMountingCoordinator(); + auto javaSurfaceHandler = iterator->second.lockLocal(); + if (javaSurfaceHandler) { + mountingCoordinator = javaSurfaceHandler->cthis() + ->getSurfaceHandler() + .getMountingCoordinator(); } } @@ -216,60 +196,6 @@ void FabricUIManagerBinding::startSurfaceWithSurfaceHandler( } } -// Used by non-bridgeless+Fabric -void FabricUIManagerBinding::startSurface( - jint surfaceId, - jni::alias_ref moduleName, - NativeMap* initialProps) { - TraceSection s("FabricUIManagerBinding::startSurface"); - - if (enableFabricLogs_) { - LOG(WARNING) - << "FabricUIManagerBinding::startSurface() was called (address: " - << this << ", surfaceId: " << surfaceId << ")."; - } - - auto scheduler = getScheduler(); - if (!scheduler) { - LOG(ERROR) << "FabricUIManagerBinding::startSurface: scheduler disappeared"; - return; - } - - SurfaceHandler* surfaceHandler = nullptr; - { - std::unique_lock lock(surfaceHandlerRegistryMutex_); - auto [it, _] = surfaceHandlerRegistry_.try_emplace( - surfaceId, - std::in_place_index<0>, - moduleName->toStdString(), - surfaceId); - surfaceHandler = &std::get(it->second); - } - - surfaceHandler->setContextContainer(scheduler->getContextContainer()); - if (initialProps != nullptr) { - surfaceHandler->setProps(initialProps->consume()); - } - - auto layoutContext = LayoutContext{}; - layoutContext.pointScaleFactor = pointScaleFactor_; - surfaceHandler->constraintLayout({}, layoutContext); - - scheduler->registerSurface(*surfaceHandler); - - auto mountingManager = getMountingManager("startSurface"); - if (mountingManager != nullptr) { - mountingManager->onSurfaceStart(surfaceId); - } - - surfaceHandler->start(); - - if (ReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid()) { - surfaceHandler->getMountingCoordinator()->setMountingOverrideDelegate( - animationDriver_); - } -} - jint FabricUIManagerBinding::findNextFocusableElement( jint parentTag, jint focusedTag, @@ -366,125 +292,6 @@ jintArray FabricUIManagerBinding::getRelativeAncestorList( return result; } -// Used by non-bridgeless+Fabric -void FabricUIManagerBinding::startSurfaceWithConstraints( - jint surfaceId, - jni::alias_ref moduleName, - NativeMap* initialProps, - jfloat minWidth, - jfloat maxWidth, - jfloat minHeight, - jfloat maxHeight, - jfloat offsetX, - jfloat offsetY, - jboolean isRTL, - jboolean doLeftAndRightSwapInRTL) { - TraceSection s("FabricUIManagerBinding::startSurfaceWithConstraints"); - - if (enableFabricLogs_) { - LOG(WARNING) - << "FabricUIManagerBinding::startSurfaceWithConstraints() was called (address: " - << this << ", surfaceId: " << surfaceId << ")."; - } - - auto scheduler = getScheduler(); - if (!scheduler) { - LOG(ERROR) - << "FabricUIManagerBinding::startSurfaceWithConstraints: scheduler disappeared"; - return; - } - - auto minimumSize = Size{ - .width = minWidth / pointScaleFactor_, - .height = minHeight / pointScaleFactor_}; - auto maximumSize = Size{ - .width = maxWidth / pointScaleFactor_, - .height = maxHeight / pointScaleFactor_}; - - LayoutContext context; - context.viewportOffset = - Point{.x = offsetX / pointScaleFactor_, .y = offsetY / pointScaleFactor_}; - context.pointScaleFactor = {pointScaleFactor_}; - context.swapLeftAndRightInRTL = doLeftAndRightSwapInRTL != 0; - LayoutConstraints constraints = {}; - constraints.minimumSize = minimumSize; - constraints.maximumSize = maximumSize; - constraints.layoutDirection = - isRTL != 0 ? LayoutDirection::RightToLeft : LayoutDirection::LeftToRight; - - SurfaceHandler* surfaceHandler = nullptr; - { - std::unique_lock lock(surfaceHandlerRegistryMutex_); - auto [it, _] = surfaceHandlerRegistry_.try_emplace( - surfaceId, - std::in_place_index<0>, - moduleName->toStdString(), - surfaceId); - surfaceHandler = &std::get(it->second); - } - - surfaceHandler->setContextContainer(scheduler->getContextContainer()); - if (initialProps != nullptr) { - surfaceHandler->setProps(initialProps->consume()); - } - surfaceHandler->constraintLayout(constraints, context); - - scheduler->registerSurface(*surfaceHandler); - - auto mountingManager = getMountingManager("startSurfaceWithConstraints"); - if (mountingManager != nullptr) { - mountingManager->onSurfaceStart(surfaceId); - } - - surfaceHandler->start(); - - if (ReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid()) { - surfaceHandler->getMountingCoordinator()->setMountingOverrideDelegate( - animationDriver_); - } -} - -// Used by non-bridgeless+Fabric -void FabricUIManagerBinding::stopSurface(jint surfaceId) { - TraceSection s("FabricUIManagerBinding::stopSurface"); - if (enableFabricLogs_) { - LOG(WARNING) - << "FabricUIManagerBinding::stopSurface() was called (address: " << this - << ", surfaceId: " << surfaceId << ")."; - } - - auto scheduler = getScheduler(); - if (!scheduler) { - LOG(ERROR) << "FabricUIManagerBinding::stopSurface: scheduler disappeared"; - return; - } - - { - std::unique_lock lock(surfaceHandlerRegistryMutex_); - auto iterator = surfaceHandlerRegistry_.find(surfaceId); - if (iterator == surfaceHandlerRegistry_.end()) { - LOG(ERROR) - << "FabricUIManagerBinding::stopSurface: Surface with given id is not found"; - return; - } - - auto* surfaceHandler = std::get_if(&iterator->second); - if (surfaceHandler != nullptr) { - surfaceHandler->stop(); - scheduler->unregisterSurface(*surfaceHandler); - } else { - LOG(ERROR) << "Java-owned SurfaceHandler found in stopSurface"; - } - surfaceHandlerRegistry_.erase(iterator); - } - - auto mountingManager = getMountingManager("stopSurface"); - if (!mountingManager) { - return; - } - mountingManager->onSurfaceStop(surfaceId); -} - // Used by bridgeless void FabricUIManagerBinding::stopSurfaceWithSurfaceHandler( jni::alias_ref @@ -523,58 +330,6 @@ void FabricUIManagerBinding::stopSurfaceWithSurfaceHandler( mountingManager->onSurfaceStop(surfaceHandler.getSurfaceId()); } -void FabricUIManagerBinding::setConstraints( - jint surfaceId, - jfloat minWidth, - jfloat maxWidth, - jfloat minHeight, - jfloat maxHeight, - jfloat offsetX, - jfloat offsetY, - jboolean isRTL, - jboolean doLeftAndRightSwapInRTL) { - TraceSection s("FabricUIManagerBinding::setConstraints"); - - auto scheduler = getScheduler(); - if (!scheduler) { - LOG(ERROR) - << "FabricUIManagerBinding::setConstraints: scheduler disappeared"; - return; - } - - auto minimumSize = Size{ - .width = minWidth / pointScaleFactor_, - .height = minHeight / pointScaleFactor_}; - auto maximumSize = Size{ - .width = maxWidth / pointScaleFactor_, - .height = maxHeight / pointScaleFactor_}; - - LayoutContext context; - context.viewportOffset = - Point{.x = offsetX / pointScaleFactor_, .y = offsetY / pointScaleFactor_}; - context.pointScaleFactor = {pointScaleFactor_}; - context.swapLeftAndRightInRTL = doLeftAndRightSwapInRTL != 0; - LayoutConstraints constraints = {}; - constraints.minimumSize = minimumSize; - constraints.maximumSize = maximumSize; - constraints.layoutDirection = (isRTL != 0u) ? LayoutDirection::RightToLeft - : LayoutDirection::LeftToRight; - - { - std::shared_lock lock(surfaceHandlerRegistryMutex_); - auto iterator = surfaceHandlerRegistry_.find(surfaceId); - if (iterator == surfaceHandlerRegistry_.end()) { - LOG(ERROR) - << "FabricUIManagerBinding::setConstraints: Surface with given id is not found"; - return; - } - auto* surfaceHandler = std::get_if(&iterator->second); - if (surfaceHandler != nullptr) { - surfaceHandler->constraintLayout(constraints, context); - } - } -} - #pragma mark - Install/uninstall java binding void FabricUIManagerBinding::installFabricUIManager( @@ -920,15 +675,6 @@ void FabricUIManagerBinding::registerNatives() { makeNativeMethod( "installFabricUIManager", FabricUIManagerBinding::installFabricUIManager), - makeNativeMethod("startSurface", FabricUIManagerBinding::startSurface), - makeNativeMethod( - "startSurfaceWithConstraints", - FabricUIManagerBinding::startSurfaceWithConstraints), - makeNativeMethod("stopSurface", FabricUIManagerBinding::stopSurface), - makeNativeMethod( - "setConstraints", FabricUIManagerBinding::setConstraints), - makeNativeMethod( - "setPixelDensity", FabricUIManagerBinding::setPixelDensity), makeNativeMethod( "driveCxxAnimations", FabricUIManagerBinding::driveCxxAnimations), makeNativeMethod( diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h index 97229f08fdcf..ccc8d7a2334d 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -48,17 +47,6 @@ class FabricUIManagerBinding : public jni::HybridClass, std::shared_ptr getScheduler(); private: - void setConstraints( - jint surfaceId, - jfloat minWidth, - jfloat maxWidth, - jfloat minHeight, - jfloat maxHeight, - jfloat offsetX, - jfloat offsetY, - jboolean isRTL, - jboolean doLeftAndRightSwapInRTL); - static void initHybrid(jni::alias_ref jobj); void installFabricUIManager( @@ -68,23 +56,6 @@ class FabricUIManagerBinding : public jni::HybridClass, EventBeatManager *eventBeatManager, ComponentFactory *componentsRegistry); - void startSurface(jint surfaceId, jni::alias_ref moduleName, NativeMap *initialProps); - - void startSurfaceWithConstraints( - jint surfaceId, - jni::alias_ref moduleName, - NativeMap *initialProps, - jfloat minWidth, - jfloat maxWidth, - jfloat minHeight, - jfloat maxHeight, - jfloat offsetX, - jfloat offsetY, - jboolean isRTL, - jboolean doLeftAndRightSwapInRTL); - - void stopSurface(jint surfaceId); - void startSurfaceWithSurfaceHandler( jint surfaceId, jni::alias_ref surfaceHandlerBinding, @@ -125,8 +96,6 @@ class FabricUIManagerBinding : public jni::HybridClass, void schedulerDidClearPendingSnapshots() override; - void setPixelDensity(float pointScaleFactor); - void driveCxxAnimations(); void driveAnimationBackend(jlong frameTimeNanos); @@ -156,19 +125,13 @@ class FabricUIManagerBinding : public jni::HybridClass, std::shared_ptr animationDriver_; - // Roots not created through ReactSurface (non-bridgeless) will store their - // SurfaceHandler here, for other roots we keep a weak reference to the Java - // owner - std::unordered_map>> - surfaceHandlerRegistry_{}; + std::unordered_map> surfaceHandlerRegistry_{}; std::shared_mutex surfaceHandlerRegistryMutex_; // Protects `surfaceHandlerRegistry_`. // Track pending transactions, one per surfaceId std::mutex pendingTransactionsMutex_; std::vector pendingTransactions_; - float pointScaleFactor_ = 1; - bool enableFabricLogs_{false}; std::shared_ptr animationChoreographer_; diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/fabric/FabricUIManagerTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/fabric/FabricUIManagerTest.kt index 38033aae0a54..61fe82a81059 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/fabric/FabricUIManagerTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/fabric/FabricUIManagerTest.kt @@ -9,6 +9,7 @@ package com.facebook.react.fabric +import android.view.View import com.facebook.react.bridge.BridgeReactContext import com.facebook.react.bridge.JavaOnlyArray import com.facebook.react.bridge.ReactApplicationContext @@ -18,6 +19,7 @@ import com.facebook.react.uimanager.events.BatchEventDispatchedListener import com.facebook.testutils.fakes.FakeBatchEventDispatchedListener import com.facebook.testutils.shadows.ShadowSoLoader import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -43,6 +45,18 @@ class FabricUIManagerTest { underTest = FabricUIManager(reactContext, viewManagerRegistry, batchEventDispatchedListener) } + @Test + fun legacySurfaceLifecycleMethods_areUnsupported() { + val rootView = View(reactContext) + + assertThatThrownBy { underTest.addRootView(rootView, null) } + .isInstanceOf(UnsupportedOperationException::class.java) + assertThatThrownBy { underTest.startSurface(rootView, "module", null, 0, 0) } + .isInstanceOf(UnsupportedOperationException::class.java) + assertThatThrownBy { underTest.stopSurface(1) } + .isInstanceOf(UnsupportedOperationException::class.java) + } + @Test fun createDispatchCommandMountItemForInterop_withValidString_returnsStringEvent() { val command =