Skip to content

Commit 9f28e7d

Browse files
tianyifSheenaChhabra
authored andcommitted
Improve AudioCapabilities with AudioManager API in Android 13
PiperOrigin-RevId: 604700601 (cherry picked from commit ccd603a)
1 parent bf8b874 commit 9f28e7d

File tree

3 files changed

+347
-53
lines changed

3 files changed

+347
-53
lines changed

‎libraries/common/src/main/java/androidx/media3/common/util/Util.java

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
import java.util.Locale;
123123
import java.util.MissingResourceException;
124124
import java.util.NoSuchElementException;
125+
import java.util.Objects;
125126
import java.util.TimeZone;
126127
import java.util.UUID;
127128
import java.util.concurrent.CancellationException;
@@ -505,7 +506,7 @@ public static boolean isRunningOnEmulator() {
505506

506507
/**
507508
* Tests two objects for {@link Object#equals(Object)} equality, handling the case where one or
508-
* both may be null.
509+
* both may be {@code null}.
509510
*
510511
* @param o1 The first object.
511512
* @param o2 The second object.
@@ -516,6 +517,64 @@ public static boolean areEqual(@Nullable Object o1, @Nullable Object o2) {
516517
return o1 == null ? o2 == null : o1.equals(o2);
517518
}
518519

520+
/**
521+
* Tests two {@link SparseArray} instances for content equality, handling the case where one or
522+
* both may be {@code null}.
523+
*
524+
* @see SparseArray#contentEquals(SparseArray)
525+
* @param sparseArray1 The first {@link SparseArray} instance.
526+
* @param sparseArray2 The second {@link SparseArray} instance.
527+
* @return True if the two {@link SparseArray} instances are equal in contents.
528+
*/
529+
@UnstableApi
530+
public static <T> boolean contentEquals(
531+
@Nullable SparseArray<T> sparseArray1, @Nullable SparseArray<T> sparseArray2) {
532+
if (sparseArray1 == null) {
533+
return sparseArray2 == null;
534+
} else if (sparseArray2 == null) {
535+
return false;
536+
}
537+
538+
if (Util.SDK_INT >= 31) {
539+
return sparseArray1.contentEquals(sparseArray2);
540+
}
541+
542+
int size = sparseArray1.size();
543+
if (size != sparseArray2.size()) {
544+
return false;
545+
}
546+
547+
for (int index = 0; index < size; index++) {
548+
int key = sparseArray1.keyAt(index);
549+
if (!Objects.equals(sparseArray1.valueAt(index), sparseArray2.get(key))) {
550+
return false;
551+
}
552+
}
553+
554+
return true;
555+
}
556+
557+
/**
558+
* Returns a hash code value for the contents of this {@link SparseArray}, combining the {@link
559+
* Objects#hashCode(Object)} result of all its keys and values.
560+
*
561+
* @see SparseArray#contentHashCode()
562+
* @param sparseArray The {@link SparseArray} instance.
563+
* @return The hash code.
564+
*/
565+
@UnstableApi
566+
public static <T> int contentHashCode(SparseArray<T> sparseArray) {
567+
if (Util.SDK_INT >= 31) {
568+
return sparseArray.contentHashCode();
569+
}
570+
int hash = 17;
571+
for (int index = 0; index < sparseArray.size(); index++) {
572+
hash = 31 * hash + sparseArray.keyAt(index);
573+
hash = 31 * hash + Objects.hashCode(sparseArray.valueAt(index));
574+
}
575+
return hash;
576+
}
577+
519578
/**
520579
* Tests whether an {@code items} array contains an object equal to {@code item}, according to
521580
* {@link Object#equals(Object)}.

‎libraries/common/src/test/java/androidx/media3/common/util/UtilTest.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import static androidx.media3.common.util.Util.binarySearchCeil;
1919
import static androidx.media3.common.util.Util.binarySearchFloor;
20+
import static androidx.media3.common.util.Util.contentEquals;
21+
import static androidx.media3.common.util.Util.contentHashCode;
2022
import static androidx.media3.common.util.Util.escapeFileName;
2123
import static androidx.media3.common.util.Util.getCodecsOfType;
2224
import static androidx.media3.common.util.Util.getStringForTime;
@@ -42,6 +44,7 @@
4244
import android.os.Handler;
4345
import android.os.HandlerThread;
4446
import android.os.Looper;
47+
import android.util.SparseArray;
4548
import android.util.SparseLongArray;
4649
import androidx.media3.common.C;
4750
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -1523,6 +1526,77 @@ public void getRoleFlagStrings() {
15231526
assertThat(roleFlags).containsExactly("describes-music", "easy-read");
15241527
}
15251528

1529+
@Test
1530+
public void contentEquals_twoNullSparseArrays_returnsTrue() {
1531+
assertThat(contentEquals(null, null)).isTrue();
1532+
}
1533+
1534+
@Test
1535+
public void contentEquals_oneNullSparseArrayAndOneNonNullSparseArray_returnsFalse() {
1536+
SparseArray<Integer> sparseArray = new SparseArray<>();
1537+
sparseArray.put(1, 2);
1538+
1539+
assertThat(contentEquals(sparseArray, null)).isFalse();
1540+
assertThat(contentEquals(null, sparseArray)).isFalse();
1541+
}
1542+
1543+
@Test
1544+
@Config(minSdk = 16) // Specifies the minimum SDK to enforce the test to run with all API levels.
1545+
public void contentEquals_sparseArraysWithEqualContent_returnsTrue() {
1546+
SparseArray<Integer> sparseArray1 = new SparseArray<>();
1547+
sparseArray1.put(1, 2);
1548+
sparseArray1.put(3, 4);
1549+
SparseArray<Integer> sparseArray2 = new SparseArray<>();
1550+
sparseArray2.put(3, 4);
1551+
sparseArray2.put(1, 2);
1552+
1553+
assertThat(contentEquals(sparseArray1, sparseArray2)).isTrue();
1554+
}
1555+
1556+
@Test
1557+
@Config(minSdk = 16) // Specifies the minimum SDK to enforce the test to run with all API levels.
1558+
public void contentEquals_sparseArraysWithDifferentContents_returnsFalse() {
1559+
SparseArray<Integer> sparseArray1 = new SparseArray<>();
1560+
sparseArray1.put(1, 2);
1561+
sparseArray1.put(3, 4);
1562+
SparseArray<Integer> sparseArray2 = new SparseArray<>();
1563+
sparseArray2.put(3, 4);
1564+
SparseArray<Integer> sparseArray3 = new SparseArray<>();
1565+
sparseArray3.put(1, 3);
1566+
sparseArray3.put(3, 4);
1567+
1568+
assertThat(contentEquals(sparseArray1, sparseArray2)).isFalse();
1569+
assertThat(contentEquals(sparseArray1, sparseArray3)).isFalse();
1570+
}
1571+
1572+
@Test
1573+
@Config(minSdk = 16) // Specifies the minimum SDK to enforce the test to run with all API levels.
1574+
public void contentHashCode_sparseArraysWithEqualContent_returnsEqualContentHashCode() {
1575+
SparseArray<Integer> sparseArray1 = new SparseArray<>();
1576+
sparseArray1.put(1, 2);
1577+
sparseArray1.put(3, 4);
1578+
SparseArray<Integer> sparseArray2 = new SparseArray<>();
1579+
sparseArray2.put(3, 4);
1580+
sparseArray2.put(1, 2);
1581+
1582+
assertThat(contentHashCode(sparseArray1)).isEqualTo(contentHashCode(sparseArray2));
1583+
}
1584+
1585+
@Test
1586+
@Config(minSdk = 16) // Specifies the minimum SDK to enforce the test to run with all API levels.
1587+
public void contentHashCode_sparseArraysWithDifferentContent_returnsDifferentContentHashCode() {
1588+
// In theory this is not guaranteed though, adding this test to ensure a sensible
1589+
// contentHashCode implementation.
1590+
SparseArray<Integer> sparseArray1 = new SparseArray<>();
1591+
sparseArray1.put(1, 2);
1592+
sparseArray1.put(3, 4);
1593+
SparseArray<Integer> sparseArray2 = new SparseArray<>();
1594+
sparseArray2.put(3, 2);
1595+
sparseArray2.put(1, 4);
1596+
1597+
assertThat(contentHashCode(sparseArray1)).isNotEqualTo(contentHashCode(sparseArray2));
1598+
}
1599+
15261600
private static void assertEscapeUnescapeFileName(String fileName, String escapedFileName) {
15271601
assertThat(escapeFileName(fileName)).isEqualTo(escapedFileName);
15281602
assertThat(unescapeFileName(escapedFileName)).isEqualTo(fileName);

0 commit comments

Comments
 (0)