From 637bd5e07d9c11a1e04e3d885ee12dd783163a78 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 13 Oct 2026 09:07:02 -0700 Subject: [PATCH 1/3] Deprecate legacy Android UIManager surface APIs (#59039) 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`. Reviewed By: christophpurrer 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 bca384f2296662c064088f756f11a8589cca1643 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 13 Oct 2026 09:07:02 -0700 Subject: [PATCH 2/3] Remove obsolete Android Fabric surface paths (#59036) Summary: 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 = From 8d5ce241fa80a2055171aaf452198c8f42d20b8a Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 13 Oct 2026 09:07:02 -0700 Subject: [PATCH 3/3] Remove obsolete Android UIManager surface APIs Summary: The legacy bridge can no longer be initialized, and the native bridge+Fabric surface path was removed by the parent diff. Remove the corresponding View-based lifecycle APIs from `UIManager`, `FabricUIManager`, and `UIManagerModule`, along with their throwing implementations and unreachable `ReactInstanceManager` call paths. The supported `SurfaceHandlerBinding` lifecycle remains unchanged. Changelog: [Android][Breaking] - Remove legacy View-based surface lifecycle methods from `UIManager`, `FabricUIManager`, and `UIManagerModule`. Reviewed By: christophpurrer Differential Revision: D124983537 --- .../ReactAndroid/api/ReactAndroid.api | 10 -- .../facebook/react/ReactInstanceManager.java | 96 +------------------ .../com/facebook/react/bridge/UIManager.kt | 44 --------- .../react/fabric/FabricUIManager.java | 40 -------- .../react/uimanager/UIManagerModule.kt | 37 ------- .../react/fabric/FabricUIManagerTest.kt | 14 --- .../facebook/testutils/fakes/FakeUIManager.kt | 21 ---- 7 files changed, 4 insertions(+), 258 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 6c76d3a2197f..19799efc6b83 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1364,7 +1364,6 @@ public final class com/facebook/react/bridge/ScrollEndedListeners { } public abstract interface class com/facebook/react/bridge/UIManager : com/facebook/react/bridge/PerformanceCounter { - public abstract fun addRootView (Landroid/view/View;Lcom/facebook/react/bridge/WritableMap;)I public abstract fun addUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V public abstract fun dispatchCommand (IILcom/facebook/react/bridge/ReadableArray;)V public abstract fun dispatchCommand (ILjava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V @@ -1378,8 +1377,6 @@ public abstract interface class com/facebook/react/bridge/UIManager : com/facebo public abstract fun resolveCustomDirectEventName (Ljava/lang/String;)Ljava/lang/String; public abstract fun resolveView (I)Landroid/view/View; public abstract fun sendAccessibilityEvent (II)V - public abstract fun startSurface (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/WritableMap;II)I - public abstract fun stopSurface (I)V public abstract fun sweepActiveTouchForTag (II)V public abstract fun synchronouslyUpdateViewOnUIThread (ILcom/facebook/react/bridge/ReadableMap;)V public abstract fun updateRootLayoutSpecs (IIIII)V @@ -2248,7 +2245,6 @@ public class com/facebook/react/fabric/FabricUIManager : com/facebook/react/brid public static final field TAG Ljava/lang/String; public field mDevToolsReactPerfLogger Lcom/facebook/react/fabric/DevToolsReactPerfLogger; public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Lcom/facebook/react/uimanager/ViewManagerRegistry;Lcom/facebook/react/uimanager/events/BatchEventDispatchedListener;)V - public fun addRootView (Landroid/view/View;Lcom/facebook/react/bridge/WritableMap;)I public fun addUIBlock (Lcom/facebook/react/fabric/interop/UIBlock;)V public fun addUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V public fun attachRootView (Lcom/facebook/react/fabric/SurfaceHandlerBinding;Landroid/view/View;)V @@ -2286,9 +2282,7 @@ public class com/facebook/react/fabric/FabricUIManager : com/facebook/react/brid public fun sendAccessibilityEvent (II)V public fun sendAccessibilityEventFromJS (IILjava/lang/String;)V public fun setJSResponder (IIIZ)V - public fun startSurface (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/WritableMap;II)I public fun startSurface (Lcom/facebook/react/fabric/SurfaceHandlerBinding;Landroid/content/Context;Landroid/view/View;)V - public fun stopSurface (I)V public fun stopSurface (Lcom/facebook/react/fabric/SurfaceHandlerBinding;)V public fun sweepActiveTouchForTag (II)V public fun synchronouslyUpdateViewOnUIThread (ILcom/facebook/react/bridge/ReadableMap;)V @@ -4241,8 +4235,6 @@ public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/b public static final field TAG Ljava/lang/String; public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Lcom/facebook/react/uimanager/ViewManagerResolver;I)V public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Ljava/util/List;I)V - public fun addRootView (Landroid/view/View;)I - public fun addRootView (Landroid/view/View;Lcom/facebook/react/bridge/WritableMap;)I public fun addUIBlock (Lcom/facebook/react/uimanager/UIBlock;)V public fun addUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V public fun clearJSResponder ()V @@ -4287,8 +4279,6 @@ public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/b public fun setJSResponder (IZ)V public fun setLayoutAnimationEnabledExperimental (Z)V public fun setViewLocalData (ILjava/lang/Object;)V - public fun startSurface (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/WritableMap;II)I - public fun stopSurface (I)V public fun sweepActiveTouchForTag (II)V public fun synchronouslyUpdateViewOnUIThread (ILcom/facebook/react/bridge/ReadableMap;)V public fun updateInsetsPadding (IIIII)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index f2f254cd48d4..f09ecb1f9897 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -8,8 +8,6 @@ package com.facebook.react; import static com.facebook.infer.annotation.ThreadConfined.UI; -import static com.facebook.react.bridge.ReactMarkerConstants.ATTACH_MEASURED_ROOT_VIEWS_END; -import static com.facebook.react.bridge.ReactMarkerConstants.ATTACH_MEASURED_ROOT_VIEWS_START; import static com.facebook.react.bridge.ReactMarkerConstants.CHANGE_THREAD_PRIORITY; import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_VIEW_MANAGERS_END; import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_VIEW_MANAGERS_START; @@ -20,7 +18,6 @@ import static com.facebook.react.bridge.ReactMarkerConstants.SETUP_REACT_CONTEXT_END; import static com.facebook.react.bridge.ReactMarkerConstants.SETUP_REACT_CONTEXT_START; import static com.facebook.react.bridge.ReactMarkerConstants.VM_INIT; -import static com.facebook.react.uimanager.common.UIManagerType.FABRIC; import static com.facebook.systrace.Systrace.TRACE_TAG_REACT; import android.annotation.SuppressLint; @@ -42,7 +39,6 @@ import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.ThreadConfined; import com.facebook.infer.annotation.ThreadSafe; -import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.JSBundleLoader; import com.facebook.react.bridge.JSExceptionHandler; @@ -54,10 +50,8 @@ import com.facebook.react.bridge.ReactMarkerConstants; import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; -import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.UIManagerProvider; import com.facebook.react.bridge.UiThreadUtil; -import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.LifecycleState; import com.facebook.react.common.ReactConstants; import com.facebook.react.common.SurfaceDelegateFactory; @@ -82,8 +76,6 @@ import com.facebook.react.packagerconnection.RequestHandler; import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.ReactRoot; -import com.facebook.react.uimanager.ReactStage; -import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; import com.facebook.soloader.SoLoader; @@ -766,7 +758,7 @@ public void destroy() { synchronized (mReactContextLock) { if (mCurrentReactContext != null) { for (ReactRoot reactRoot : mAttachedReactRoots) { - detachRootViewFromInstance(reactRoot, mCurrentReactContext); + detachRootViewFromInstance(reactRoot); } mCurrentReactContext.destroy(); @@ -910,14 +902,6 @@ public void attachRootView(ReactRoot reactRoot) { } else { FLog.e(ReactConstants.TAG, "ReactRoot was attached multiple times"); } - - // If react context is being created in the background, JS application will be started - // automatically when creation completes, as reactRoot is part of the attached - // reactRoot list. - ReactContext currentContext = getCurrentReactContext(); - if (mCreateReactContextThread == null && currentContext != null) { - attachRootViewToInstance(reactRoot); - } } } @@ -935,11 +919,7 @@ public void detachRootView(ReactRoot reactRoot) { if (!mAttachedReactRoots.remove(reactRoot)) { return; } - - ReactContext reactContext = mCurrentReactContext; - if (reactContext != null && reactContext.hasActiveReactInstance()) { - detachRootViewFromInstance(reactRoot, reactContext); - } + clearReactRoot(reactRoot); } /** Uses configured {@link ReactPackage} instances to create all view managers. */ @@ -1217,12 +1197,6 @@ private void setupReactContext(final ReactApplicationContext reactContext) { mDevSupportManager.onNewReactContextCreated(reactContext); mMemoryPressureRouter.addMemoryPressureListener(catalystInstance); - - ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_START); - for (ReactRoot reactRoot : mAttachedReactRoots) { - attachRootViewToInstance(reactRoot); - } - ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_END); } // There is a race condition here - `finalListeners` can contain null entries @@ -1260,48 +1234,7 @@ private void setupReactContext(final ReactApplicationContext reactContext) { ReactMarker.logMarker(ReactMarkerConstants.REACT_BRIDGE_LOADING_END); } - private void attachRootViewToInstance(final ReactRoot reactRoot) { - FLog.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()"); - if (!reactRoot.getState().compareAndSet(ReactRoot.STATE_STOPPED, ReactRoot.STATE_STARTED)) { - // Already started - return; - } - - Systrace.beginSection(TRACE_TAG_REACT, "attachRootViewToInstance"); - - @Nullable UIManager uiManager = UIManagerHelper.getUIManager(mCurrentReactContext, FABRIC); - - // If we can't get a UIManager something has probably gone horribly wrong - if (uiManager == null) { - throw new IllegalStateException( - "Unable to attach a rootView to ReactInstance when UIManager is not properly" - + " initialized."); - } - - @Nullable Bundle initialProperties = reactRoot.getAppProperties(); - - final int rootTag = - uiManager.startSurface( - reactRoot.getRootViewGroup(), - reactRoot.getJSModuleName(), - initialProperties == null - ? new WritableNativeMap() - : Arguments.fromBundle(initialProperties), - reactRoot.getWidthMeasureSpec(), - reactRoot.getHeightMeasureSpec()); - reactRoot.setShouldLogContentAppeared(true); - - Systrace.beginAsyncSection(TRACE_TAG_REACT, "pre_rootView.onAttachedToReactInstance", rootTag); - UiThreadUtil.runOnUiThread( - () -> { - Systrace.endAsyncSection( - TRACE_TAG_REACT, "pre_rootView.onAttachedToReactInstance", rootTag); - reactRoot.onStage(ReactStage.ON_ATTACH_TO_INSTANCE); - }); - Systrace.endSection(TRACE_TAG_REACT); - } - - private void detachRootViewFromInstance(ReactRoot reactRoot, ReactContext reactContext) { + private void detachRootViewFromInstance(ReactRoot reactRoot) { FLog.d(ReactConstants.TAG, "ReactInstanceManager.detachRootViewFromInstance()"); UiThreadUtil.assertOnUiThread(); @@ -1310,27 +1243,6 @@ private void detachRootViewFromInstance(ReactRoot reactRoot, ReactContext reactC return; } - // Stop surface in Fabric. - // Calling FabricUIManager.stopSurface causes the C++ Binding.stopSurface - // to be called synchronously over the JNI, which causes an empty tree - // to be committed via the Scheduler, which will cause mounting instructions - // to be queued up and synchronously executed to delete and remove - // all the views in the hierarchy. - final int surfaceId = reactRoot.getRootViewTag(); - if (surfaceId != View.NO_ID) { - UIManager uiManager = UIManagerHelper.getUIManager(reactContext, FABRIC); - if (uiManager != null) { - uiManager.stopSurface(surfaceId); - } else { - FLog.w(ReactConstants.TAG, "Failed to stop surface, UIManager has already gone away"); - } - } else { - ReactSoftExceptionLogger.logSoftException( - TAG, - new RuntimeException( - "detachRootViewFromInstance called with ReactRootView with invalid id")); - } - clearReactRoot(reactRoot); } @@ -1344,7 +1256,7 @@ private void tearDownReactContext(ReactContext reactContext) { synchronized (mAttachedReactRoots) { for (ReactRoot reactRoot : mAttachedReactRoots) { - detachRootViewFromInstance(reactRoot, reactContext); + detachRootViewFromInstance(reactRoot); } } 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 7587d9cc7a89..1465f07eb784 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 @@ -8,7 +8,6 @@ package com.facebook.react.bridge import android.view.View -import androidx.annotation.AnyThread import androidx.annotation.UiThread import com.facebook.infer.annotation.ThreadConfined import com.facebook.react.common.annotations.UnstableReactNativeAPI @@ -16,49 +15,6 @@ import com.facebook.react.uimanager.events.EventDispatcher @OptIn(UnstableReactNativeAPI::class) public interface UIManager : PerformanceCounter { - /** - * Registers a new root view. - * - * @deprecated Use `ReactHost.createSurface(...)` and `ReactSurface.start()` instead. - */ - @UiThread - @ThreadConfined(ThreadConfined.UI) - @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. - * - * @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, - initialProps: WritableMap?, - widthMeasureSpec: Int, - heightMeasureSpec: Int, - ): Int - - /** - * 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 - @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 * parameters. offsetX and offsetY are the position of the RootView within the screen. 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 76556860259f..c8004f8fe3b1 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 @@ -255,18 +255,6 @@ public FabricUIManager( mReactApplicationContext.registerComponentCallbacks(viewManagerRegistry); } - /** - * @deprecated Use {@code ReactHost.createSurface(...)} and {@code ReactSurface.start()} instead. - */ - @Override - @UiThread - @ThreadConfined(UI) - @Deprecated - public int addRootView( - final T rootView, final @Nullable WritableMap initialProps) { - throw new UnsupportedOperationException("FabricUIManager.addRootView is unsupported."); - } - /** * Find the next focusable element's id and position relative to the parent from the shadow tree * based on the current focusable element and the direction. @@ -319,23 +307,6 @@ 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) - public int startSurface( - final T rootView, - final String moduleName, - final @Nullable WritableMap initialProps, - int widthMeasureSpec, - int heightMeasureSpec) { - throw new UnsupportedOperationException( - "FabricUIManager.startSurface(View, ...) is unsupported."); - } - public void startSurface( final SurfaceHandlerBinding surfaceHandler, final Context context, @@ -384,17 +355,6 @@ public void onRequestEventBeat() { mEventDispatcher.dispatchAllEvents(); } - /** - * @deprecated Use {@code ReactSurface.stop()} instead. - */ - @Deprecated - @AnyThread - @ThreadConfined(ANY) - @Override - public void stopSurface(final int surfaceID) { - throw new UnsupportedOperationException("FabricUIManager.stopSurface(int) is unsupported."); - } - @Override public void initialize() { mEventDispatcher.addBatchEventDispatchedListener(mBatchEventDispatchedListener); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.kt index e2da958fb238..abb8d635e664 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.kt @@ -204,9 +204,6 @@ public open class UIManagerModule : ReactContextBaseJavaModule, LifecycleEventLi override val performanceCounters: Map get() = HashMap() - /** Adds a root view with no initial properties. */ - public open fun addRootView(rootView: T): Int = addRootView(rootView, null) - /** * Used by native animated module to bypass the process of updating the values through the shadow * view hierarchy. This method will directly update native views, which means that updates for @@ -215,40 +212,6 @@ public open class UIManagerModule : ReactContextBaseJavaModule, LifecycleEventLi */ override fun synchronouslyUpdateViewOnUIThread(reactTag: Int, props: ReadableMap): Unit = Unit - /** - * Registers a new root view. JS can use the returned tag with manageChildren to add/remove - * children to this view. - * - * Calling addRootView through UIManagerModule calls addRootView in the non-Fabric renderer, - * always. This is deprecated in favor of calling startSurface in Fabric, which must be done - * directly through the FabricUIManager. - * - * Note that this must be called after getWidth()/getHeight() actually return something. See - * CatalystApplicationFragment as an example. - * - * TODO(6242243): Make addRootView thread safe NB: this method is horribly not-thread-safe. - */ - override fun addRootView(rootView: T, initialProps: WritableMap?): Int { - Systrace.beginSection(Systrace.TRACE_TAG_REACT, "UIManagerModule.addRootView") - val tag = ReactRootViewTagGenerator.getNextRootViewTag() - Systrace.endSection(Systrace.TRACE_TAG_REACT) - return tag - } - - override fun startSurface( - rootView: T, - moduleName: String, - initialProps: WritableMap?, - widthMeasureSpec: Int, - heightMeasureSpec: Int, - ): Int { - throw UnsupportedOperationException() - } - - override fun stopSurface(surfaceId: Int) { - throw UnsupportedOperationException() - } - /** Unregisters a new root view. */ @ReactMethod public open fun removeRootView(rootViewTag: Int): Unit = Unit 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 61fe82a81059..38033aae0a54 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,7 +9,6 @@ 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 @@ -19,7 +18,6 @@ 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 @@ -45,18 +43,6 @@ 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 = 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 e1e708edcd1b..0572a7f90e53 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 @@ -29,27 +29,6 @@ class FakeUIManager : UIManager, UIBlockViewResolver { error("Not yet implemented") } - @Deprecated("") - override fun addRootView(rootView: T, initialProps: WritableMap?): Int { - error("Not yet implemented") - } - - @Deprecated("") - override fun startSurface( - rootView: T, - moduleName: String, - initialProps: WritableMap?, - widthMeasureSpec: Int, - heightMeasureSpec: Int, - ): Int { - error("Not yet implemented") - } - - @Deprecated("") - override fun stopSurface(surfaceId: Int) { - error("Not yet implemented") - } - override fun updateRootLayoutSpecs( rootTag: Int, widthMeasureSpec: Int,