Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

### Performance

- Use `RGB_565` instead of `ARGB_8888` for screenshot and replay capture bitmaps, halving per-frame memory usage ([#5821](https://github.com/getsentry/sentry-java/pull/5821))
- Remove an unused lock from `SentryPerformanceProvider`, which was allocated on every cold start in `ContentProvider.onCreate` without ever being acquired ([#5871](https://github.com/getsentry/sentry-java/pull/5871))
- Parse the app start profiling config with only the deserializer it needs instead of building a full `JsonSerializer` and `SentryOptions`, cutting 188 of 221 allocations on the main thread before `Application.onCreate` ([#5867](https://github.com/getsentry/sentry-java/pull/5867))
- Batch and coalesce scope-persistence disk writes to reduce startup cost ([#5791](https://github.com/getsentry/sentry-java/pull/5791))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ private boolean isMaskingEnabled() {
try (final MaskRenderer maskRenderer = new MaskRenderer()) {
// Make bitmap mutable if needed
if (!screenshot.isMutable()) {
mutableBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, true);
mutableBitmap = screenshot.copy(Bitmap.Config.RGB_565, true);
if (mutableBitmap == null) {
screenshot.recycle();
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import java.io.ByteArrayOutputStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -97,9 +97,8 @@ public class ScreenshotUtils {
}

try {
// ARGB_8888 -> This configuration is very flexible and offers the best quality
final Bitmap bitmap =
Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);

final @NotNull CountDownLatch latch = new CountDownLatch(1);

Comment thread
sentry[bot] marked this conversation as resolved.
Expand All @@ -110,21 +109,21 @@ public class ScreenshotUtils {
thread.start();

boolean success = false;
final AtomicInteger copyResultCode = new AtomicInteger(-1);
try {
final Handler handler = new Handler(thread.getLooper());
final AtomicBoolean copyResultSuccess = new AtomicBoolean(false);

PixelCopy.request(
window,
bitmap,
copyResult -> {
copyResultSuccess.set(copyResult == PixelCopy.SUCCESS);
copyResultCode.set(copyResult);
latch.countDown();
},
handler);

success =
latch.await(CAPTURE_TIMEOUT_MS, TimeUnit.MILLISECONDS) && copyResultSuccess.get();
final boolean completed = latch.await(CAPTURE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
success = completed && copyResultCode.get() == PixelCopy.SUCCESS;
} catch (Throwable e) {
// ignored
logger.log(SentryLevel.ERROR, "Taking screenshot using PixelCopy failed.", e);
Expand All @@ -133,6 +132,10 @@ public class ScreenshotUtils {
}

if (!success) {
logger.log(
SentryLevel.WARNING,
"PixelCopy failed for screenshot capture (result=%d).",
copyResultCode.get());
Comment thread
romtsn marked this conversation as resolved.
return null;
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ internal class CanvasStrategy(
Bitmap.createBitmap(
config.recordingWidth,
config.recordingHeight,
Bitmap.Config.ARGB_8888,
Bitmap.Config.RGB_565,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,15 @@ internal class PixelCopyStrategy(
private val executor = executorProvider.getExecutor()
private val mainLooperHandler = executorProvider.getMainLooperHandler()
private val screenshot =
Bitmap.createBitmap(config.recordingWidth, config.recordingHeight, Bitmap.Config.ARGB_8888)
Bitmap.createBitmap(
config.recordingWidth,
config.recordingHeight,
if (options.sessionReplay.isCaptureSurfaceViews) {
Bitmap.Config.ARGB_8888
} else {
Bitmap.Config.RGB_565
},
)
private val prescaledMatrix by
lazy(NONE) { Matrix().apply { preScale(config.scaleFactorX, config.scaleFactorY) } }
private val lastCaptureSuccessful = AtomicBoolean(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import kotlin.test.assertFalse
import kotlin.test.assertTrue
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
Expand Down Expand Up @@ -470,7 +471,9 @@ class PixelCopyStrategyTest {

assertFalse(fixture.contentChangedMarked.get())
assertTrue(strategy.lastCaptureSuccessful())
verify(fixture.callback).onScreenshotRecorded(any<Bitmap>())
val screenshot = argumentCaptor<Bitmap>()
verify(fixture.callback).onScreenshotRecorded(screenshot.capture())
assertEquals(Bitmap.Config.RGB_565, screenshot.firstValue.config)
}

@Test
Expand Down Expand Up @@ -502,7 +505,9 @@ class PixelCopyStrategyTest {
shadowOf(Looper.getMainLooper()).idle()

assertTrue(strategy.lastCaptureSuccessful())
verify(fixture.callback).onScreenshotRecorded(any<Bitmap>())
val screenshot = argumentCaptor<Bitmap>()
verify(fixture.callback).onScreenshotRecorded(screenshot.capture())
assertEquals(Bitmap.Config.ARGB_8888, screenshot.firstValue.config)
}

@Test
Expand Down
Loading