Fix BigDecimal#stripTrailingZeros for 0.0

Bug: b/301570464
Change-Id: I79e6cccb70040c2e7d3a40cf13a7b5c248e9252d
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 8e23208..82314cf 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
@@ -1088,6 +1088,16 @@
     }
 
     private void initializeAndroidQMethodProviders(DexItemFactory factory) {
+      // BigDecimal BigDecimal.stripTrailingZeros()
+      DexType bigDecimal = factory.createType("Ljava/math/BigDecimal;");
+      addProvider(
+          new StatifyingMethodWithForwardingGenerator(
+              factory.createMethod(
+                  bigDecimal, factory.createProto(bigDecimal), "stripTrailingZeros"),
+              BackportedMethods::BigDecimalMethods_stripTrailingZeros,
+              "stripTrailingZeros",
+              bigDecimal));
+
       // void android.drm.DrmManagerClient.close()
       addProvider(
           new InvokeRewriter(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index 7d65007..6c73cde 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -35,6 +35,7 @@
 import com.android.tools.r8.cf.code.CfReturn;
 import com.android.tools.r8.cf.code.CfReturnVoid;
 import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfStaticFieldRead;
 import com.android.tools.r8.cf.code.CfStore;
 import com.android.tools.r8.cf.code.CfThrow;
 import com.android.tools.r8.cf.code.CfTryCatch;
@@ -78,6 +79,8 @@
     factory.createSynthesizedType("Ljava/lang/reflect/Constructor;");
     factory.createSynthesizedType("Ljava/lang/reflect/InvocationTargetException;");
     factory.createSynthesizedType("Ljava/lang/reflect/Method;");
+    factory.createSynthesizedType("Ljava/math/BigDecimal;");
+    factory.createSynthesizedType("Ljava/math/BigInteger;");
     factory.createSynthesizedType("Ljava/util/AbstractMap$SimpleImmutableEntry;");
     factory.createSynthesizedType("Ljava/util/ArrayList;");
     factory.createSynthesizedType("Ljava/util/Arrays;");
@@ -425,6 +428,69 @@
         ImmutableList.of());
   }
 
+  public static CfCode BigDecimalMethods_stripTrailingZeros(
+      DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        4,
+        1,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/math/BigDecimal;"),
+                    factory.createProto(factory.intType),
+                    factory.createString("signum")),
+                false),
+            new CfIf(IfType.NE, ValueType.INT, label2),
+            label1,
+            new CfNew(factory.createType("Ljava/math/BigDecimal;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/math/BigInteger;"),
+                    factory.createType("Ljava/math/BigInteger;"),
+                    factory.createString("ZERO"))),
+            new CfConstNumber(0, ValueType.INT),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/math/BigDecimal;"),
+                    factory.createProto(
+                        factory.voidType,
+                        factory.createType("Ljava/math/BigInteger;"),
+                        factory.intType),
+                    factory.createString("<init>")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/math/BigDecimal;"))
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/math/BigDecimal;"),
+                    factory.createProto(factory.createType("Ljava/math/BigDecimal;")),
+                    factory.createString("stripTrailingZeros")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label3),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode BooleanMethods_compare(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BigDecimalBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BigDecimalBackportTest.java
new file mode 100644
index 0000000..edb29f1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/BigDecimalBackportTest.java
@@ -0,0 +1,39 @@
+// 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 com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.math.BigDecimal;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public final class BigDecimalBackportTest extends AbstractBackportTest {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+  }
+
+  public BigDecimalBackportTest(TestParameters parameters) {
+    super(parameters, BigDecimal.class, Main.class);
+    registerTarget(AndroidApiLevel.Q, 3);
+    ignoreInvokes("valueOf");
+    ignoreInvokes("toString");
+  }
+
+  static final class Main extends MiniAssert {
+    public static void main(String[] args) {
+      testStripTrailingZeros();
+    }
+
+    private static void testStripTrailingZeros() {
+      assertEquals("0", BigDecimal.valueOf(0.0).stripTrailingZeros().toString());
+      assertEquals("1", BigDecimal.valueOf(1.0).stripTrailingZeros().toString());
+      assertEquals("-1", BigDecimal.valueOf(-1.0).stripTrailingZeros().toString());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/BigDecimalMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/BigDecimalMethods.java
new file mode 100644
index 0000000..8faac64
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/BigDecimalMethods.java
@@ -0,0 +1,21 @@
+// 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 java.math.BigDecimal;
+import java.math.BigInteger;
+
+public final class BigDecimalMethods {
+
+  // Make BigDecimal#stripTrailingZeros consistent (b/301570464).
+  public static BigDecimal stripTrailingZeros(BigDecimal biggie) {
+    // If biggie is ZERO, then platform appears to be inconsistent so return our own value.
+    if (biggie.signum() == 0) {
+      return new BigDecimal(BigInteger.ZERO, 0);
+    }
+    // If biggie is not zero, then platform appears to consistent so forward to the platform method.
+    return biggie.stripTrailingZeros();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
index 3a7cb1e..d11c2f7 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
@@ -38,6 +38,7 @@
           AtomicReferenceArrayMethods.class,
           AtomicReferenceFieldUpdaterMethods.class,
           AtomicReferenceMethods.class,
+          BigDecimalMethods.class,
           BooleanMethods.class,
           ByteMethods.class,
           CharSequenceMethods.class,