Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix RecordingCanvas.nFinishRecording for Q and R #8690

Merged
merged 1 commit into from Dec 14, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,11 +1,16 @@
package org.robolectric.shadows;

import static android.os.Build.VERSION_CODES.Q;
import static android.os.Build.VERSION_CODES.R;
import static android.os.Build.VERSION_CODES.S;

import android.graphics.RecordingCanvas;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import org.robolectric.nativeruntime.DefaultNativeRuntimeLoader;
import org.robolectric.nativeruntime.RecordingCanvasNatives;
import org.robolectric.shadows.ShadowNativeRecordingCanvas.Picker;
Expand All @@ -14,15 +19,22 @@
@Implements(value = RecordingCanvas.class, minSdk = Q, shadowPicker = Picker.class)
public class ShadowNativeRecordingCanvas extends ShadowNativeBaseRecordingCanvas {

// Used for'nFinishRecording' for Android Q and R.
private static final Map<Long, Long> recordingCanvasToRenderNode =
Collections.synchronizedMap(new HashMap<>());

@Implementation
protected static long nCreateDisplayListCanvas(long node, int width, int height) {
DefaultNativeRuntimeLoader.injectAndLoad();
return RecordingCanvasNatives.nCreateDisplayListCanvas(node, width, height);
long result = RecordingCanvasNatives.nCreateDisplayListCanvas(node, width, height);
recordingCanvasToRenderNode.put(result, node);
return result;
}

@Implementation
protected static void nResetDisplayListCanvas(long canvas, long node, int width, int height) {
RecordingCanvasNatives.nResetDisplayListCanvas(canvas, node, width, height);
recordingCanvasToRenderNode.put(canvas, node);
}

@Implementation
Expand All @@ -45,6 +57,15 @@ protected static void nFinishRecording(long renderer, long renderNode) {
RecordingCanvasNatives.nFinishRecording(renderer, renderNode);
}

@Implementation(minSdk = Q, maxSdk = R)
protected static long nFinishRecording(long renderer) {
Long renderNode = recordingCanvasToRenderNode.get(renderer);
if (renderNode != null && renderNode != 0) {
RecordingCanvasNatives.nFinishRecording(renderer, renderNode);
}
return 0;
}

@Implementation
protected static void nDrawRenderNode(long renderer, long renderNode) {
RecordingCanvasNatives.nDrawRenderNode(renderer, renderNode);
Expand Down Expand Up @@ -103,6 +124,11 @@ protected static void nDrawWebViewFunctor(long canvas, int functor) {
RecordingCanvasNatives.nDrawWebViewFunctor(canvas, functor);
}

@Resetter
public static void reset() {
recordingCanvasToRenderNode.clear();
}

/** Shadow picker for {@link RecordingCanvas}. */
public static final class Picker extends GraphicsShadowPicker<Object> {
public Picker() {
Expand Down
Expand Up @@ -459,6 +459,14 @@ protected static long nGetUniqueId(long renderNode) {
return RenderNodeNatives.nGetUniqueId(renderNode);
}

@Implementation(minSdk = Q, maxSdk = R)
protected static void nSetDisplayList(long renderNode, long newData) {
// No-op in Q and R
// In S and above, the functionality of nSetDisplayList is a part of
// RecordingCanvas.finishRecording (which gets called just prior to this). So this method is a
// no-op.
}

/** Shadow picker for {@link RenderNode}. */
public static final class Picker extends GraphicsShadowPicker<Object> {
public Picker() {
Expand Down