Backport android.media.MediaDrm.close()
Method close was added in API level 28. Rewrite to release which has
been present since API level 18.
Fixes: b/264392414
Change-Id: Ifdb1397767986603fefd734110312b61301f7a82
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 823bee3..a07a676 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -92,6 +92,7 @@
"Landroid/content/ContentProviderClient;";
public static final String androidDrmDrmManagerClientDescriptorString =
"Landroid/drm/DrmManagerClient;";
+ public static final String androidMediaMediaDrmDescriptorString = "Landroid/media/MediaDrm;";
/** Set of types that may be synthesized during compilation. */
private final Set<DexType> possibleCompilerSynthesizedTypes = Sets.newIdentityHashSet();
@@ -622,6 +623,8 @@
createStaticallyKnownType(androidContentContentProviderClientDescriptorString);
public final DexType androidDrmDrmManagerClientType =
createStaticallyKnownType(androidDrmDrmManagerClientDescriptorString);
+ public final DexType androidMediaMediaDrmType =
+ createStaticallyKnownType(androidMediaMediaDrmDescriptorString);
public final StringBuildingMethods stringBuilderMethods =
new StringBuildingMethods(stringBuilderType);
@@ -681,6 +684,8 @@
androidContentContentProviderClientMembers = new AndroidContentContentProviderClientMembers();
public final AndroidDrmDrmManagerClientMembers androidDrmDrmManagerClientMembers =
new AndroidDrmDrmManagerClientMembers();
+ public final AndroidMediaMediaDrmMembers androidMediaMediaDrmMembers =
+ new AndroidMediaMediaDrmMembers();
// java.**
public final JavaIoFileMembers javaIoFileMembers = new JavaIoFileMembers();
@@ -1187,6 +1192,14 @@
createMethod(androidDrmDrmManagerClientType, createProto(voidType), "close");
}
+ // android.media.MediaDrm
+ public class AndroidMediaMediaDrmMembers extends LibraryMembers {
+ public final DexMethod release =
+ createMethod(androidMediaMediaDrmType, createProto(voidType), "release");
+ public final DexMethod close =
+ createMethod(androidMediaMediaDrmType, createProto(voidType), "close");
+ }
+
public class BooleanMembers extends BoxedPrimitiveMembers {
public final DexField FALSE = createField(boxedBooleanType, boxedBooleanType, "FALSE");
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 7ea2a53..892dc5a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -49,6 +49,7 @@
import com.android.tools.r8.ir.desugar.backports.DrmManagerClientMethodRewrites;
import com.android.tools.r8.ir.desugar.backports.FloatMethodRewrites;
import com.android.tools.r8.ir.desugar.backports.LongMethodRewrites;
+import com.android.tools.r8.ir.desugar.backports.MediaDrmMethodRewrites;
import com.android.tools.r8.ir.desugar.backports.NumericMethodRewrites;
import com.android.tools.r8.ir.desugar.backports.ObjectsMethodRewrites;
import com.android.tools.r8.ir.desugar.backports.OptionalMethodRewrites;
@@ -238,6 +239,9 @@
initializeAndroidOThreadLocalMethodProviderWithSupplier(factory);
}
}
+ if (options.getMinApiLevel().isLessThan(AndroidApiLevel.P)) {
+ initializeAndroidPMethodProviders(factory);
+ }
if (options.getMinApiLevel().isLessThan(AndroidApiLevel.R)) {
if (options.testing.alwaysBackportListSetMapMethods
|| typeIsPresentWithoutBackportsFrom(factory.setType, AndroidApiLevel.R)) {
@@ -1070,6 +1074,13 @@
method, BackportedMethods::StringMethods_joinIterable, "joinIterable"));
}
+ private void initializeAndroidPMethodProviders(DexItemFactory factory) {
+ // void android.drm.DrmManagerClient.close()
+ addProvider(
+ new InvokeRewriter(
+ factory.androidMediaMediaDrmMembers.close, MediaDrmMethodRewrites.rewriteClose()));
+ }
+
private void initializeAndroidRObjectsMethodProviderWithSupplier(DexItemFactory factory) {
// Objects
DexType type = factory.objectsType;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/MediaDrmMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/MediaDrmMethodRewrites.java
new file mode 100644
index 0000000..57b0fe2
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/MediaDrmMethodRewrites.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.desugar.backports;
+
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import org.objectweb.asm.Opcodes;
+
+public final class MediaDrmMethodRewrites {
+
+ private MediaDrmMethodRewrites() {}
+
+ public static MethodInvokeRewriter rewriteClose() {
+ // Rewrite android/media/MediaDrm#close to android/media/MediaDrm#release
+ return (invoke, factory) ->
+ new CfInvoke(Opcodes.INVOKEVIRTUAL, factory.androidMediaMediaDrmMembers.release, false);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/MediaDrmBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/MediaDrmBackportTest.java
new file mode 100644
index 0000000..500308b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/MediaDrmBackportTest.java
@@ -0,0 +1,102 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.backports;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class MediaDrmBackportTest extends AbstractBackportTest {
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimesAndAllApiLevels().build();
+ }
+
+ public MediaDrmBackportTest(TestParameters parameters) throws IOException {
+ super(
+ parameters,
+ MediaDrmBackportTest.getMediaDrm(parameters),
+ ImmutableList.of(
+ MediaDrmBackportTest.getTestRunner(), MediaDrmBackportTest.getMediaDrm(parameters)));
+
+ // The constructor is used by the test and release has been available since API 18 and is the
+ // method close is rewritten to.
+ ignoreInvokes("<init>");
+ ignoreInvokes("release");
+
+ // android.media.MediaDrm.close added in API 28.
+ registerTarget(AndroidApiLevel.P, 1);
+ }
+
+ private static byte[] getMediaDrm(TestParameters parameters) throws IOException {
+ if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.P)) {
+ assertTrue(parameters.getRuntime().asDex().getVm().isNewerThanOrEqual(DexVm.ART_8_1_0_HOST));
+ return transformer(MediaDrmApiLevel28.class)
+ .setClassDescriptor(DexItemFactory.androidMediaMediaDrmDescriptorString)
+ .transform();
+ } else {
+ return transformer(MediaDrm.class)
+ .setClassDescriptor(DexItemFactory.androidMediaMediaDrmDescriptorString)
+ .transform();
+ }
+ }
+
+ private static byte[] getTestRunner() throws IOException {
+ return transformer(TestRunner.class)
+ .replaceClassDescriptorInMethodInstructions(
+ descriptor(MediaDrm.class), DexItemFactory.androidMediaMediaDrmDescriptorString)
+ .transform();
+ }
+
+ public static class MediaDrm {
+ public boolean wasClosed = false;
+
+ public void close() {
+ TestRunner.doFail("close should not be called");
+ }
+
+ public void release() {
+ wasClosed = true;
+ }
+ }
+
+ public static class MediaDrmApiLevel28 {
+ public boolean wasClosed = false;
+
+ public void close() {
+ wasClosed = true;
+ }
+
+ public void release() {
+ TestRunner.doFail("release should not be called");
+ }
+ }
+
+ public static class TestRunner extends MiniAssert {
+
+ public static void main(String[] args) {
+ MediaDrm mediaDrm = new MediaDrm();
+ MiniAssert.assertFalse(mediaDrm.wasClosed);
+ mediaDrm.close();
+ MiniAssert.assertTrue(mediaDrm.wasClosed);
+ }
+
+ // Forwards to MiniAssert to avoid having to make it public.
+ public static void doFail(String message) {
+ MiniAssert.fail(message);
+ }
+ }
+}