From d967c8e71a7b892c6a1f09484742352ded956b28 Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 03:27:23 -0700
Subject: [PATCH 01/13] Apply Nullsafe FIXMEs for
 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java

Summary:
Note this diff is only adding FIXMEs that will be removed in the next diff. This diff exists to make the next diff easily reviewable

Changelog: [Internal]

Differential Revision: D71126384
---
 .../react/devsupport/StackTraceHelper.java       | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java
index 9975ae6e7e6837..57e70b1dc6a5fe 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java
@@ -137,23 +137,34 @@ public static StackFrame[] convertJsStackTrace(@Nullable ReadableArray stack) {
     int size = stack != null ? stack.size() : 0;
     StackFrame[] result = new StackFrame[size];
     for (int i = 0; i < size; i++) {
+      // NULLSAFE_FIXME[Nullable Dereference]
       ReadableType type = stack.getType(i);
       if (type == ReadableType.Map) {
+        // NULLSAFE_FIXME[Nullable Dereference]
         ReadableMap frame = stack.getMap(i);
+        // NULLSAFE_FIXME[Nullable Dereference]
         String methodName = frame.getString("methodName");
+        // NULLSAFE_FIXME[Nullable Dereference]
         String fileName = frame.getString("file");
         boolean collapse =
+            // NULLSAFE_FIXME[Nullable Dereference]
             frame.hasKey("collapse") && !frame.isNull("collapse") && frame.getBoolean("collapse");
         int lineNumber = -1;
+        // NULLSAFE_FIXME[Nullable Dereference]
         if (frame.hasKey(LINE_NUMBER_KEY) && !frame.isNull(LINE_NUMBER_KEY)) {
+          // NULLSAFE_FIXME[Nullable Dereference]
           lineNumber = frame.getInt(LINE_NUMBER_KEY);
         }
         int columnNumber = -1;
+        // NULLSAFE_FIXME[Nullable Dereference]
         if (frame.hasKey(COLUMN_KEY) && !frame.isNull(COLUMN_KEY)) {
+          // NULLSAFE_FIXME[Nullable Dereference]
           columnNumber = frame.getInt(COLUMN_KEY);
         }
+        // NULLSAFE_FIXME[Parameter Not Nullable]
         result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber, collapse);
       } else if (type == ReadableType.String) {
+        // NULLSAFE_FIXME[Parameter Not Nullable, Nullable Dereference]
         result[i] = new StackFrameImpl(null, stack.getString(i), -1, -1);
       }
     }
@@ -203,14 +214,18 @@ public static StackFrame[] convertJsStackTrace(String stack) {
       } else if (matcher1.find()) {
         matcher = matcher1;
       } else {
+        // NULLSAFE_FIXME[Parameter Not Nullable]
         result[i] = new StackFrameImpl(null, stackTrace[i], -1, -1);
         continue;
       }
       result[i] =
           new StackFrameImpl(
+              // NULLSAFE_FIXME[Parameter Not Nullable]
               matcher.group(2),
               matcher.group(1) == null ? "(unknown)" : matcher.group(1),
+              // NULLSAFE_FIXME[Parameter Not Nullable]
               Integer.parseInt(matcher.group(3)),
+              // NULLSAFE_FIXME[Parameter Not Nullable]
               Integer.parseInt(matcher.group(4)));
     }
     return result;
