Skip to content

Commit b85eb89

Browse files
romtsnclaude
andcommitted
fix(screenshot): Recycle bitmaps on all early-return paths to prevent memory leaks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2e8662b commit b85eb89

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

sentry-android-core/src/main/java/io/sentry/android/core/ScreenshotEventProcessor.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,15 @@ private boolean isMaskingEnabled() {
126126
if (isMaskingEnabled()) {
127127
final @Nullable ViewHierarchyNode rootNode = captureViewHierarchy(activity);
128128
if (rootNode == null) {
129-
// Don't return unmasked screenshot when masking is configured
129+
screenshot.recycle();
130130
return event;
131131
}
132-
screenshot = applyMasking(screenshot, rootNode);
133-
if (screenshot == null) {
134-
// Don't return unmasked screenshot when masking is configured
132+
final @Nullable Bitmap masked = applyMasking(screenshot, rootNode);
133+
if (masked == null) {
134+
// applyMasking already recycles its bitmaps on failure
135135
return event;
136136
}
137+
screenshot = masked;
137138
}
138139

139140
final Bitmap finalScreenshot = screenshot;
@@ -210,6 +211,7 @@ private boolean isMaskingEnabled() {
210211
if (!screenshot.isMutable()) {
211212
mutableBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, true);
212213
if (mutableBitmap == null) {
214+
screenshot.recycle();
213215
return null;
214216
}
215217
createdCopy = true;
@@ -225,11 +227,14 @@ private boolean isMaskingEnabled() {
225227
return mutableBitmap;
226228
} catch (Throwable e) {
227229
options.getLogger().log(SentryLevel.ERROR, "Failed to mask screenshot", e);
228-
// Recycle the copy if we created one, to avoid memory leak
229-
if (createdCopy && !mutableBitmap.isRecycled()) {
230-
mutableBitmap.recycle();
230+
if (createdCopy) {
231+
if (!mutableBitmap.isRecycled()) {
232+
mutableBitmap.recycle();
233+
}
234+
}
235+
if (!screenshot.isRecycled()) {
236+
screenshot.recycle();
231237
}
232-
// Don't return unmasked screenshot when masking is configured
233238
return null;
234239
}
235240
}

0 commit comments

Comments
 (0)