Skip to content

Commit

Permalink
Merge pull request #1954 from DataDog/xgouchet/RUM-3774/crash_drawabl…
Browse files Browse the repository at this point in the history
…e_utils

RUMM-3774 prevent crash in Canvas Wrapper
  • Loading branch information
xgouchet committed Mar 29, 2024
2 parents 2b9548a + 0b607b4 commit 2f83078
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ import com.datadog.android.api.InternalLogger
internal class CanvasWrapper(
private val logger: InternalLogger = InternalLogger.UNBOUND
) {

internal fun createCanvas(bitmap: Bitmap): Canvas? {
@Suppress("SwallowedException", "TooGenericExceptionCaught")
if (bitmap.isRecycled || !bitmap.isMutable) {
logger.log(
level = InternalLogger.Level.ERROR,
target = InternalLogger.Target.MAINTAINER,
{ INVALID_BITMAP }
)
return null
}

@Suppress("TooGenericExceptionCaught")
return try {
Canvas(bitmap)
} catch (e: IllegalStateException) {
Expand All @@ -38,6 +48,7 @@ internal class CanvasWrapper(
}

private companion object {
private const val INVALID_BITMAP = "Cannot create canvas: bitmap is either already recycled or immutable"
private const val FAILED_TO_CREATE_CANVAS = "Failed to create canvas"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2016-Present Datadog, Inc.
*/

package com.datadog.android.sessionreplay.internal.recorder.wrappers

import android.graphics.Bitmap
import com.datadog.android.api.InternalLogger
import com.datadog.android.sessionreplay.forge.ForgeConfigurator
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
import fr.xgouchet.elmyr.junit5.ForgeExtension
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.Extensions
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.junit.jupiter.MockitoSettings
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness

@Extensions(
ExtendWith(MockitoExtension::class),
ExtendWith(ForgeExtension::class)
)
@MockitoSettings(strictness = Strictness.LENIENT)
@ForgeConfiguration(ForgeConfigurator::class)
internal class CanvasWrapperTest {

lateinit var testedWrapper: CanvasWrapper

@Mock
lateinit var mockLogger: InternalLogger

@Mock
lateinit var mockBitmap: Bitmap

@BeforeEach
fun `set up`() {
testedWrapper = CanvasWrapper(mockLogger)
}

@Test
fun `M return null W createCanvas() {recycled bitmap}`() {
// Given
whenever(mockBitmap.isRecycled) doReturn true

// When
val canvas = testedWrapper.createCanvas(mockBitmap)

// Then
assertThat(canvas).isNull()
}

@Test
fun `M return null W createCanvas() {immutable bitmap}`() {
// Given
whenever(mockBitmap.isRecycled) doReturn false
whenever(mockBitmap.isMutable) doReturn false

// When
val canvas = testedWrapper.createCanvas(mockBitmap)

// Then
assertThat(canvas).isNull()
}
}

0 comments on commit 2f83078

Please sign in to comment.