Merge "Use reflection to operate on BackdropFrameRenderer" into main
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowBackdropFrameRendererTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowBackdropFrameRendererTest.java
index 83af4fa..9236f76 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowBackdropFrameRendererTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowBackdropFrameRendererTest.java
@@ -1,14 +1,16 @@
package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.S;
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+import static org.robolectric.util.ReflectionHelpers.ClassParameter.from;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.view.ThreadedRenderer;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.android.internal.policy.BackdropFrameRenderer;
import com.android.internal.policy.DecorView;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -19,30 +21,35 @@
/** Tests for {@link ShadowBackdropFrameRenderer} */
@RunWith(AndroidJUnit4.class)
-@Config(minSdk = S)
+@Config(minSdk = S, maxSdk = UPSIDE_DOWN_CAKE)
public class ShadowBackdropFrameRendererTest {
@Test
public void releaseRenderer_afterCreate_doesNotLeakThread() throws Exception {
Activity activity = Robolectric.setupActivity(Activity.class);
DecorView decorView = (DecorView) activity.getWindow().getDecorView();
+ Class<?> backdropFrameRendererClass =
+ Class.forName("com.android.internal.policy.BackdropFrameRenderer");
for (int i = 0; i < 100; i++) {
- BackdropFrameRenderer r =
- new BackdropFrameRenderer(
- decorView,
- ThreadedRenderer.create(RuntimeEnvironment.getApplication(), false, "renderer"),
- new Rect(0, 0, 0, 0),
- null,
- null,
- null,
- Color.BLUE,
- Color.BLUE,
- false,
- Insets.of(0, 0, 0, 0));
+ Object r =
+ ReflectionHelpers.callConstructor(
+ backdropFrameRendererClass,
+ from(DecorView.class, decorView),
+ from(
+ ThreadedRenderer.class,
+ ThreadedRenderer.create(RuntimeEnvironment.getApplication(), false, "renderer")),
+ from(Rect.class, new Rect(0, 0, 0, 0)),
+ from(Drawable.class, null),
+ from(Drawable.class, null),
+ from(Drawable.class, null),
+ from(Integer.TYPE, Color.BLUE),
+ from(Integer.TYPE, Color.BLUE),
+ from(Boolean.TYPE, false),
+ from(Insets.class, Insets.of(0, 0, 0, 0)));
ReflectionHelpers.callInstanceMethod(r, "releaseRenderer");
// Without the ShadowBackdropFrameRenderer.run override, the call to join would hang
// indefinitely.
- r.join();
+ ((Thread) r).join();
}
}
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBackdropFrameRenderer.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBackdropFrameRenderer.java
index e97c857..36f000e 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBackdropFrameRenderer.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBackdropFrameRenderer.java
@@ -1,12 +1,12 @@
package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.S;
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
import static org.robolectric.util.reflector.Reflector.reflector;
import android.os.Looper;
import android.view.Choreographer;
import android.view.ThreadedRenderer;
-import com.android.internal.policy.BackdropFrameRenderer;
import com.google.common.util.concurrent.Uninterruptibles;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -21,14 +21,18 @@
import org.robolectric.util.reflector.ForType;
/** Shadow for {@link BackdropFrameRenderer} */
-@Implements(value = BackdropFrameRenderer.class, minSdk = S, isInAndroidSdk = false)
+@Implements(
+ className = "com.android.internal.policy.BackdropFrameRenderer",
+ minSdk = S,
+ maxSdk = UPSIDE_DOWN_CAKE,
+ isInAndroidSdk = false)
public class ShadowBackdropFrameRenderer {
// Updated to the real value in the generated Shadow constructor
- @RealObject private final BackdropFrameRenderer realBackdropFrameRenderer = null;
+ @RealObject private final Object realBackdropFrameRenderer = null;
private Looper looper;
- private static final List<BackdropFrameRenderer> activeRenderers = new CopyOnWriteArrayList<>();
+ private static final List<Object> activeRenderers = new CopyOnWriteArrayList<>();
@Implementation
protected void run() {
@@ -60,19 +64,19 @@
// called from ShadowChoreographer to ensure choreographer is unpaused before this is executed
static void reset() {
- for (BackdropFrameRenderer renderer : activeRenderers) {
+ for (Object renderer : activeRenderers) {
reflector(BackdropFrameRendererReflector.class, renderer).releaseRenderer();
// Explicitly quit the looper if in legacy looper mode - otherwise it will hang forever
if (ConfigurationRegistry.get(LooperMode.Mode.class) == Mode.LEGACY) {
ShadowBackdropFrameRenderer shadowBackdropFrameRenderer = Shadow.extract(renderer);
shadowBackdropFrameRenderer.looper.quit();
}
- Uninterruptibles.joinUninterruptibly(renderer);
+ Uninterruptibles.joinUninterruptibly((Thread) renderer);
activeRenderers.remove(renderer);
}
}
- @ForType(BackdropFrameRenderer.class)
+ @ForType(className = "com.android.internal.policy.BackdropFrameRenderer")
interface BackdropFrameRendererReflector {
void releaseRenderer();