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();