Skip to content

Commit 3924768

Browse files
huntiemeta-codesync[bot]
authored andcommitted
Fix bitmap reuse race condition in FrameTimingsObserver (#55745)
Summary: Pull Request resolved: #55745 The shared `bitmapBuffer` could be overwritten by a new `PixelCopy` request on the main thread while a previous frame's encoding coroutine was still reading from it. Each frame now gets its own bitmap, recycled after encoding. NOTE: This will come at a slight perf cost (allocating extra new bitmaps in memory), for the tradeoff of correctness. Changelog: [Internal] Reviewed By: rubennorte Differential Revision: D94368260 fbshipit-source-id: f89f6f4cdd34278ed91d4a673af343999550d919
1 parent d552f2a commit 3924768

File tree

1 file changed

+3
-12
lines changed

1 file changed

+3
-12
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ internal class FrameTimingsObserver(
3131

3232
private val mainHandler = Handler(Looper.getMainLooper())
3333
private var frameCounter: Int = 0
34-
private var bitmapBuffer: Bitmap? = null
3534
private var isStarted: Boolean = false
3635

3736
@Volatile private var currentWindow: Window? = null
@@ -61,9 +60,6 @@ internal class FrameTimingsObserver(
6160

6261
currentWindow?.removeOnFrameMetricsAvailableListener(frameMetricsListener)
6362
mainHandler.removeCallbacksAndMessages(null)
64-
65-
bitmapBuffer?.recycle()
66-
bitmapBuffer = null
6763
}
6864

6965
fun setCurrentWindow(window: Window?) {
@@ -124,14 +120,7 @@ internal class FrameTimingsObserver(
124120
val decorView = window.decorView
125121
val width = decorView.width
126122
val height = decorView.height
127-
128-
// Reuse bitmap if dimensions haven't changed
129-
val bitmap =
130-
bitmapBuffer?.takeIf { it.width == width && it.height == height }
131-
?: run {
132-
bitmapBuffer?.recycle()
133-
Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).also { bitmapBuffer = it }
134-
}
123+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
135124

136125
PixelCopy.request(
137126
window,
@@ -142,6 +131,7 @@ internal class FrameTimingsObserver(
142131
callback(encodeScreenshot(window, bitmap, width, height))
143132
}
144133
} else {
134+
bitmap.recycle()
145135
callback(null)
146136
}
147137
},
@@ -169,6 +159,7 @@ internal class FrameTimingsObserver(
169159
null
170160
} finally {
171161
scaledBitmap?.recycle()
162+
bitmap.recycle()
172163
}
173164
}
174165

0 commit comments

Comments
 (0)