From 251882314de2ca63279185f38646f268e1a72beb 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/12] 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 a9d7d7c716e2951c84367197bd410cd1d5d0f7f7 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/12] 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 ad6f4aebe1a043b78159e2c4e910bf652b3dc353 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/12] 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 047c8d819a20aa4fe43b6417da054232575bad03 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/12] 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 1413972b7399d2aa198889b69b963f399ad81c6a 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/12] 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 62ba061510562fac474cb172c51c87c29016c421 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/12] 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 e84fdb11bdad265f104b4592e4ebd77a527f4e6e 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/12] 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 155e45578b5b73..8350285e76608f 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;
@@ -457,6 +458,7 @@ public String getSourceUrl(String mainModuleName) {
       }
 
       try (Sink output = Okio.sink(outputFile)) {
+        // NULLSAFE_FIXME[Nullable Dereference]
         Okio.buffer(response.body().source()).readAll(output);
       }
 

From eae2338ab48c46f9c20cfba9bf50bb854063288f 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/12] 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 8350285e76608f..5411029777aaa2 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;
       }
@@ -453,12 +457,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 2584f94359b7c7d28157202dcbc75b800dd4d328 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/12] 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 92302ff790eda7ba1fa1f00b30e3a4a7fafe2976 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/12] 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 3b9d1e5433a34bdaebcf77a93ba879b64da5e40b 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/12] 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 59fb0e9e10d6691f306f9e19466fc2e023bd34fc Mon Sep 17 00:00:00 2001
From: Gijs Weterings <gweterings@meta.com>
Date: Tue, 18 Mar 2025 04:26:34 -0700
Subject: [PATCH 12/12] 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

Reviewed By: mdvacca

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;