@@ -224,6 +239,7 @@ public static StackFrame[] convertJavaStackTrace(Throwable exception) {
       result[i] =
           new StackFrameImpl(
               stackTrace[i].getClassName(),
+              // NULLSAFE_FIXME[Parameter Not Nullable]
               stackTrace[i].getFileName(),
               stackTrace[i].getMethodName(),
               stackTrace[i].getLineNumber(),

From 2715cf7245e25c2d471ddafb3bc001d783d3f36e Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 05:14:07 -0700
Subject: [PATCH 02/13] Fix Nullsafe FIXMEs for StackTraceHelper.java and mark
 Nullsafe

Summary:
Gone trough all the FIXMEs added in the previous diff by the nullsafe tool, marked the class as nullsafe and ensured no remaining violations.

Changelog: [Android][Fixed] Made StackTraceHelper.java nullsafe

Differential Revision: D71126387
---
 .../react/devsupport/StackTraceHelper.java    | 103 ++++++++++--------
 .../react/devsupport/interfaces/StackFrame.kt |   4 +-
 .../react/devsupport/StackTraceHelperTest.kt  |   4 +-
 3 files changed, 59 insertions(+), 52 deletions(-)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java
index 57e70b1dc6a5fe..06084402c2b152 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java
@@ -8,6 +8,8 @@
 package com.facebook.react.devsupport;
 
 import androidx.annotation.Nullable;
+import com.facebook.infer.annotation.Assertions;
+import com.facebook.infer.annotation.Nullsafe;
 import com.facebook.react.bridge.JavaOnlyArray;
 import com.facebook.react.bridge.JavaOnlyMap;
 import com.facebook.react.bridge.ReadableArray;
@@ -26,6 +28,7 @@
 import org.json.JSONObject;
 
 /** Helper class converting JS and Java stack traces into arrays of {@link StackFrame} objects. */
+@Nullsafe(Nullsafe.Mode.LOCAL)
 public class StackTraceHelper {
 
   public static final String COLUMN_KEY = "column";
@@ -49,27 +52,29 @@ public class StackTraceHelper {
 
   /** Represents a generic entry in a stack trace, be it originally from JS or Java. */
   public static class StackFrameImpl implements StackFrame {
-    private final String mFile;
+    @Nullable private final String mFile;
     private final String mMethod;
     private final int mLine;
     private final int mColumn;
-    private final String mFileName;
+    @Nullable private final String mFileName;
     private final boolean mIsCollapsed;
 
-    private StackFrameImpl(String file, String method, int line, int column, boolean isCollapsed) {
+    private StackFrameImpl(
+        @Nullable String file, String method, int line, int column, boolean isCollapsed) {
       mFile = file;
       mMethod = method;
       mLine = line;
       mColumn = column;
-      mFileName = file != null ? new File(file).getName() : "";
+      mFileName = file != null ? new File(file).getName() : null;
       mIsCollapsed = isCollapsed;
     }
 
-    private StackFrameImpl(String file, String method, int line, int column) {
+    private StackFrameImpl(@Nullable String file, String method, int line, int column) {
       this(file, method, line, column, false);
     }
 
-    private StackFrameImpl(String file, String fileName, String method, int line, int column) {
+    private StackFrameImpl(
+        @Nullable String file, @Nullable String fileName, String method, int line, int column) {
       mFile = file;
       mFileName = fileName;
       mMethod = method;
@@ -84,7 +89,8 @@ private StackFrameImpl(String file, String fileName, String method, int line, in
      * <p>JS traces return the full path to the file here, while Java traces only return the file
      * name (the path is not known).
      */
-    public String getFile() {
+    @Override
+    public @Nullable String getFile() {
       return mFile;
     }
 
@@ -109,7 +115,8 @@ public int getColumn() {
      * <p>For JS traces this is different from {@link #getFile()} in that it only returns the file
      * name, not the full path. For Java traces there is no difference.
      */
-    public String getFileName() {
+    @Override
+    public @Nullable String getFileName() {
       return mFileName;
     }
 
@@ -119,9 +126,10 @@ public boolean isCollapsed() {
 
     /** Convert the stack frame to a JSON representation. */
     public JSONObject toJSON() {
+      String file = getFile();
       return new JSONObject(
           MapBuilder.of(
-              "file", getFile(),
+              "file", (file == null) ? "" : file,
               "methodName", getMethod(),
               "lineNumber", getLine(),
               "column", getColumn(),
@@ -136,36 +144,33 @@ public JSONObject toJSON() {
   public static StackFrame[] convertJsStackTrace(@Nullable ReadableArray stack) {
     int size = stack != null ? stack.size() : 0;
     StackFrame[] result = new StackFrame[size];
-    for (int i = 0; i < size; i++) {
-      // NULLSAFE_FIXME[Nullable Dereference]
-      ReadableType type = stack.getType(i);
-      if (type == ReadableType.Map) {
-        // NULLSAFE_FIXME[Nullable Dereference]
-        ReadableMap frame = stack.getMap(i);
-        // NULLSAFE_FIXME[Nullable Dereference]
-        String methodName = frame.getString("methodName");
-        // NULLSAFE_FIXME[Nullable Dereference]
-        String fileName = frame.getString("file");
-        boolean collapse =
-            // NULLSAFE_FIXME[Nullable Dereference]
-            frame.hasKey("collapse") && !frame.isNull("collapse") && frame.getBoolean("collapse");
-        int lineNumber = -1;
-        // NULLSAFE_FIXME[Nullable Dereference]
-        if (frame.hasKey(LINE_NUMBER_KEY) && !frame.isNull(LINE_NUMBER_KEY)) {
-          // NULLSAFE_FIXME[Nullable Dereference]
-          lineNumber = frame.getInt(LINE_NUMBER_KEY);
-        }
-        int columnNumber = -1;
-        // NULLSAFE_FIXME[Nullable Dereference]
-        if (frame.hasKey(COLUMN_KEY) && !frame.isNull(COLUMN_KEY)) {
-          // NULLSAFE_FIXME[Nullable Dereference]
-          columnNumber = frame.getInt(COLUMN_KEY);
+    if (stack != null) {
+      for (int i = 0; i < size; i++) {
+        ReadableType type = stack.getType(i);
+        if (type == ReadableType.Map) {
+          ReadableMap frame = stack.getMap(i);
+          Assertions.assertNotNull(frame);
+          String methodName = frame.getString("methodName");
+          String fileName = frame.getString("file");
+          Assertions.assertNotNull(fileName);
+          Assertions.assertNotNull(methodName);
+          boolean collapse =
+              frame.hasKey("collapse") && !frame.isNull("collapse") && frame.getBoolean("collapse");
+          int lineNumber = -1;
+          if (frame.hasKey(LINE_NUMBER_KEY) && !frame.isNull(LINE_NUMBER_KEY)) {
+            lineNumber = frame.getInt(LINE_NUMBER_KEY);
+          }
+          int columnNumber = -1;
+          if (frame.hasKey(COLUMN_KEY) && !frame.isNull(COLUMN_KEY)) {
+            columnNumber = frame.getInt(COLUMN_KEY);
+          }
+          result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber, collapse);
+        } else if (type == ReadableType.String) {
+          String stackFrame = stack.getString(i);
+          if (stackFrame != null) {
+            result[i] = new StackFrameImpl(null, stackFrame, -1, -1);
+          }
         }
-        // NULLSAFE_FIXME[Parameter Not Nullable]
-        result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber, collapse);
-      } else if (type == ReadableType.String) {
-        // NULLSAFE_FIXME[Parameter Not Nullable, Nullable Dereference]
-        result[i] = new StackFrameImpl(null, stack.getString(i), -1, -1);
       }
     }
     return result;
@@ -214,19 +219,22 @@ public static StackFrame[] convertJsStackTrace(String stack) {
       } else if (matcher1.find()) {
         matcher = matcher1;
       } else {
-        // NULLSAFE_FIXME[Parameter Not Nullable]
-        result[i] = new StackFrameImpl(null, stackTrace[i], -1, -1);
+        String unmatchedStackFrame = stackTrace[i];
+        if (unmatchedStackFrame != null) {
+          result[i] = new StackFrameImpl(null, unmatchedStackFrame, -1, -1);
+        }
+        continue;
+      }
+      String fileName = matcher.group(2);
+      String methodName = matcher.group(1) == null ? "(unknown)" : matcher.group(1);
+      String lineString = matcher.group(3);
+      String columnString = matcher.group(4);
+      if (methodName == null || fileName == null || lineString == null || columnString == null) {
         continue;
       }
       result[i] =
           new StackFrameImpl(
-              // NULLSAFE_FIXME[Parameter Not Nullable]
-              matcher.group(2),
-              matcher.group(1) == null ? "(unknown)" : matcher.group(1),
-              // NULLSAFE_FIXME[Parameter Not Nullable]
-              Integer.parseInt(matcher.group(3)),
-              // NULLSAFE_FIXME[Parameter Not Nullable]
-              Integer.parseInt(matcher.group(4)));
+              fileName, methodName, Integer.parseInt(lineString), Integer.parseInt(columnString));
     }
     return result;
   }
@@ -239,7 +247,6 @@ public static StackFrame[] convertJavaStackTrace(Throwable exception) {
       result[i] =
           new StackFrameImpl(
               stackTrace[i].getClassName(),
-              // NULLSAFE_FIXME[Parameter Not Nullable]
               stackTrace[i].getFileName(),
               stackTrace[i].getMethodName(),
               stackTrace[i].getLineNumber(),
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/StackFrame.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/StackFrame.kt
index 47f32567879a0f..8f462ae6171bae 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/StackFrame.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/StackFrame.kt
@@ -20,7 +20,7 @@ public interface StackFrame {
   public val file: String?
 
   /** Get the name of the method this frame points to. */
-  public val method: String?
+  public val method: String
 
   /** Get the line number this frame points to in the file returned by [.getFile]. */
   public val line: Int
@@ -40,5 +40,5 @@ public interface StackFrame {
   public val isCollapsed: Boolean
 
   /** Convert the stack frame to a JSON representation. */
-  public fun toJSON(): JSONObject?
+  public fun toJSON(): JSONObject
 }
diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/StackTraceHelperTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/StackTraceHelperTest.kt
index 9476927d3eba4d..33dcc7e7ba3293 100644
--- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/StackTraceHelperTest.kt
+++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/StackTraceHelperTest.kt
@@ -47,7 +47,7 @@ class StackTraceHelperTest {
   fun testParseStackFrameWithInvalidFrame() {
     val frame = StackTraceHelper.convertJsStackTrace("Test.bundle:ten:twenty").get(0)
     assertThat(frame.method).isEqualTo("Test.bundle:ten:twenty")
-    assertThat(frame.fileName).isEqualTo("")
+    assertThat(frame.fileName).isEqualTo(null)
     assertThat(frame.line).isEqualTo(-1)
     assertThat(frame.column).isEqualTo(-1)
   }
@@ -56,7 +56,7 @@ class StackTraceHelperTest {
   fun testParseStackFrameWithNativeCodeFrame() {
     val frame = StackTraceHelper.convertJsStackTrace("forEach@[native code]").get(0)
     assertThat(frame.method).isEqualTo("forEach@[native code]")
-    assertThat(frame.fileName).isEqualTo("")
+    assertThat(frame.fileName).isEqualTo(null)
     assertThat(frame.line).isEqualTo(-1)
     assertThat(frame.column).isEqualTo(-1)
   }

From 6d490e9e68c77585b80dc94c8510f81dc3704ad1 Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 05:14:08 -0700
Subject: [PATCH 03/13] Apply Nullsafe FIXMEs for
 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java

Summary:
Note this diff is only adding FIXMEs that will be removed in the next diff. This diff exists to make the next diff easily reviewable

Changelog: [Internal]

Differential Revision: D71126389
---
 .../com/facebook/react/devsupport/MultipartStreamReader.java    | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java
index 3f74eb60983d08..7c343d41b8143f 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java
@@ -60,6 +60,7 @@ private void emitChunk(Buffer chunk, boolean done, ChunkListener listener) throw
     ByteString marker = ByteString.encodeUtf8(CRLF + CRLF);
     long indexOfMarker = chunk.indexOf(marker);
     if (indexOfMarker == -1) {
+      // NULLSAFE_FIXME[Parameter Not Nullable]
       listener.onChunkComplete(null, chunk, done);
     } else {
       Buffer headers = new Buffer();
@@ -148,6 +149,7 @@ public boolean readAllParts(ChunkListener listener) throws IOException {
         Buffer chunk = new Buffer();
         content.skip(chunkStart);
         content.read(chunk, length);
+        // NULLSAFE_FIXME[Parameter Not Nullable]
         emitProgress(currentHeaders, chunk.size() - currentHeadersLength, true, listener);
         emitChunk(chunk, isCloseDelimiter, listener);
         currentHeaders = null;

From 65bf3835547337f0bba9d040180bec6348838406 Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 05:14:08 -0700
Subject: [PATCH 04/13] Fix Nullsafe FIXMEs for MultipartStreamReader.java

Summary:
Gone trough all the FIXMEs added in the previous diff by the nullsafe tool, marked the class as nullsafe and ensured no remaining violations.

Changelog: [Android][Fixed] Made MultipartStreamReader.java nullsafe

Differential Revision: D71126393
---
 .../facebook/react/devsupport/MultipartStreamReader.java    | 6 ++++--
 .../facebook/react/devsupport/MultipartStreamReaderTest.kt  | 6 +++---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java
index 7c343d41b8143f..4c99f9bee75fbb 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.java
@@ -7,7 +7,9 @@
 
 package com.facebook.react.devsupport;
 
+import com.facebook.infer.annotation.Nullsafe;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import okio.Buffer;
@@ -15,6 +17,7 @@
 import okio.ByteString;
 
 /** Utility class to parse the body of a response of type multipart/mixed. */
+@Nullsafe(Nullsafe.Mode.LOCAL)
 class MultipartStreamReader {
   // Standard line separator for HTTP.
   private static final String CRLF = "\r\n";
@@ -60,8 +63,7 @@ private void emitChunk(Buffer chunk, boolean done, ChunkListener listener) throw
     ByteString marker = ByteString.encodeUtf8(CRLF + CRLF);
     long indexOfMarker = chunk.indexOf(marker);
     if (indexOfMarker == -1) {
-      // NULLSAFE_FIXME[Parameter Not Nullable]
-      listener.onChunkComplete(null, chunk, done);
+      listener.onChunkComplete(Collections.emptyMap(), chunk, done);
     } else {
       Buffer headers = new Buffer();
       Buffer body = new Buffer();
diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/MultipartStreamReaderTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/MultipartStreamReaderTest.kt
index b6e56307d3198c..2a693a8c1ee165 100644
--- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/MultipartStreamReaderTest.kt
+++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/MultipartStreamReaderTest.kt
@@ -33,7 +33,7 @@ class MultipartStreamReaderTest {
 
     val callback: CallCountTrackingChunkCallback =
         object : CallCountTrackingChunkCallback() {
-          override fun onChunkComplete(headers: Map<String, String>?, body: Buffer, done: Boolean) {
+          override fun onChunkComplete(headers: Map<String, String>, body: Buffer, done: Boolean) {
             super.onChunkComplete(headers, body, done)
 
             assertThat(done).isTrue
@@ -68,7 +68,7 @@ class MultipartStreamReaderTest {
 
     val callback: CallCountTrackingChunkCallback =
         object : CallCountTrackingChunkCallback() {
-          override fun onChunkComplete(headers: Map<String, String>?, body: Buffer, done: Boolean) {
+          override fun onChunkComplete(headers: Map<String, String>, body: Buffer, done: Boolean) {
             super.onChunkComplete(headers, body, done)
 
             assertThat(done).isEqualTo(callCount == 3)
@@ -125,7 +125,7 @@ class MultipartStreamReaderTest {
     var callCount = 0
       private set
 
-    override fun onChunkComplete(headers: Map<String, String>?, body: Buffer, done: Boolean) {
+    override fun onChunkComplete(headers: Map<String, String>, body: Buffer, done: Boolean) {
       callCount++
     }
 

From 526e0ba50bed1cb51e9b6235fe26da2985140d7b Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 05:14:08 -0700
Subject: [PATCH 05/13] Apply Nullsafe FIXMEs for
 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java

Summary:
Note this diff is only adding FIXMEs that will be removed in the next diff. This diff exists to make the next diff easily reviewable

Changelog: [Internal]

Differential Revision: D71126392
---
 .../com/facebook/react/devsupport/JSDebuggerWebSocketClient.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java
index c5ee17c8441193..98a4bbe9b6c2cb 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java
@@ -210,6 +210,7 @@ public void onMessage(@Nullable WebSocket webSocket, String text) {
   }
 
   @Override
+  // NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
   public void onFailure(WebSocket webSocket, Throwable t, Response response) {
     abort("Websocket exception", t);
   }

From f78c1d312cdf796ad9dde06e07096861b174f1f1 Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 05:14:08 -0700
Subject: [PATCH 06/13] Fix Nullsafe FIXMEs for JSDebuggerWebSocketClient.java
 and mark nullsafe

Summary:
Gone trough all the FIXMEs added in the previous diff by the nullsafe tool, marked the class as nullsafe and ensured no remaining violations.

Changelog: [Android][Fixed] Made JSDebuggerWebsocketClient.java nullsafe

Differential Revision: D71126385
---
 .../facebook/react/devsupport/JSDebuggerWebSocketClient.java | 5 +++--
 .../react/devsupport/JSDebuggerWebSocketClientTest.kt        | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java
index 98a4bbe9b6c2cb..be02307e1b342d 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/JSDebuggerWebSocketClient.java
@@ -13,6 +13,7 @@
 import androidx.annotation.Nullable;
 import com.facebook.common.logging.FLog;
 import com.facebook.infer.annotation.Assertions;
+import com.facebook.infer.annotation.Nullsafe;
 import com.facebook.react.common.JavascriptException;
 import com.facebook.react.common.annotations.VisibleForTesting;
 import java.io.IOException;
@@ -29,6 +30,7 @@
 import okhttp3.WebSocketListener;
 
 /** A wrapper around WebSocketClient that recognizes RN debugging message format. */
+@Nullsafe(Nullsafe.Mode.LOCAL)
 class JSDebuggerWebSocketClient extends WebSocketListener {
 
   private static final String TAG = "JSDebuggerWebSocketClient";
@@ -210,8 +212,7 @@ public void onMessage(@Nullable WebSocket webSocket, String text) {
   }
 
   @Override
-  // NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
-  public void onFailure(WebSocket webSocket, Throwable t, Response response) {
+  public void onFailure(@Nullable WebSocket webSocket, Throwable t, @Nullable Response response) {
     abort("Websocket exception", t);
   }
 
diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.kt
index fbef2c7dc9e1b7..bcec632eb6250e 100644
--- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.kt
+++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.kt
@@ -41,7 +41,7 @@ class JSDebuggerWebSocketClientTest {
     val client = spy(JSDebuggerWebSocketClient())
     val injectedObjects = mapOf("key1" to "value1", "key2" to "value2")
     client.loadBundle(
-        "http://localhost:8080/index.js", injectedObjects as HashMap<String, String>?, cb)
+        "http://localhost:8080/index.js", injectedObjects as HashMap<String, String>, cb)
     verify(client)
         .sendMessage(
             0,

From 7e46cf02e4b56bf49ad4510484d52e13837eb096 Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 05:14:08 -0700
Subject: [PATCH 07/13] Apply Nullsafe FIXMEs for
 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java

Summary:
Note this diff is only adding FIXMEs that will be removed in the next diff. This diff exists to make the next diff easily reviewable

Changelog: [Internal]

Differential Revision: D71126395
---
 .../java/com/facebook/react/devsupport/DevServerHelper.java     | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java
index 0a9fab60e39ce7..3ca204db7f2f95 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java
@@ -208,6 +208,7 @@ protected Void doInBackground(Void... params) {
 
         mInspectorPackagerConnection =
             new CxxInspectorPackagerConnection(
+                // NULLSAFE_FIXME[Parameter Not Nullable]
                 getInspectorDeviceUrl(), metadata.get("deviceName"), mPackageName);
         mInspectorPackagerConnection.connect();
         return null;
@@ -452,6 +453,7 @@ public String getSourceUrl(String mainModuleName) {
       }
 
       try (Sink output = Okio.sink(outputFile)) {
+        // NULLSAFE_FIXME[Nullable Dereference]
         Okio.buffer(response.body().source()).readAll(output);
       }
 

From b0d6cad6e3fe2c965cd433f700bfbf127ff7bd27 Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 07:06:39 -0700
Subject: [PATCH 08/13] Fix Nullsafe FIXMEs for DevServerHelper.java and mark
 nullsafe

Summary:
Gone trough all the FIXMEs added in the previous diff by the nullsafe tool, marked the class as nullsafe and ensured no remaining violations.

Changelog: [Android][Fixed] Made DevServerHelper.java nullsafe

Differential Revision: D71126391
---
 .../react/devsupport/DevServerHelper.java         | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java
index 3ca204db7f2f95..d59c09544416a9 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java
@@ -15,6 +15,7 @@
 import androidx.annotation.Nullable;
 import com.facebook.common.logging.FLog;
 import com.facebook.infer.annotation.Assertions;
+import com.facebook.infer.annotation.Nullsafe;
 import com.facebook.react.bridge.ReactContext;
 import com.facebook.react.common.ReactConstants;
 import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
@@ -59,6 +60,7 @@
  *   <li>Genymotion emulator with default settings: 10.0.3.2
  * </ul>
  */
+@Nullsafe(Nullsafe.Mode.LOCAL)
 public class DevServerHelper {
   private static final int HTTP_CONNECT_TIMEOUT_MS = 5000;
 
@@ -205,11 +207,13 @@ public void openInspectorConnection() {
       protected Void doInBackground(Void... params) {
         Map<String, String> metadata =
             AndroidInfoHelpers.getInspectorHostMetadata(mApplicationContext);
-
+        String deviceName = metadata.get("deviceName");
+        if (deviceName == null) {
+          FLog.w(ReactConstants.TAG, "Could not get device name from Inspector Host Metadata.");
+          return null;
+        }
         mInspectorPackagerConnection =
-            new CxxInspectorPackagerConnection(
-                // NULLSAFE_FIXME[Parameter Not Nullable]
-                getInspectorDeviceUrl(), metadata.get("deviceName"), mPackageName);
+            new CxxInspectorPackagerConnection(getInspectorDeviceUrl(), deviceName, mPackageName);
         mInspectorPackagerConnection.connect();
         return null;
       }
@@ -448,12 +452,11 @@ public String getSourceUrl(String mainModuleName) {
     final Request request = new Request.Builder().url(resourceURL).build();
 
     try (Response response = mClient.newCall(request).execute()) {
-      if (!response.isSuccessful()) {
+      if (!response.isSuccessful() || response.body() == null) {
         return null;
       }
 
       try (Sink output = Okio.sink(outputFile)) {
-        // NULLSAFE_FIXME[Nullable Dereference]
         Okio.buffer(response.body().source()).readAll(output);
       }
 

From 8d61941c4d651a7547c1bc0134286b67c37d8e2d Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 07:06:40 -0700
Subject: [PATCH 09/13] Apply Nullsafe FIXMEs for
 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java

Summary:
Note this diff is only adding FIXMEs that will be removed in the next diff. This diff exists to make the next diff easily reviewable

Changelog: [Internal]

Differential Revision: D71126390
---
 .../react/devsupport/CxxInspectorPackagerConnection.java         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java
index ccb10de08c3d9b..754cd2a455f567 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java
@@ -39,6 +39,7 @@ private static native HybridData initHybrid(
 
   public native void closeQuietly();
 
+  // NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
   public native void sendEventToAllConnections(String event);
 
   /** Java wrapper around a C++ IWebSocketDelegate, allowing us to call the interface from Java. */

From 8c35ef43ec8d9c7390d7bde3ce70cc74fc238860 Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 07:06:40 -0700
Subject: [PATCH 10/13] Fix Nullsafe FIXMEs for
 CxxInspectorPackagerConnection.java and mark nullsafe

Summary:
Gone trough all the FIXMEs added in the previous diff by the nullsafe tool, marked the class as nullsafe and ensured no remaining violations.

Changelog: [Android][Fixed] Made CxxInspectorPackagerConnection.java nullsafe

Differential Revision: D71126386
---
 .../react/devsupport/CxxInspectorPackagerConnection.java   | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java
index 754cd2a455f567..dd2652115500bf 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.java
@@ -10,6 +10,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import androidx.annotation.Nullable;
+import com.facebook.infer.annotation.Nullsafe;
 import com.facebook.jni.HybridData;
 import com.facebook.proguard.annotations.DoNotStrip;
 import java.io.Closeable;
@@ -21,7 +22,8 @@
 import okhttp3.WebSocketListener;
 
 /** Java wrapper around a C++ InspectorPackagerConnection. */
-/* package */ class CxxInspectorPackagerConnection implements IInspectorPackagerConnection {
+/* package */ @Nullsafe(Nullsafe.Mode.LOCAL)
+class CxxInspectorPackagerConnection implements IInspectorPackagerConnection {
   static {
     DevSupportSoLoader.staticInit();
   }
@@ -39,8 +41,7 @@ private static native HybridData initHybrid(
 
   public native void closeQuietly();
 
-  // NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
-  public native void sendEventToAllConnections(String event);
+  public native void sendEventToAllConnections(@Nullable String event);
 
   /** Java wrapper around a C++ IWebSocketDelegate, allowing us to call the interface from Java. */
   @DoNotStrip

From bb45cd27d189b5f2f2a1d265e2f200f98507dc20 Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 07:06:40 -0700
Subject: [PATCH 11/13] Apply Nullsafe FIXMEs for
 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java

Summary:
Note this diff is only adding FIXMEs that will be removed in the next diff. This diff exists to make the next diff easily reviewable

Changelog: [Internal]

Differential Revision: D71126397
---
 .../com/facebook/react/devsupport/DebugOverlayController.java   | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java
index 421377f7adaf24..d5ba84e98e55a1 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java
@@ -57,6 +57,7 @@ private static boolean hasPermission(Context context, String permission) {
       PackageInfo info =
           context
               .getPackageManager()
+              // NULLSAFE_FIXME[Nullable Dereference]
               .getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
       if (info.requestedPermissions != null) {
         for (String p : info.requestedPermissions) {
@@ -73,6 +74,7 @@ private static boolean hasPermission(Context context, String permission) {
 
   private static boolean canHandleIntent(Context context, Intent intent) {
     PackageManager packageManager = context.getPackageManager();
+    // NULLSAFE_FIXME[Parameter Not Nullable]
     return intent.resolveActivity(packageManager) != null;
   }
 

From 94fddf5a526f7ab955d1c4f1c126de8e1b7b2a9f Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 07:06:40 -0700
Subject: [PATCH 12/13] Fix Nullsafe FIXMEs for DebugOverlayController.java and
 mark nullsafe

Summary:
Gone trough all the FIXMEs added in the previous diff by the nullsafe tool, marked the class as nullsafe and ensured no remaining violations.

Changelog: [Android][Fixed] Made DebugOverlayController.java nullsafe

Differential Revision: D71126394
---
 .../facebook/react/devsupport/DebugOverlayController.java  | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java
index d5ba84e98e55a1..9db6ef475fb916 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DebugOverlayController.java
@@ -18,6 +18,7 @@
 import android.widget.FrameLayout;
 import androidx.annotation.Nullable;
 import com.facebook.common.logging.FLog;
+import com.facebook.infer.annotation.Nullsafe;
 import com.facebook.react.bridge.ReactContext;
 import com.facebook.react.bridge.UiThreadUtil;
 import com.facebook.react.common.ReactConstants;
@@ -26,7 +27,8 @@
  * Helper class for controlling overlay view with FPS and JS FPS info that gets added directly
  * to @{link WindowManager} instance.
  */
-/* package */ class DebugOverlayController {
+/* package */ @Nullsafe(Nullsafe.Mode.LOCAL)
+class DebugOverlayController {
 
   public static void requestPermission(Context context) {
     // Get permission to show debug overlay in dev builds.
@@ -74,8 +76,7 @@ private static boolean hasPermission(Context context, String permission) {
 
   private static boolean canHandleIntent(Context context, Intent intent) {
     PackageManager packageManager = context.getPackageManager();
-    // NULLSAFE_FIXME[Parameter Not Nullable]
-    return intent.resolveActivity(packageManager) != null;
+    return packageManager != null && intent.resolveActivity(packageManager) != null;
   }
 
   private final WindowManager mWindowManager;

From d9bd70eb67ef843a052b71849d7249e041bc11ba Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Mon, 17 Mar 2025 07:12:35 -0700
Subject: [PATCH 13/13] Apply Nullsafe FIXMEs for
 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java
 (#50065)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50065

Note this diff is only adding FIXMEs that will be removed in the next diff. This diff exists to make the next diff easily reviewable

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D71126388
---
 .../com/facebook/react/devsupport/BundleDownloader.java     | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java
index 4fca36c35d30f2..3d593d0b739503 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java
@@ -141,8 +141,10 @@ public void onResponse(Call call, final Response response) throws IOException {
               // Make sure the result is a multipart response and parse the boundary.
               String contentType = response.header("content-type");
               Pattern regex = Pattern.compile("multipart/mixed;.*boundary=\"([^\"]+)\"");
+              // NULLSAFE_FIXME[Parameter Not Nullable]
               Matcher match = regex.matcher(contentType);
               if (match.find()) {
+                // NULLSAFE_FIXME[Parameter Not Nullable]
                 processMultipartResponse(url, r, match.group(1), outputFile, bundleInfo, callback);
               } else {
                 // In case the server doesn't support multipart/mixed responses, fallback to normal
@@ -152,8 +154,10 @@ public void onResponse(Call call, final Response response) throws IOException {
                       url,
                       r.code(),
                       r.headers(),
+                      // NULLSAFE_FIXME[Nullable Dereference]
                       r.body().source(),
                       outputFile,
+                      // NULLSAFE_FIXME[Parameter Not Nullable]
                       bundleInfo,
                       callback);
                 }
@@ -173,6 +177,7 @@ private void processMultipartResponse(
       throws IOException {
 
     MultipartStreamReader bodyReader =
+        // NULLSAFE_FIXME[Nullable Dereference]
         new MultipartStreamReader(response.body().source(), boundary);
     boolean completed =
         bodyReader.readAllParts(
@@ -192,6 +197,7 @@ public void onChunkComplete(
                     status = Integer.parseInt(headers.get("X-Http-Status"));
                   }
                   processBundleResult(
+                      // NULLSAFE_FIXME[Parameter Not Nullable]
                       url, status, Headers.of(headers), body, outputFile, bundleInfo, callback);
                 } else {
                   if (!headers.containsKey("Content-Type")