Skip to content

Conversation

allenchen1154
Copy link
Contributor

@allenchen1154 allenchen1154 commented May 14, 2025

When using the RenderNode rendering strategy, the call to OffscreenLayer.finish() decrements the save count on the Canvas returned from OffscreenLayer.start(), so we need to know whether to skip the call to Canvas.restore() in ImageLayer, otherwise the Canvas will throw an exception.

Fixes #2609

When using the RenderNode rendering strategy, the call to `OffscreenLayer.finish()` decrements the save count on the `Canvas` returned from `OffscreenLayer.start()`, so we need to know whether to skip the call to `Canvas.restore()` in `ImageLayer`, otherwise the `Canvas` will thrown an exception.
@allenchen1154
Copy link
Contributor Author

Draft for now as I would like to add a repro test case.

Copy link

Snapshot Tests
API 23: Report Diff
API 31: Report Diff

*/
public boolean finishDecrementsCanvasSaveCount() {
// endRecording() will decrement the save count of the Canvas returned by beginRecording()
return currentStrategy == RenderStrategy.RENDER_NODE;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@geomaster I'm not sure why this happens, but I narrowed down the beginRecording()/endRecording() interaction as the root cause of the underflow error.

@allenchen1154
Copy link
Contributor Author

allenchen1154 commented May 19, 2025

For reference my repro code is as follows:

val composition by rememberLottieComposition(
    LottieCompositionSpec
        .RawRes(R.raw.feat_campaignlisting_guestsubmission__submit_request),
)
val progress by animateLottieCompositionAsState(composition = composition, isPlaying = true)

val bitmap = Bitmap.createScaledBitmap(
    BitmapFactory.decodeResource(LocalContext.current.resources, R.drawable.feat_campaignlisting_guestsubmission__img_1),
    324,
    238,
    false,
)

val dynamicProperties = rememberLottieDynamicProperties(
    rememberLottieDynamicProperty(LottieProperty.IMAGE, bitmap, "**", "Card.png"),
)

LottieAnimation(
    composition = composition,
    progress = { progress },
    dynamicProperties = dynamicProperties,
)

@allenchen1154 allenchen1154 marked this pull request as ready for review May 20, 2025 00:05
Copy link

Snapshot Tests
API 23: Report Diff
API 31: Report Diff


internal fun SnapshotTestCaseContext.getBitmapFromAssets(name: String): Bitmap {
return BitmapFactory.decodeStream(context.assets.open(name), null, BitmapFactory.Options())!!
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this utility function so it can be shared

@gpeal gpeal merged commit 1cbe8c1 into airbnb:master May 27, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CRASH: Fatal Exception: java.lang.IllegalStateException: Underflow in restore - more restores than saves
2 participants