diff options
3 files changed, 67 insertions, 7 deletions
diff --git a/ojluni/src/main/java/java/util/PriorityQueue.java b/ojluni/src/main/java/java/util/PriorityQueue.java index 70c99bff9d0..264b1a8983f 100644 --- a/ojluni/src/main/java/java/util/PriorityQueue.java +++ b/ojluni/src/main/java/java/util/PriorityQueue.java @@ -25,6 +25,13 @@ package java.util; +import android.compat.Compatibility; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; + +import dalvik.annotation.compat.VersionCodes; +import dalvik.system.VMRuntime; + import java.util.function.Consumer; import java.util.function.Predicate; import jdk.internal.misc.SharedSecrets; @@ -327,7 +334,18 @@ public class PriorityQueue<E> extends AbstractQueue<E> int i = size; if (i >= queue.length) grow(i + 1); - siftUp(i, e); + if (i == 0) { + // Android-changed: Keep old behavior on Android 13 or below. http://b/289878283 + boolean usePreAndroidUBehavior = VMRuntime.getSdkVersion() < VersionCodes.UPSIDE_DOWN_CAKE + || !Compatibility.isChangeEnabled(PRIORITY_QUEUE_OFFER_NON_COMPARABLE_ONE_ELEMENT); + if (usePreAndroidUBehavior) { + queue[0] = e; + } else { + siftUp(i, e); + } + } else { + siftUp(i, e); + } size = i + 1; return true; } @@ -970,4 +988,18 @@ public class PriorityQueue<E> extends AbstractQueue<E> if (expectedModCount != modCount) throw new ConcurrentModificationException(); } + + // Android-added: Backward-compatible flag for offer() API. + /** + * Since Android 14, {@link PriorityQueue#offer(E)} requires all elements to be comparable if + * there was no comparator. Previously, the first element being added did not need to be + * comparable. + * + * This flag is enabled for apps targeting Android 14+. + * + * @hide + */ + @ChangeId + @EnabledSince(targetSdkVersion = VersionCodes.UPSIDE_DOWN_CAKE) + public static final long PRIORITY_QUEUE_OFFER_NON_COMPARABLE_ONE_ELEMENT = 289878283L; } diff --git a/ojluni/src/test/java/util/PriorityQueue/AddNonComparable.java b/ojluni/src/test/java/util/PriorityQueue/AddNonComparable.java index 3adf7f3255e..1b22ac0f74e 100644 --- a/ojluni/src/test/java/util/PriorityQueue/AddNonComparable.java +++ b/ojluni/src/test/java/util/PriorityQueue/AddNonComparable.java @@ -46,6 +46,11 @@ import java.util.function.Supplier; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import android.compat.Compatibility; + +import dalvik.annotation.compat.VersionCodes; +import dalvik.system.VMRuntime; + public class AddNonComparable { static <E> void test(Queue<E> queue, Supplier<E> supplier, @@ -58,11 +63,23 @@ public class AddNonComparable { @Test public void queues() { - test(new PriorityQueue<>(), NonComparable::new, - (q, e) -> { - assertEquals(q.size(), 0); - assertTrue(e instanceof ClassCastException); - }); + // Android-added: test old behavior in < U. + boolean testPreAndroidUBehavior = VMRuntime.getSdkVersion() < VersionCodes.UPSIDE_DOWN_CAKE + || !Compatibility.isChangeEnabled(PriorityQueue.PRIORITY_QUEUE_OFFER_NON_COMPARABLE_ONE_ELEMENT); + + if (testPreAndroidUBehavior) { + test(new PriorityQueue<>(), NonComparable::new, + (q, e) -> { + assertEquals(q.size(), 1); + assertTrue(e == null); + }); + } else { + test(new PriorityQueue<>(), NonComparable::new, + (q, e) -> { + assertEquals(q.size(), 0); + assertTrue(e instanceof ClassCastException); + }); + } test(new PriorityQueue<>(), AComparable::new, (q, e) -> { assertEquals(q.size(), 1); diff --git a/ojluni/src/test/java/util/concurrent/tck/PriorityQueueTest.java b/ojluni/src/test/java/util/concurrent/tck/PriorityQueueTest.java index 072abac2188..b7f2e9fc23c 100644 --- a/ojluni/src/test/java/util/concurrent/tck/PriorityQueueTest.java +++ b/ojluni/src/test/java/util/concurrent/tck/PriorityQueueTest.java @@ -45,6 +45,11 @@ import java.util.Queue; import junit.framework.Test; import junit.framework.TestSuite; +import android.compat.Compatibility; + +import dalvik.annotation.compat.VersionCodes; +import dalvik.system.VMRuntime; + public class PriorityQueueTest extends JSR166TestCase { public static void main(String[] args) { main(suite(), args); @@ -226,10 +231,16 @@ public class PriorityQueueTest extends JSR166TestCase { */ public void testOfferNonComparable() { PriorityQueue q = new PriorityQueue(1); + // Android-added: test old behavior in < U. + boolean preAndroidUBehavior = VMRuntime.getSdkVersion() < VersionCodes.UPSIDE_DOWN_CAKE + || !Compatibility.isChangeEnabled(PriorityQueue.PRIORITY_QUEUE_OFFER_NON_COMPARABLE_ONE_ELEMENT); try { q.offer(new Object()); - shouldThrow(); + if (!preAndroidUBehavior) { + shouldThrow(); + } } catch (ClassCastException success) { + assertFalse(preAndroidUBehavior); assertTrue(q.isEmpty()); assertEquals(0, q.size()); assertNull(q.poll()); |