From 7f5b1a98e988602168efa68f149750bf920b4ad9 Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 8 Mar 2024 03:24:07 -0800 Subject: [PATCH] Use Guava's `toByteArray` & `fromByteArray` methods where possible Also remove intermediate object allocations in `Util.toByteArray(int...)`. `Util.toByteArray(InputStream)` is kept (but deprecated) because it's been part of the library for a while and might be in use by some apps. The others are much newer, so the chance of usages outside the library is very low, so we just remove them directly. PiperOrigin-RevId: 613878453 --- .../androidx/media3/common/util/Util.java | 57 +++++-------------- .../media3/container/MdtaMetadataEntry.java | 5 +- .../datasource/DefaultHttpDataSource.java | 3 +- .../datasource/cache/SimpleCacheTest.java | 4 +- .../datasource/okhttp/OkHttpDataSource.java | 6 +- .../exoplayer/drm/HttpMediaDrmCallback.java | 3 +- .../exoplayer/MetadataRetrieverTest.java | 3 +- .../media3/test/utils/CacheAsserts.java | 4 +- .../androidx/media3/test/utils/TestUtil.java | 10 ++-- 9 files changed, 33 insertions(+), 62 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index d2936003ee..12f9388982 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -92,8 +92,10 @@ import androidx.media3.common.Player.Commands; import androidx.media3.common.audio.AudioProcessor; import com.google.common.base.Ascii; import com.google.common.base.Charsets; +import com.google.common.io.ByteStreams; import com.google.common.math.DoubleMath; import com.google.common.math.LongMath; +import com.google.common.primitives.Ints; import com.google.common.primitives.UnsignedBytes; import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.Futures; @@ -203,47 +205,30 @@ public final class Util { private Util() {} /** - * Converts the entirety of an {@link InputStream} to a byte array. - * - * @param inputStream the {@link InputStream} to be read. The input stream is not closed by this - * method. - * @return a byte array containing all of the inputStream's bytes. - * @throws IOException if an error occurs reading from the stream. + * @deprecated Use Guava's {@link ByteStreams#toByteArray(InputStream)} instead. */ @UnstableApi + @Deprecated public static byte[] toByteArray(InputStream inputStream) throws IOException { - byte[] buffer = new byte[1024 * 4]; - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - int bytesRead; - while ((bytesRead = inputStream.read(buffer)) != -1) { - outputStream.write(buffer, 0, bytesRead); - } - return outputStream.toByteArray(); - } - - /** Converts an integer into an equivalent byte array. */ - @UnstableApi - public static byte[] toByteArray(int value) { - return new byte[] { - (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value - }; + return ByteStreams.toByteArray(inputStream); } /** * Converts an array of integers into an equivalent byte array. * *

Each integer is converted into 4 sequential bytes. + * + *

For a single integer, prefer Guava's {@link Ints#toByteArray(int)} implementation. */ @UnstableApi public static byte[] toByteArray(int... values) { byte[] array = new byte[values.length * 4]; int index = 0; for (int value : values) { - byte[] byteArray = toByteArray(value); - array[index++] = byteArray[0]; - array[index++] = byteArray[1]; - array[index++] = byteArray[2]; - array[index++] = byteArray[3]; + array[index++] = (byte) (value >> 24); + array[index++] = (byte) (value >> 16); + array[index++] = (byte) (value >> 8); + array[index++] = (byte) (value); } return array; } @@ -251,23 +236,7 @@ public final class Util { /** Converts a float into an equivalent byte array. */ @UnstableApi public static byte[] toByteArray(float value) { - return toByteArray(Float.floatToIntBits(value)); - } - - /** Converts a byte array into a float. */ - @UnstableApi - public static float toFloat(byte[] bytes) { - checkArgument(bytes.length == 4); - int intBits = - bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF); - return Float.intBitsToFloat(intBits); - } - - /** Converts a byte array into an integer. */ - @UnstableApi - public static int toInteger(byte[] bytes) { - checkArgument(bytes.length == 4); - return bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]; + return Ints.toByteArray(Float.floatToIntBits(value)); } /** @@ -1060,7 +1029,7 @@ public final class Util { @Nullable InputStream inputStream = null; try { inputStream = context.getAssets().open(assetPath); - return Util.fromUtf8Bytes(Util.toByteArray(inputStream)); + return Util.fromUtf8Bytes(ByteStreams.toByteArray(inputStream)); } finally { Util.closeQuietly(inputStream); } diff --git a/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java b/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java index 93c47fc7f6..40c223624b 100644 --- a/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java +++ b/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java @@ -21,6 +21,7 @@ import androidx.annotation.Nullable; import androidx.media3.common.Metadata; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; +import com.google.common.primitives.Ints; import java.util.Arrays; /** @@ -113,10 +114,10 @@ public final class MdtaMetadataEntry implements Metadata.Entry { formattedValue = Util.fromUtf8Bytes(value); break; case TYPE_INDICATOR_FLOAT32: - formattedValue = String.valueOf(Util.toFloat(value)); + formattedValue = String.valueOf(Float.intBitsToFloat(Ints.fromByteArray(value))); break; case TYPE_INDICATOR_INT32: - formattedValue = String.valueOf(Util.toInteger(value)); + formattedValue = String.valueOf(Ints.fromByteArray(value)); break; default: formattedValue = Util.toHexString(value); diff --git a/libraries/datasource/src/main/java/androidx/media3/datasource/DefaultHttpDataSource.java b/libraries/datasource/src/main/java/androidx/media3/datasource/DefaultHttpDataSource.java index 6a9a1d8af5..c43e6ddd25 100644 --- a/libraries/datasource/src/main/java/androidx/media3/datasource/DefaultHttpDataSource.java +++ b/libraries/datasource/src/main/java/androidx/media3/datasource/DefaultHttpDataSource.java @@ -33,6 +33,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.ForwardingMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; +import com.google.common.io.ByteStreams; import com.google.common.net.HttpHeaders; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.io.IOException; @@ -423,7 +424,7 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou byte[] errorResponseBody; try { errorResponseBody = - errorStream != null ? Util.toByteArray(errorStream) : Util.EMPTY_BYTE_ARRAY; + errorStream != null ? ByteStreams.toByteArray(errorStream) : Util.EMPTY_BYTE_ARRAY; } catch (IOException e) { errorResponseBody = Util.EMPTY_BYTE_ARRAY; } diff --git a/libraries/datasource/src/test/java/androidx/media3/datasource/cache/SimpleCacheTest.java b/libraries/datasource/src/test/java/androidx/media3/datasource/cache/SimpleCacheTest.java index 758921e2d3..38e1d441a5 100644 --- a/libraries/datasource/src/test/java/androidx/media3/datasource/cache/SimpleCacheTest.java +++ b/libraries/datasource/src/test/java/androidx/media3/datasource/cache/SimpleCacheTest.java @@ -16,7 +16,6 @@ package androidx.media3.datasource.cache; import static androidx.media3.common.C.LENGTH_UNSET; -import static androidx.media3.common.util.Util.toByteArray; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.doAnswer; @@ -28,6 +27,7 @@ import androidx.media3.datasource.cache.Cache.CacheException; import androidx.media3.test.utils.TestUtil; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.common.io.ByteStreams; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -646,7 +646,7 @@ public class SimpleCacheTest { assertThat(cacheSpan.isCached).isTrue(); byte[] expected = generateData(cacheSpan.key, (int) cacheSpan.position, (int) cacheSpan.length); try (FileInputStream inputStream = new FileInputStream(cacheSpan.file)) { - assertThat(toByteArray(inputStream)).isEqualTo(expected); + assertThat(ByteStreams.toByteArray(inputStream)).isEqualTo(expected); } } diff --git a/libraries/datasource_okhttp/src/main/java/androidx/media3/datasource/okhttp/OkHttpDataSource.java b/libraries/datasource_okhttp/src/main/java/androidx/media3/datasource/okhttp/OkHttpDataSource.java index e360989db8..c72796405d 100644 --- a/libraries/datasource_okhttp/src/main/java/androidx/media3/datasource/okhttp/OkHttpDataSource.java +++ b/libraries/datasource_okhttp/src/main/java/androidx/media3/datasource/okhttp/OkHttpDataSource.java @@ -32,12 +32,10 @@ import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSourceException; import androidx.media3.datasource.DataSpec; import androidx.media3.datasource.HttpDataSource; -import androidx.media3.datasource.HttpDataSource.HttpDataSourceException; -import androidx.media3.datasource.HttpDataSource.InvalidContentTypeException; -import androidx.media3.datasource.HttpDataSource.InvalidResponseCodeException; import androidx.media3.datasource.HttpUtil; import androidx.media3.datasource.TransferListener; import com.google.common.base.Predicate; +import com.google.common.io.ByteStreams; import com.google.common.net.HttpHeaders; import com.google.common.util.concurrent.SettableFuture; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -338,7 +336,7 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { byte[] errorResponseBody; try { - errorResponseBody = Util.toByteArray(Assertions.checkNotNull(responseByteStream)); + errorResponseBody = ByteStreams.toByteArray(Assertions.checkNotNull(responseByteStream)); } catch (IOException e) { errorResponseBody = Util.EMPTY_BYTE_ARRAY; } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/HttpMediaDrmCallback.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/HttpMediaDrmCallback.java index 95eb55e4d6..8973607d02 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/HttpMediaDrmCallback.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/HttpMediaDrmCallback.java @@ -30,6 +30,7 @@ import androidx.media3.datasource.StatsDataSource; import androidx.media3.exoplayer.drm.ExoMediaDrm.KeyRequest; import androidx.media3.exoplayer.drm.ExoMediaDrm.ProvisionRequest; import com.google.common.collect.ImmutableMap; +import com.google.common.io.ByteStreams; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -182,7 +183,7 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback { while (true) { DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec); try { - return Util.toByteArray(inputStream); + return ByteStreams.toByteArray(inputStream); } catch (InvalidResponseCodeException e) { @Nullable String redirectUrl = getRedirectUrl(e, manualRedirectCount); if (redirectUrl == null) { diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MetadataRetrieverTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MetadataRetrieverTest.java index 4654c30b45..a41c383e49 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MetadataRetrieverTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MetadataRetrieverTest.java @@ -40,6 +40,7 @@ import androidx.media3.test.utils.FakeClock; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.common.collect.ImmutableList; +import com.google.common.primitives.Ints; import com.google.common.util.concurrent.ListenableFuture; import java.util.ArrayList; import java.util.List; @@ -166,7 +167,7 @@ public class MetadataRetrieverTest { MdtaMetadataEntry expectedTemporalLayersCountMetdata = new MdtaMetadataEntry( /* key= */ "com.android.video.temporal_layers_count", - /* value= */ Util.toByteArray(4), + /* value= */ Ints.toByteArray(4), MdtaMetadataEntry.TYPE_INDICATOR_INT32); SmtaMetadataEntry expectedSmtaEntry = new SmtaMetadataEntry(/* captureFrameRate= */ 240, /* svcTemporalLayerCount= */ 4); diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/CacheAsserts.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/CacheAsserts.java index 3f20d466ed..cf2b246906 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/CacheAsserts.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/CacheAsserts.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertWithMessage; import android.net.Uri; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.UnstableApi; -import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSourceInputStream; import androidx.media3.datasource.DataSourceUtil; @@ -30,6 +29,7 @@ import androidx.media3.datasource.PlaceholderDataSource; import androidx.media3.datasource.cache.Cache; import androidx.media3.datasource.cache.CacheDataSource; import androidx.media3.test.utils.FakeDataSet.FakeData; +import com.google.common.io.ByteStreams; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.io.IOException; import java.util.ArrayList; @@ -158,7 +158,7 @@ public final class CacheAsserts { public static void assertReadData(DataSource dataSource, DataSpec dataSpec, byte[] expected) throws IOException { try (DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec)) { - byte[] bytes = Util.toByteArray(inputStream); + byte[] bytes = ByteStreams.toByteArray(inputStream); assertThat(bytes).isEqualTo(expected); } } diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java index 079438016e..57f4355537 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java @@ -36,7 +36,6 @@ import androidx.media3.common.MediaMetadata; import androidx.media3.common.StreamKey; import androidx.media3.common.Timeline; import androidx.media3.common.TrackGroup; -import androidx.media3.common.util.Assertions; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import androidx.media3.database.DatabaseProvider; @@ -53,7 +52,9 @@ import androidx.media3.extractor.PositionHolder; import androidx.media3.extractor.SeekMap; import androidx.media3.extractor.metadata.MetadataInputBuffer; import com.google.common.collect.ImmutableList; +import com.google.common.io.ByteStreams; import com.google.common.primitives.Bytes; +import com.google.common.primitives.UnsignedBytes; import com.google.common.truth.Correspondence; import java.io.File; import java.io.FileInputStream; @@ -140,8 +141,7 @@ public class TestUtil { public static byte[] createByteArray(int... bytes) { byte[] array = new byte[bytes.length]; for (int i = 0; i < array.length; i++) { - Assertions.checkState(0x00 <= bytes[i] && bytes[i] <= 0xFF); - array[i] = (byte) bytes[i]; + array[i] = UnsignedBytes.checkedCast(bytes[i]); } return array; } @@ -202,14 +202,14 @@ public class TestUtil { /** Returns the bytes of an asset file. */ public static byte[] getByteArray(Context context, String fileName) throws IOException { try (InputStream inputStream = getInputStream(context, fileName)) { - return Util.toByteArray(inputStream); + return ByteStreams.toByteArray(inputStream); } } /** Returns the bytes of a file using its file path. */ public static byte[] getByteArrayFromFilePath(String filePath) throws IOException { try (InputStream inputStream = new FileInputStream(filePath)) { - return Util.toByteArray(inputStream); + return ByteStreams.toByteArray(inputStream); } }