diff --git a/libraries/common/src/main/java/androidx/media3/common/Format.java b/libraries/common/src/main/java/androidx/media3/common/Format.java index ad2b579743..7c7ffafaeb 100644 --- a/libraries/common/src/main/java/androidx/media3/common/Format.java +++ b/libraries/common/src/main/java/androidx/media3/common/Format.java @@ -20,7 +20,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import android.os.Bundle; import androidx.annotation.IntDef; import androidx.annotation.Nullable; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import com.google.common.base.Joiner; @@ -1450,9 +1450,11 @@ public final class Format implements Bundleable { /** Object that can restore {@code Format} from a {@link Bundle}. */ @UnstableApi public static final Creator CREATOR = Format::fromBundle; - private static Format fromBundle(Bundle bundle) { + /** Restores a {@code Format} from a {@link Bundle}. */ + @UnstableApi + public static Format fromBundle(Bundle bundle) { Builder builder = new Builder(); - BundleableUtil.ensureClassLoader(bundle); + BundleCollectionUtil.ensureClassLoader(bundle); builder .setId(defaultIfNull(bundle.getString(FIELD_ID), DEFAULT.id)) .setLabel(defaultIfNull(bundle.getString(FIELD_LABEL), DEFAULT.label)) diff --git a/libraries/common/src/main/java/androidx/media3/common/MediaItem.java b/libraries/common/src/main/java/androidx/media3/common/MediaItem.java index 926dde3a42..9880bcec64 100644 --- a/libraries/common/src/main/java/androidx/media3/common/MediaItem.java +++ b/libraries/common/src/main/java/androidx/media3/common/MediaItem.java @@ -24,7 +24,7 @@ import android.os.Bundle; import androidx.annotation.IntRange; import androidx.annotation.Nullable; import androidx.media3.common.util.Assertions; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import com.google.common.collect.ImmutableList; @@ -929,15 +929,16 @@ public final class MediaItem implements Bundleable { UUID scheme = UUID.fromString(checkNotNull(bundle.getString(FIELD_SCHEME))); @Nullable Uri licenseUri = bundle.getParcelable(FIELD_LICENSE_URI); Bundle licenseMapAsBundle = - BundleableUtil.getBundleWithDefault(bundle, FIELD_LICENSE_REQUEST_HEADERS, Bundle.EMPTY); + BundleCollectionUtil.getBundleWithDefault( + bundle, FIELD_LICENSE_REQUEST_HEADERS, Bundle.EMPTY); ImmutableMap licenseRequestHeaders = - BundleableUtil.bundleToStringImmutableMap(licenseMapAsBundle); + BundleCollectionUtil.bundleToStringImmutableMap(licenseMapAsBundle); boolean multiSession = bundle.getBoolean(FIELD_MULTI_SESSION, false); boolean playClearContentWithoutKey = bundle.getBoolean(FIELD_PLAY_CLEAR_CONTENT_WITHOUT_KEY, false); boolean forceDefaultLicenseUri = bundle.getBoolean(FIELD_FORCE_DEFAULT_LICENSE_URI, false); ArrayList<@C.TrackType Integer> forcedSessionTrackTypesArray = - BundleableUtil.getIntegerArrayListWithDefault( + BundleCollectionUtil.getIntegerArrayListWithDefault( bundle, FIELD_FORCED_SESSION_TRACK_TYPES, new ArrayList<>()); ImmutableList<@C.TrackType Integer> forcedSessionTrackTypes = ImmutableList.copyOf(forcedSessionTrackTypesArray); @@ -965,7 +966,8 @@ public final class MediaItem implements Bundleable { } if (!licenseRequestHeaders.isEmpty()) { bundle.putBundle( - FIELD_LICENSE_REQUEST_HEADERS, BundleableUtil.stringMapToBundle(licenseRequestHeaders)); + FIELD_LICENSE_REQUEST_HEADERS, + BundleCollectionUtil.stringMapToBundle(licenseRequestHeaders)); } if (multiSession) { bundle.putBoolean(FIELD_MULTI_SESSION, multiSession); @@ -1246,14 +1248,17 @@ public final class MediaItem implements Bundleable { } if (!streamKeys.isEmpty()) { bundle.putParcelableArrayList( - FIELD_STREAM_KEYS, BundleableUtil.toBundleArrayList(streamKeys)); + FIELD_STREAM_KEYS, + BundleCollectionUtil.toBundleArrayList(streamKeys, StreamKey::toBundle)); } if (customCacheKey != null) { bundle.putString(FIELD_CUSTOM_CACHE_KEY, customCacheKey); } if (!subtitleConfigurations.isEmpty()) { bundle.putParcelableArrayList( - FIELD_SUBTITLE_CONFIGURATION, BundleableUtil.toBundleArrayList(subtitleConfigurations)); + FIELD_SUBTITLE_CONFIGURATION, + BundleCollectionUtil.toBundleArrayList( + subtitleConfigurations, SubtitleConfiguration::toBundle)); } if (imageDurationMs != C.TIME_UNSET) { bundle.putLong(FIELD_IMAGE_DURATION_MS, imageDurationMs); @@ -1277,13 +1282,14 @@ public final class MediaItem implements Bundleable { List streamKeys = streamKeysBundles == null ? ImmutableList.of() - : BundleableUtil.fromBundleList(StreamKey::fromBundle, streamKeysBundles); + : BundleCollectionUtil.fromBundleList(StreamKey::fromBundle, streamKeysBundles); @Nullable List subtitleBundles = bundle.getParcelableArrayList(FIELD_SUBTITLE_CONFIGURATION); ImmutableList subtitleConfiguration = subtitleBundles == null ? ImmutableList.of() - : BundleableUtil.fromBundleList(SubtitleConfiguration.CREATOR, subtitleBundles); + : BundleCollectionUtil.fromBundleList( + SubtitleConfiguration::fromBundle, subtitleBundles); long imageDurationMs = bundle.getLong(FIELD_IMAGE_DURATION_MS, C.TIME_UNSET); return new LocalConfiguration( @@ -2337,14 +2343,20 @@ public final class MediaItem implements Bundleable { } /** - * An object that can restore {@link MediaItem} from a {@link Bundle}. + * An object that can restore {@code MediaItem} from a {@link Bundle}. * *

The {@link #localConfiguration} of a restored instance will always be {@code null}. */ @UnstableApi public static final Creator CREATOR = MediaItem::fromBundle; + /** + * Restores a {@code MediaItem} from a {@link Bundle}. + * + *

The {@link #localConfiguration} of a restored instance will always be {@code null}. + */ + @UnstableApi @SuppressWarnings("deprecation") // Unbundling to ClippingProperties while it still exists. - private static MediaItem fromBundle(Bundle bundle) { + public static MediaItem fromBundle(Bundle bundle) { String mediaId = checkNotNull(bundle.getString(FIELD_MEDIA_ID, DEFAULT_MEDIA_ID)); @Nullable Bundle liveConfigurationBundle = bundle.getBundle(FIELD_LIVE_CONFIGURATION); LiveConfiguration liveConfiguration; diff --git a/libraries/common/src/main/java/androidx/media3/common/PlaybackException.java b/libraries/common/src/main/java/androidx/media3/common/PlaybackException.java index 44ff185d4e..ca2facab59 100644 --- a/libraries/common/src/main/java/androidx/media3/common/PlaybackException.java +++ b/libraries/common/src/main/java/androidx/media3/common/PlaybackException.java @@ -455,7 +455,7 @@ public class PlaybackException extends Exception implements Bundleable { /** * Defines a minimum field ID value for subclasses to use when implementing {@link #toBundle()} - * and {@link Bundleable.Creator}. + * and delegating to {@link #PlaybackException(Bundle)}. * *

Subclasses should obtain their {@link Bundle Bundle's} field keys by applying a non-negative * offset on this constant and passing the result to {@link Util#intToStringMaxRadix(int)}. diff --git a/libraries/common/src/main/java/androidx/media3/common/Timeline.java b/libraries/common/src/main/java/androidx/media3/common/Timeline.java index 4b338ee44b..2bd7d09bc5 100644 --- a/libraries/common/src/main/java/androidx/media3/common/Timeline.java +++ b/libraries/common/src/main/java/androidx/media3/common/Timeline.java @@ -28,14 +28,17 @@ import android.os.SystemClock; import android.util.Pair; import androidx.annotation.Nullable; import androidx.media3.common.util.Assertions; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.BundleUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; +import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.InlineMe; import java.util.ArrayList; import java.util.List; +import org.checkerframework.checker.nullness.qual.NonNull; // TODO: b/288080357 - Replace developer.android.com fully-qualified SVG URLs below with relative // URLs once we stop publishing exoplayer2 javadoc. @@ -1479,9 +1482,9 @@ public abstract class Timeline implements Bundleable { private static Timeline fromBundle(Bundle bundle) { ImmutableList windows = - fromBundleListRetriever(Window.CREATOR, BundleUtil.getBinder(bundle, FIELD_WINDOWS)); + fromBundleListRetriever(Window::fromBundle, BundleUtil.getBinder(bundle, FIELD_WINDOWS)); ImmutableList periods = - fromBundleListRetriever(Period.CREATOR, BundleUtil.getBinder(bundle, FIELD_PERIODS)); + fromBundleListRetriever(Period::fromBundle, BundleUtil.getBinder(bundle, FIELD_PERIODS)); @Nullable int[] shuffledWindowIndices = bundle.getIntArray(FIELD_SHUFFLED_WINDOW_INDICES); return new RemotableTimeline( windows, @@ -1491,17 +1494,12 @@ public abstract class Timeline implements Bundleable { : shuffledWindowIndices); } - private static ImmutableList fromBundleListRetriever( - Creator creator, @Nullable IBinder binder) { + private static ImmutableList fromBundleListRetriever( + Function fromBundleFunc, @Nullable IBinder binder) { if (binder == null) { return ImmutableList.of(); } - ImmutableList.Builder builder = new ImmutableList.Builder<>(); - List bundleList = BundleListRetriever.getList(binder); - for (int i = 0; i < bundleList.size(); i++) { - builder.add(creator.fromBundle(bundleList.get(i))); - } - return builder.build(); + return BundleCollectionUtil.fromBundleList(fromBundleFunc, BundleListRetriever.getList(binder)); } private static int[] generateUnshuffledIndices(int n) { diff --git a/libraries/common/src/main/java/androidx/media3/common/TrackGroup.java b/libraries/common/src/main/java/androidx/media3/common/TrackGroup.java index 6a19c28ea6..beea4a3519 100644 --- a/libraries/common/src/main/java/androidx/media3/common/TrackGroup.java +++ b/libraries/common/src/main/java/androidx/media3/common/TrackGroup.java @@ -20,7 +20,7 @@ import static androidx.media3.common.util.Assertions.checkArgument; import android.os.Bundle; import androidx.annotation.CheckResult; import androidx.annotation.Nullable; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.Log; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; @@ -179,17 +179,19 @@ public final class TrackGroup implements Bundleable { } /** Object that can restore {@code TrackGroup} from a {@link Bundle}. */ + @UnstableApi public static final Creator CREATOR = TrackGroup::fromBundle; + + /** Restores a {@code TrackGroup} from a {@link Bundle}. */ @UnstableApi - public static final Creator CREATOR = - bundle -> { - @Nullable List formatBundles = bundle.getParcelableArrayList(FIELD_FORMATS); - List formats = - formatBundles == null - ? ImmutableList.of() - : BundleableUtil.fromBundleList(Format.CREATOR, formatBundles); - String id = bundle.getString(FIELD_ID, /* defaultValue= */ ""); - return new TrackGroup(id, formats.toArray(new Format[0])); - }; + public static TrackGroup fromBundle(Bundle bundle) { + @Nullable List formatBundles = bundle.getParcelableArrayList(FIELD_FORMATS); + List formats = + formatBundles == null + ? ImmutableList.of() + : BundleCollectionUtil.fromBundleList(Format::fromBundle, formatBundles); + String id = bundle.getString(FIELD_ID, /* defaultValue= */ ""); + return new TrackGroup(id, formats.toArray(new Format[0])); + } private void verifyCorrectness() { // TrackGroups should only contain tracks with exactly the same content (but in different diff --git a/libraries/common/src/main/java/androidx/media3/common/TrackSelectionOverride.java b/libraries/common/src/main/java/androidx/media3/common/TrackSelectionOverride.java index f7b08bacb0..7667697662 100644 --- a/libraries/common/src/main/java/androidx/media3/common/TrackSelectionOverride.java +++ b/libraries/common/src/main/java/androidx/media3/common/TrackSelectionOverride.java @@ -116,11 +116,14 @@ public final class TrackSelectionOverride implements Bundleable { /** Object that can restore {@code TrackSelectionOverride} from a {@link Bundle}. */ @UnstableApi - public static final Creator CREATOR = - bundle -> { - Bundle trackGroupBundle = checkNotNull(bundle.getBundle(FIELD_TRACK_GROUP)); - TrackGroup mediaTrackGroup = TrackGroup.CREATOR.fromBundle(trackGroupBundle); - int[] tracks = checkNotNull(bundle.getIntArray(FIELD_TRACKS)); - return new TrackSelectionOverride(mediaTrackGroup, Ints.asList(tracks)); - }; + public static final Creator CREATOR = TrackSelectionOverride::fromBundle; + + /** Restores a {@code TrackSelectionOverride} from a {@link Bundle}. */ + @UnstableApi + public static TrackSelectionOverride fromBundle(Bundle bundle) { + Bundle trackGroupBundle = checkNotNull(bundle.getBundle(FIELD_TRACK_GROUP)); + TrackGroup mediaTrackGroup = TrackGroup.fromBundle(trackGroupBundle); + int[] tracks = checkNotNull(bundle.getIntArray(FIELD_TRACKS)); + return new TrackSelectionOverride(mediaTrackGroup, Ints.asList(tracks)); + } } diff --git a/libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java b/libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java index f7e5711d07..89e6acf057 100644 --- a/libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java +++ b/libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java @@ -16,7 +16,7 @@ package androidx.media3.common; import static androidx.media3.common.util.Assertions.checkNotNull; -import static androidx.media3.common.util.BundleableUtil.toBundleArrayList; +import static androidx.media3.common.util.BundleCollectionUtil.toBundleArrayList; import static com.google.common.base.MoreObjects.firstNonNull; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -29,7 +29,7 @@ import android.view.accessibility.CaptioningManager; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import com.google.common.collect.ImmutableList; @@ -245,7 +245,8 @@ public class TrackSelectionParameters implements Bundleable { List overrideList = overrideBundleList == null ? ImmutableList.of() - : BundleableUtil.fromBundleList(TrackSelectionOverride.CREATOR, overrideBundleList); + : BundleCollectionUtil.fromBundleList( + TrackSelectionOverride::fromBundle, overrideBundleList); overrides = new HashMap<>(); for (int i = 0; i < overrideList.size(); i++) { TrackSelectionOverride override = overrideList.get(i); @@ -1424,7 +1425,7 @@ public class TrackSelectionParameters implements Bundleable { /** * Defines a minimum field ID value for subclasses to use when implementing {@link #toBundle()} - * and {@link Bundleable.Creator}. + * and delegating to {@link Builder#Builder(Bundle)}. * *

Subclasses should obtain keys for their {@link Bundle} representation by applying a * non-negative offset on this constant and passing the result to {@link @@ -1477,7 +1478,9 @@ public class TrackSelectionParameters implements Bundleable { // General bundle.putBoolean(FIELD_FORCE_LOWEST_BITRATE, forceLowestBitrate); bundle.putBoolean(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE, forceHighestSupportedBitrate); - bundle.putParcelableArrayList(FIELD_SELECTION_OVERRIDES, toBundleArrayList(overrides.values())); + bundle.putParcelableArrayList( + FIELD_SELECTION_OVERRIDES, + toBundleArrayList(overrides.values(), TrackSelectionOverride::toBundle)); bundle.putIntArray(FIELD_DISABLED_TRACK_TYPE, Ints.toArray(disabledTrackTypes)); return bundle; diff --git a/libraries/common/src/main/java/androidx/media3/common/Tracks.java b/libraries/common/src/main/java/androidx/media3/common/Tracks.java index 86a73170df..00175f3213 100644 --- a/libraries/common/src/main/java/androidx/media3/common/Tracks.java +++ b/libraries/common/src/main/java/androidx/media3/common/Tracks.java @@ -17,11 +17,11 @@ package androidx.media3.common; import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkNotNull; -import static androidx.media3.common.util.BundleableUtil.toBundleArrayList; +import static androidx.media3.common.util.BundleCollectionUtil.toBundleArrayList; import android.os.Bundle; import androidx.annotation.Nullable; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import com.google.common.base.MoreObjects; @@ -245,21 +245,23 @@ public final class Tracks implements Bundleable { } /** Object that can restore a group of tracks from a {@link Bundle}. */ + @UnstableApi public static final Creator CREATOR = Group::fromBundle; + + /** Restores a group of tracks from a {@link Bundle}. */ @UnstableApi - public static final Creator CREATOR = - bundle -> { - // Can't create a Tracks.Group without a TrackGroup - TrackGroup trackGroup = - TrackGroup.CREATOR.fromBundle(checkNotNull(bundle.getBundle(FIELD_TRACK_GROUP))); - final @C.FormatSupport int[] trackSupport = - MoreObjects.firstNonNull( - bundle.getIntArray(FIELD_TRACK_SUPPORT), new int[trackGroup.length]); - boolean[] selected = - MoreObjects.firstNonNull( - bundle.getBooleanArray(FIELD_TRACK_SELECTED), new boolean[trackGroup.length]); - boolean adaptiveSupported = bundle.getBoolean(FIELD_ADAPTIVE_SUPPORTED, false); - return new Group(trackGroup, adaptiveSupported, trackSupport, selected); - }; + public static Group fromBundle(Bundle bundle) { + // Can't create a Tracks.Group without a TrackGroup + TrackGroup trackGroup = + TrackGroup.fromBundle(checkNotNull(bundle.getBundle(FIELD_TRACK_GROUP))); + final @C.FormatSupport int[] trackSupport = + MoreObjects.firstNonNull( + bundle.getIntArray(FIELD_TRACK_SUPPORT), new int[trackGroup.length]); + boolean[] selected = + MoreObjects.firstNonNull( + bundle.getBooleanArray(FIELD_TRACK_SELECTED), new boolean[trackGroup.length]); + boolean adaptiveSupported = bundle.getBoolean(FIELD_ADAPTIVE_SUPPORTED, false); + return new Group(trackGroup, adaptiveSupported, trackSupport, selected); + } } /** Empty tracks. */ @@ -383,7 +385,7 @@ public final class Tracks implements Bundleable { @Override public Bundle toBundle() { Bundle bundle = new Bundle(); - bundle.putParcelableArrayList(FIELD_TRACK_GROUPS, toBundleArrayList(groups)); + bundle.putParcelableArrayList(FIELD_TRACK_GROUPS, toBundleArrayList(groups, Group::toBundle)); return bundle; } @@ -395,7 +397,7 @@ public final class Tracks implements Bundleable { List groups = groupBundles == null ? ImmutableList.of() - : BundleableUtil.fromBundleList(Group.CREATOR, groupBundles); + : BundleCollectionUtil.fromBundleList(Group::fromBundle, groupBundles); return new Tracks(groups); }; } diff --git a/libraries/common/src/main/java/androidx/media3/common/text/Cue.java b/libraries/common/src/main/java/androidx/media3/common/text/Cue.java index d5d4b0148f..a8155c43fe 100644 --- a/libraries/common/src/main/java/androidx/media3/common/text/Cue.java +++ b/libraries/common/src/main/java/androidx/media3/common/text/Cue.java @@ -869,7 +869,9 @@ public final class Cue implements Bundleable { @UnstableApi public static final Creator CREATOR = Cue::fromBundle; - private static final Cue fromBundle(Bundle bundle) { + /** Restores a cue from a {@link Bundle}. */ + @UnstableApi + public static Cue fromBundle(Bundle bundle) { Builder builder = new Builder(); @Nullable CharSequence text = bundle.getCharSequence(FIELD_TEXT); if (text != null) { diff --git a/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java b/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java index c8aa409d73..ecafd16f9f 100644 --- a/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java +++ b/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java @@ -20,7 +20,7 @@ import android.os.Bundle; import androidx.annotation.Nullable; import androidx.media3.common.Bundleable; import androidx.media3.common.Timeline; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import com.google.common.collect.ImmutableList; @@ -69,7 +69,8 @@ public final class CueGroup implements Bundleable { public Bundle toBundle() { Bundle bundle = new Bundle(); bundle.putParcelableArrayList( - FIELD_CUES, BundleableUtil.toBundleArrayList(filterOutBitmapCues(cues))); + FIELD_CUES, + BundleCollectionUtil.toBundleArrayList(filterOutBitmapCues(cues), Cue::toBundle)); bundle.putLong(FIELD_PRESENTATION_TIME_US, presentationTimeUs); return bundle; } @@ -81,7 +82,7 @@ public final class CueGroup implements Bundleable { List cues = cueBundles == null ? ImmutableList.of() - : BundleableUtil.fromBundleList(Cue.CREATOR, cueBundles); + : BundleCollectionUtil.fromBundleList(Cue::fromBundle, cueBundles); long presentationTimeUs = bundle.getLong(FIELD_PRESENTATION_TIME_US); return new CueGroup(cues, presentationTimeUs); } diff --git a/libraries/common/src/main/java/androidx/media3/common/util/BundleableUtil.java b/libraries/common/src/main/java/androidx/media3/common/util/BundleCollectionUtil.java similarity index 51% rename from libraries/common/src/main/java/androidx/media3/common/util/BundleableUtil.java rename to libraries/common/src/main/java/androidx/media3/common/util/BundleCollectionUtil.java index 7049542c1b..11dee1c837 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/BundleableUtil.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/BundleCollectionUtil.java @@ -21,7 +21,6 @@ import static androidx.media3.common.util.Util.castNonNull; import android.os.Bundle; import android.util.SparseArray; import androidx.annotation.Nullable; -import androidx.media3.common.Bundleable; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -30,81 +29,97 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.checkerframework.checker.nullness.qual.NonNull; -/** Utilities for {@link Bundleable}. */ +/** Utilities for converting collections to and from {@link Bundle} instances. */ @UnstableApi -public final class BundleableUtil { - - /** Converts a list of {@link Bundleable} to a list {@link Bundle}. */ - public static ImmutableList toBundleList(List bundleableList) { - return toBundleList(bundleableList, Bundleable::toBundle); - } +public final class BundleCollectionUtil { /** - * Converts a list of {@link Bundleable} to a list {@link Bundle} + * Bundles a list of objects to a list of {@link Bundle} instances. * - * @param bundleableList list of Bundleable items to be converted - * @param customToBundleFunc function that specifies how to bundle up each {@link Bundleable} + * @param list List of items to be bundled. + * @param toBundleFunc Function that specifies how to bundle each item. + * @return The {@link ImmutableList} of bundled items. */ - public static ImmutableList toBundleList( - List bundleableList, Function customToBundleFunc) { + public static ImmutableList toBundleList( + List list, Function toBundleFunc) { ImmutableList.Builder builder = ImmutableList.builder(); - for (int i = 0; i < bundleableList.size(); i++) { - T bundleable = bundleableList.get(i); - builder.add(customToBundleFunc.apply(bundleable)); + for (int i = 0; i < list.size(); i++) { + T item = list.get(i); + builder.add(toBundleFunc.apply(item)); } return builder.build(); } - /** Converts a list of {@link Bundle} to a list of {@link Bundleable}. */ - public static ImmutableList fromBundleList( - Bundleable.Creator creator, List bundleList) { + /** + * Unbundles a list of {@link Bundle} instances to a list of objects. + * + * @param fromBundleFunc Function that specified how to unbundle each item. + * @param bundleList List of {@link Bundle} instances to be unbundled. + * @return The {@link ImmutableList} of unbundled items. + */ + public static ImmutableList fromBundleList( + Function fromBundleFunc, List bundleList) { ImmutableList.Builder builder = ImmutableList.builder(); for (int i = 0; i < bundleList.size(); i++) { Bundle bundle = checkNotNull(bundleList.get(i)); // Fail fast during parsing. - T bundleable = creator.fromBundle(bundle); - builder.add(bundleable); + T item = fromBundleFunc.apply(bundle); + builder.add(item); } return builder.build(); } /** - * Converts a collection of {@link Bundleable} to an {@link ArrayList} of {@link Bundle} so that - * the returned list can be put to {@link Bundle} using {@link Bundle#putParcelableArrayList} + * Bundles a collection of objects to an {@link ArrayList} of {@link Bundle} instances so that the + * returned list can be put to {@link Bundle} using {@link Bundle#putParcelableArrayList} * conveniently. + * + * @param items Collection of items to be bundled. + * @param toBundleFunc Function that specifies how to bundle each item. + * @return The {@link ArrayList} of bundled items. */ - public static ArrayList toBundleArrayList( - Collection bundleables) { - ArrayList arrayList = new ArrayList<>(bundleables.size()); - for (T element : bundleables) { - arrayList.add(element.toBundle()); + @SuppressWarnings("NonApiType") // Intentionally using ArrayList for putParcelableArrayList. + public static ArrayList toBundleArrayList( + Collection items, Function toBundleFunc) { + ArrayList arrayList = new ArrayList<>(items.size()); + for (T item : items) { + arrayList.add(toBundleFunc.apply(item)); } return arrayList; } /** - * Converts a {@link SparseArray} of {@link Bundle} to a {@link SparseArray} of {@link - * Bundleable}. + * Unbundles a {@link SparseArray} of {@link Bundle} instances to a {@link SparseArray} of + * objects. + * + * @param fromBundleFunc Function that specified how to unbundle each item. + * @param bundleSparseArray {@link SparseArray} of {@link Bundle} instances to be unbundled. + * @return The {@link SparseArray} of unbundled items. */ - public static SparseArray fromBundleSparseArray( - Bundleable.Creator creator, SparseArray bundleSparseArray) { + public static SparseArray fromBundleSparseArray( + Function fromBundleFunc, SparseArray bundleSparseArray) { SparseArray result = new SparseArray<>(bundleSparseArray.size()); for (int i = 0; i < bundleSparseArray.size(); i++) { - result.put(bundleSparseArray.keyAt(i), creator.fromBundle(bundleSparseArray.valueAt(i))); + result.put(bundleSparseArray.keyAt(i), fromBundleFunc.apply(bundleSparseArray.valueAt(i))); } return result; } /** - * Converts a {@link SparseArray} of {@link Bundleable} to an {@link SparseArray} of {@link - * Bundle} so that the returned {@link SparseArray} can be put to {@link Bundle} using {@link + * Bundles a {@link SparseArray} of objects to a {@link SparseArray} of {@link Bundle} instances + * so that the returned {@link SparseArray} can be put to {@link Bundle} using {@link * Bundle#putSparseParcelableArray} conveniently. + * + * @param items Collection of items to be bundled. + * @param toBundleFunc Function that specifies how to bundle each item. + * @return The {@link SparseArray} of bundled items. */ - public static SparseArray toBundleSparseArray( - SparseArray bundleableSparseArray) { - SparseArray sparseArray = new SparseArray<>(bundleableSparseArray.size()); - for (int i = 0; i < bundleableSparseArray.size(); i++) { - sparseArray.put(bundleableSparseArray.keyAt(i), bundleableSparseArray.valueAt(i).toBundle()); + public static SparseArray toBundleSparseArray( + SparseArray items, Function toBundleFunc) { + SparseArray sparseArray = new SparseArray<>(items.size()); + for (int i = 0; i < items.size(); i++) { + sparseArray.put(items.keyAt(i), toBundleFunc.apply(items.valueAt(i))); } return sparseArray; } @@ -154,13 +169,13 @@ public final class BundleableUtil { * Sets the application class loader to the given {@link Bundle} if no class loader is present. * *

This assumes that all classes unparceled from {@code bundle} are sharing the class loader of - * {@code BundleableUtils}. + * {@code BundleCollectionUtil}. */ public static void ensureClassLoader(@Nullable Bundle bundle) { if (bundle != null) { - bundle.setClassLoader(castNonNull(BundleableUtil.class.getClassLoader())); + bundle.setClassLoader(castNonNull(BundleCollectionUtil.class.getClassLoader())); } } - private BundleableUtil() {} + private BundleCollectionUtil() {} } diff --git a/libraries/common/src/test/java/androidx/media3/common/TrackGroupTest.java b/libraries/common/src/test/java/androidx/media3/common/TrackGroupTest.java index bd4075a60a..e59a857540 100644 --- a/libraries/common/src/test/java/androidx/media3/common/TrackGroupTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/TrackGroupTest.java @@ -34,7 +34,7 @@ public final class TrackGroupTest { TrackGroup trackGroupToBundle = new TrackGroup(id, format1, format2); - TrackGroup trackGroupFromBundle = TrackGroup.CREATOR.fromBundle(trackGroupToBundle.toBundle()); + TrackGroup trackGroupFromBundle = TrackGroup.fromBundle(trackGroupToBundle.toBundle()); assertThat(trackGroupFromBundle).isEqualTo(trackGroupToBundle); } diff --git a/libraries/common/src/test/java/androidx/media3/common/util/BundleableUtilTest.java b/libraries/common/src/test/java/androidx/media3/common/util/BundleCollectionUtilTest.java similarity index 78% rename from libraries/common/src/test/java/androidx/media3/common/util/BundleableUtilTest.java rename to libraries/common/src/test/java/androidx/media3/common/util/BundleCollectionUtilTest.java index 239485e3c1..93d8eeed34 100644 --- a/libraries/common/src/test/java/androidx/media3/common/util/BundleableUtilTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/util/BundleCollectionUtilTest.java @@ -25,9 +25,9 @@ import java.util.Map; import org.junit.Test; import org.junit.runner.RunWith; -/** Unit tests for {@link BundleableUtil}. */ +/** Unit tests for {@link BundleCollectionUtil}. */ @RunWith(AndroidJUnit4.class) -public class BundleableUtilTest { +public class BundleCollectionUtilTest { @Test public void testStringMapToBundle() { @@ -37,8 +37,8 @@ public class BundleableUtilTest { originalMap.put("thirdKey", "repeatedValue"); originalMap.put("", "valueOfEmptyKey"); - Bundle mapAsBundle = BundleableUtil.stringMapToBundle(originalMap); - Map restoredMap = BundleableUtil.bundleToStringHashMap(mapAsBundle); + Bundle mapAsBundle = BundleCollectionUtil.stringMapToBundle(originalMap); + Map restoredMap = BundleCollectionUtil.bundleToStringHashMap(mapAsBundle); assertThat(restoredMap).isEqualTo(originalMap); } @@ -57,11 +57,11 @@ public class BundleableUtilTest { outerBundle.putBundle("2", null); Bundle restoredInnerBundle = - BundleableUtil.getBundleWithDefault(outerBundle, "0", defaultBundle); + BundleCollectionUtil.getBundleWithDefault(outerBundle, "0", defaultBundle); Bundle restoredEmptyBundle = - BundleableUtil.getBundleWithDefault(outerBundle, "1", defaultBundle); + BundleCollectionUtil.getBundleWithDefault(outerBundle, "1", defaultBundle); Bundle restoredNullBundle = - BundleableUtil.getBundleWithDefault(outerBundle, "2", defaultBundle); + BundleCollectionUtil.getBundleWithDefault(outerBundle, "2", defaultBundle); assertThat(restoredInnerBundle).isEqualTo(fullInnerBundle); assertThat(restoredEmptyBundle).isEqualTo(Bundle.EMPTY); @@ -83,11 +83,11 @@ public class BundleableUtilTest { bundle.putIntegerArrayList("2", null); ArrayList restoredIntegerArray = - BundleableUtil.getIntegerArrayListWithDefault(bundle, "0", defaultIntegerArray); + BundleCollectionUtil.getIntegerArrayListWithDefault(bundle, "0", defaultIntegerArray); ArrayList restoredEmptyIntegerArray = - BundleableUtil.getIntegerArrayListWithDefault(bundle, "1", defaultIntegerArray); + BundleCollectionUtil.getIntegerArrayListWithDefault(bundle, "1", defaultIntegerArray); ArrayList restoredNullIntegerArray = - BundleableUtil.getIntegerArrayListWithDefault(bundle, "2", defaultIntegerArray); + BundleCollectionUtil.getIntegerArrayListWithDefault(bundle, "2", defaultIntegerArray); assertThat(restoredIntegerArray).isEqualTo(normalArray); assertThat(restoredEmptyIntegerArray).isEqualTo(emptyArray); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/TrackGroupArray.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/TrackGroupArray.java index befc158d25..3256caeab0 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/TrackGroupArray.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/TrackGroupArray.java @@ -20,7 +20,7 @@ import androidx.annotation.Nullable; import androidx.media3.common.Bundleable; import androidx.media3.common.C; import androidx.media3.common.TrackGroup; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.Log; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; @@ -118,22 +118,24 @@ public final class TrackGroupArray implements Bundleable { public Bundle toBundle() { Bundle bundle = new Bundle(); bundle.putParcelableArrayList( - FIELD_TRACK_GROUPS, BundleableUtil.toBundleArrayList(trackGroups)); + FIELD_TRACK_GROUPS, + BundleCollectionUtil.toBundleArrayList(trackGroups, TrackGroup::toBundle)); return bundle; } /** Object that can restores a TrackGroupArray from a {@link Bundle}. */ - public static final Creator CREATOR = - bundle -> { - @Nullable - List trackGroupBundles = bundle.getParcelableArrayList(FIELD_TRACK_GROUPS); - if (trackGroupBundles == null) { - return new TrackGroupArray(); - } - return new TrackGroupArray( - BundleableUtil.fromBundleList(TrackGroup.CREATOR, trackGroupBundles) - .toArray(new TrackGroup[0])); - }; + public static final Creator CREATOR = TrackGroupArray::fromBundle; + + /** Restores a {@code TrackGroupArray} from a {@link Bundle}. */ + public static TrackGroupArray fromBundle(Bundle bundle) { + @Nullable List trackGroupBundles = bundle.getParcelableArrayList(FIELD_TRACK_GROUPS); + if (trackGroupBundles == null) { + return new TrackGroupArray(); + } + return new TrackGroupArray( + BundleCollectionUtil.fromBundleList(TrackGroup::fromBundle, trackGroupBundles) + .toArray(new TrackGroup[0])); + } private void verifyCorrectness() { for (int i = 0; i < trackGroups.size(); i++) { diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java index 34c732b992..966995854a 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java @@ -55,7 +55,7 @@ import androidx.media3.common.TrackSelectionOverride; import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences; import androidx.media3.common.util.Assertions; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.Log; import androidx.media3.common.util.NullableType; import androidx.media3.common.util.UnstableApi; @@ -1646,15 +1646,16 @@ public class DefaultTrackSelector extends MappingTrackSelector List trackGroupArrays = trackGroupArrayBundles == null ? ImmutableList.of() - : BundleableUtil.fromBundleList(TrackGroupArray.CREATOR, trackGroupArrayBundles); + : BundleCollectionUtil.fromBundleList( + TrackGroupArray::fromBundle, trackGroupArrayBundles); @Nullable SparseArray selectionOverrideBundles = bundle.getSparseParcelableArray(Parameters.FIELD_SELECTION_OVERRIDES); SparseArray selectionOverrides = selectionOverrideBundles == null ? new SparseArray<>() - : BundleableUtil.fromBundleSparseArray( - SelectionOverride.CREATOR, selectionOverrideBundles); + : BundleCollectionUtil.fromBundleSparseArray( + SelectionOverride::fromBundle, selectionOverrideBundles); if (rendererIndices == null || rendererIndices.length != trackGroupArrays.size()) { return; // Incorrect format, ignore all overrides. @@ -2091,9 +2092,10 @@ public class DefaultTrackSelector extends MappingTrackSelector FIELD_SELECTION_OVERRIDES_RENDERER_INDICES, Ints.toArray(rendererIndices)); bundle.putParcelableArrayList( FIELD_SELECTION_OVERRIDES_TRACK_GROUP_ARRAYS, - BundleableUtil.toBundleArrayList(trackGroupArrays)); + BundleCollectionUtil.toBundleArrayList(trackGroupArrays, TrackGroupArray::toBundle)); bundle.putSparseParcelableArray( - FIELD_SELECTION_OVERRIDES, BundleableUtil.toBundleSparseArray(selections)); + FIELD_SELECTION_OVERRIDES, + BundleCollectionUtil.toBundleSparseArray(selections, SelectionOverride::toBundle)); } } @@ -2238,15 +2240,18 @@ public class DefaultTrackSelector extends MappingTrackSelector /** Object that can restore {@code SelectionOverride} from a {@link Bundle}. */ @UnstableApi - public static final Creator CREATOR = - bundle -> { - int groupIndex = bundle.getInt(FIELD_GROUP_INDEX, -1); - @Nullable int[] tracks = bundle.getIntArray(FIELD_TRACKS); - int trackType = bundle.getInt(FIELD_TRACK_TYPE, -1); - Assertions.checkArgument(groupIndex >= 0 && trackType >= 0); - Assertions.checkNotNull(tracks); - return new SelectionOverride(groupIndex, tracks, trackType); - }; + public static final Creator CREATOR = SelectionOverride::fromBundle; + + /** Restores a {@code SelectionOverride} from a {@link Bundle}. */ + @UnstableApi + public static SelectionOverride fromBundle(Bundle bundle) { + int groupIndex = bundle.getInt(FIELD_GROUP_INDEX, -1); + @Nullable int[] tracks = bundle.getIntArray(FIELD_TRACKS); + int trackType = bundle.getInt(FIELD_TRACK_TYPE, -1); + Assertions.checkArgument(groupIndex >= 0 && trackType >= 0); + Assertions.checkNotNull(tracks); + return new SelectionOverride(groupIndex, tracks, trackType); + } } /** diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/source/TrackGroupArrayTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/source/TrackGroupArrayTest.java index 4557f251b9..3d09048471 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/source/TrackGroupArrayTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/source/TrackGroupArrayTest.java @@ -41,7 +41,7 @@ public final class TrackGroupArrayTest { TrackGroupArray trackGroupArrayToBundle = new TrackGroupArray(trackGroup1, trackGroup2); TrackGroupArray trackGroupArrayFromBundle = - TrackGroupArray.CREATOR.fromBundle(trackGroupArrayToBundle.toBundle()); + TrackGroupArray.fromBundle(trackGroupArrayToBundle.toBundle()); assertThat(trackGroupArrayFromBundle).isEqualTo(trackGroupArrayToBundle); } diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelectorTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelectorTest.java index 3c1cf49c86..2ea08255bc 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelectorTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelectorTest.java @@ -45,7 +45,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.media.Spatializer; -import androidx.media3.common.Bundleable; import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; @@ -181,7 +180,7 @@ public final class DefaultTrackSelectorTest { assertThat(parameters.buildUpon().build()).isEqualTo(parameters); } - /** Tests {@link Parameters} {@link Bundleable} implementation. */ + /** Tests {@link Parameters} bundle implementation. */ @Test public void roundTripViaBundle_ofParameters_yieldsEqualInstance() { Parameters parametersToBundle = buildParametersForEqualsTest(); @@ -2841,15 +2840,14 @@ public final class DefaultTrackSelectorTest { assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED); } - /** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */ + /** Tests {@link SelectionOverride}'s bundle implementation. */ @Test public void roundTripViaBundle_ofSelectionOverride_yieldsEqualInstance() { SelectionOverride selectionOverrideToBundle = new SelectionOverride(/* groupIndex= */ 1, /* tracks...= */ 2, 3); SelectionOverride selectionOverrideFromBundle = - DefaultTrackSelector.SelectionOverride.CREATOR.fromBundle( - selectionOverrideToBundle.toBundle()); + DefaultTrackSelector.SelectionOverride.fromBundle(selectionOverrideToBundle.toBundle()); assertThat(selectionOverrideFromBundle).isEqualTo(selectionOverrideToBundle); } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/CueDecoder.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/CueDecoder.java index fcda2ed1f5..e64f9d8308 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/CueDecoder.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/CueDecoder.java @@ -19,7 +19,7 @@ import android.os.Bundle; import android.os.Parcel; import androidx.media3.common.text.Cue; import androidx.media3.common.util.Assertions; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.UnstableApi; import java.util.ArrayList; import java.util.List; @@ -65,7 +65,7 @@ public final class CueDecoder { ArrayList bundledCues = Assertions.checkNotNull(bundle.getParcelableArrayList(BUNDLE_FIELD_CUES)); return new CuesWithTiming( - BundleableUtil.fromBundleList(Cue.CREATOR, bundledCues), + BundleCollectionUtil.fromBundleList(Cue::fromBundle, bundledCues), startTimeUs, bundle.getLong(BUNDLE_FIELD_DURATION_US)); } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/text/CueEncoder.java b/libraries/extractor/src/main/java/androidx/media3/extractor/text/CueEncoder.java index 8519b8b32e..9439b98441 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/text/CueEncoder.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/text/CueEncoder.java @@ -18,7 +18,7 @@ package androidx.media3.extractor.text; import android.os.Bundle; import android.os.Parcel; import androidx.media3.common.text.Cue; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.UnstableApi; import java.util.ArrayList; import java.util.List; @@ -36,7 +36,7 @@ public final class CueEncoder { * @return The serialized byte array. */ public byte[] encode(List cues, long durationUs) { - ArrayList bundledCues = BundleableUtil.toBundleArrayList(cues); + ArrayList bundledCues = BundleCollectionUtil.toBundleArrayList(cues, Cue::toBundle); Bundle allCuesBundle = new Bundle(); allCuesBundle.putParcelableArrayList(CueDecoder.BUNDLE_FIELD_CUES, bundledCues); allCuesBundle.putLong(CueDecoder.BUNDLE_FIELD_DURATION_US, durationUs); diff --git a/libraries/session/src/main/java/androidx/media3/session/CommandButton.java b/libraries/session/src/main/java/androidx/media3/session/CommandButton.java index 2a03eb4d4d..3a55d51432 100644 --- a/libraries/session/src/main/java/androidx/media3/session/CommandButton.java +++ b/libraries/session/src/main/java/androidx/media3/session/CommandButton.java @@ -294,10 +294,12 @@ public final class CommandButton implements Bundleable { return bundle; } - /** Object that can restore {@link CommandButton} from a {@link Bundle}. */ + /** Object that can restore {@code CommandButton} from a {@link Bundle}. */ @UnstableApi public static final Creator CREATOR = CommandButton::fromBundle; - private static CommandButton fromBundle(Bundle bundle) { + /** Restores a {@code CommandButton} from a {@link Bundle}. */ + @UnstableApi + public static CommandButton fromBundle(Bundle bundle) { @Nullable Bundle sessionCommandBundle = bundle.getBundle(FIELD_SESSION_COMMAND); @Nullable SessionCommand sessionCommand = diff --git a/libraries/session/src/main/java/androidx/media3/session/ConnectionState.java b/libraries/session/src/main/java/androidx/media3/session/ConnectionState.java index bf928cd1f0..a7eb3143db 100644 --- a/libraries/session/src/main/java/androidx/media3/session/ConnectionState.java +++ b/libraries/session/src/main/java/androidx/media3/session/ConnectionState.java @@ -25,8 +25,8 @@ import androidx.annotation.Nullable; import androidx.core.app.BundleCompat; import androidx.media3.common.Bundleable; import androidx.media3.common.Player; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.BundleUtil; -import androidx.media3.common.util.BundleableUtil; import androidx.media3.common.util.Util; import com.google.common.collect.ImmutableList; import java.util.List; @@ -108,7 +108,8 @@ import java.util.List; bundle.putParcelable(FIELD_SESSION_ACTIVITY, sessionActivity); if (!customLayout.isEmpty()) { bundle.putParcelableArrayList( - FIELD_CUSTOM_LAYOUT, BundleableUtil.toBundleArrayList(customLayout)); + FIELD_CUSTOM_LAYOUT, + BundleCollectionUtil.toBundleArrayList(customLayout, CommandButton::toBundle)); } bundle.putBundle(FIELD_SESSION_COMMANDS, sessionCommands.toBundle()); bundle.putBundle(FIELD_PLAYER_COMMANDS_FROM_SESSION, playerCommandsFromSession.toBundle()); @@ -153,7 +154,7 @@ import java.util.List; List commandButtonArrayList = bundle.getParcelableArrayList(FIELD_CUSTOM_LAYOUT); ImmutableList customLayout = commandButtonArrayList != null - ? BundleableUtil.fromBundleList(CommandButton.CREATOR, commandButtonArrayList) + ? BundleCollectionUtil.fromBundleList(CommandButton::fromBundle, commandButtonArrayList) : ImmutableList.of(); @Nullable Bundle sessionCommandsBundle = bundle.getBundle(FIELD_SESSION_COMMANDS); SessionCommands sessionCommands = diff --git a/libraries/session/src/main/java/androidx/media3/session/LibraryResult.java b/libraries/session/src/main/java/androidx/media3/session/LibraryResult.java index 4310bf697e..a1972522d5 100644 --- a/libraries/session/src/main/java/androidx/media3/session/LibraryResult.java +++ b/libraries/session/src/main/java/androidx/media3/session/LibraryResult.java @@ -32,7 +32,7 @@ import androidx.media3.common.BundleListRetriever; import androidx.media3.common.Bundleable; import androidx.media3.common.MediaItem; import androidx.media3.common.MediaMetadata; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import androidx.media3.session.MediaLibraryService.LibraryParams; @@ -292,7 +292,9 @@ public final class LibraryResult implements Bundleable { BundleCompat.putBinder( bundle, FIELD_VALUE, - new BundleListRetriever(BundleableUtil.toBundleList((ImmutableList) value))); + new BundleListRetriever( + BundleCollectionUtil.toBundleList( + (ImmutableList) value, MediaItem::toBundle))); break; case VALUE_TYPE_VOID: case VALUE_TYPE_ERROR: @@ -376,8 +378,8 @@ public final class LibraryResult implements Bundleable { value = valueRetriever == null ? null - : BundleableUtil.fromBundleList( - MediaItem.CREATOR, BundleListRetriever.getList(valueRetriever)); + : BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(valueRetriever)); break; case VALUE_TYPE_VOID: case VALUE_TYPE_ERROR: diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java index febd4e485d..70172f8a54 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java @@ -73,7 +73,7 @@ import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.CueGroup; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.Clock; import androidx.media3.common.util.ListenerSet; import androidx.media3.common.util.Log; @@ -801,7 +801,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; controllerStub, seq, new BundleListRetriever( - BundleableUtil.toBundleList( + BundleCollectionUtil.toBundleList( mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); setMediaItemsInternal( @@ -823,7 +823,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; controllerStub, seq, new BundleListRetriever( - BundleableUtil.toBundleList( + BundleCollectionUtil.toBundleList( mediaItems, MediaItem::toBundleIncludeLocalConfiguration)), resetPosition)); @@ -846,7 +846,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; controllerStub, seq, new BundleListRetriever( - BundleableUtil.toBundleList( + BundleCollectionUtil.toBundleList( mediaItems, MediaItem::toBundleIncludeLocalConfiguration)), startIndex, startPositionMs)); @@ -921,7 +921,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; controllerStub, seq, new BundleListRetriever( - BundleableUtil.toBundleList( + BundleCollectionUtil.toBundleList( mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); addMediaItemsInternal(getCurrentTimeline().getWindowCount(), mediaItems); @@ -941,7 +941,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; seq, index, new BundleListRetriever( - BundleableUtil.toBundleList( + BundleCollectionUtil.toBundleList( mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); addMediaItemsInternal(index, mediaItems); @@ -1254,7 +1254,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; (iSession, seq) -> { IBinder mediaItemsBundleBinder = new BundleListRetriever( - BundleableUtil.toBundleList( + BundleCollectionUtil.toBundleList( mediaItems, MediaItem::toBundleIncludeLocalConfiguration)); if (checkNotNull(connectedToken).getInterfaceVersion() >= 2) { iSession.replaceMediaItems( diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerStub.java index 9c4dc73119..636532cd7d 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerStub.java @@ -25,7 +25,7 @@ import android.os.RemoteException; import android.text.TextUtils; import androidx.annotation.Nullable; import androidx.media3.common.Player.Commands; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.Log; import androidx.media3.session.MediaLibraryService.LibraryParams; import androidx.media3.session.PlayerInfo.BundlingExclusions; @@ -100,7 +100,8 @@ import org.checkerframework.checker.nullness.qual.NonNull; public void onSetCustomLayout(int seq, List commandButtonBundleList) { List layout; try { - layout = BundleableUtil.fromBundleList(CommandButton.CREATOR, commandButtonBundleList); + layout = + BundleCollectionUtil.fromBundleList(CommandButton::fromBundle, commandButtonBundleList); } catch (RuntimeException e) { Log.w(TAG, "Ignoring malformed Bundle for CommandButton", e); return; diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java index 5bde573e57..5f61a9ccf0 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java @@ -80,7 +80,7 @@ import androidx.media3.common.TrackSelectionOverride; import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.Tracks; import androidx.media3.common.util.Assertions; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.Consumer; import androidx.media3.common.util.Log; import androidx.media3.common.util.Util; @@ -1045,8 +1045,8 @@ import java.util.concurrent.ExecutionException; List mediaItemList; try { mediaItemList = - BundleableUtil.fromBundleList( - MediaItem.CREATOR, BundleListRetriever.getList(mediaItemsRetriever)); + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); } catch (RuntimeException e) { Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); return; @@ -1083,8 +1083,8 @@ import java.util.concurrent.ExecutionException; List mediaItemList; try { mediaItemList = - BundleableUtil.fromBundleList( - MediaItem.CREATOR, BundleListRetriever.getList(mediaItemsRetriever)); + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); } catch (RuntimeException e) { Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); return; @@ -1192,8 +1192,8 @@ import java.util.concurrent.ExecutionException; List mediaItems; try { mediaItems = - BundleableUtil.fromBundleList( - MediaItem.CREATOR, BundleListRetriever.getList(mediaItemsRetriever)); + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); } catch (RuntimeException e) { Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); return; @@ -1221,8 +1221,8 @@ import java.util.concurrent.ExecutionException; List mediaItems; try { mediaItems = - BundleableUtil.fromBundleList( - MediaItem.CREATOR, BundleListRetriever.getList(mediaItemsRetriever)); + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); } catch (RuntimeException e) { Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); return; @@ -1360,8 +1360,8 @@ import java.util.concurrent.ExecutionException; ImmutableList mediaItems; try { mediaItems = - BundleableUtil.fromBundleList( - MediaItem.CREATOR, BundleListRetriever.getList(mediaItemsRetriever)); + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); } catch (RuntimeException e) { Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); return; @@ -2006,7 +2006,8 @@ import java.util.concurrent.ExecutionException; @Override public void setCustomLayout(int sequenceNumber, List layout) throws RemoteException { - iController.onSetCustomLayout(sequenceNumber, BundleableUtil.toBundleList(layout)); + iController.onSetCustomLayout( + sequenceNumber, BundleCollectionUtil.toBundleList(layout, CommandButton::toBundle)); } @Override diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java index 7bc0a320d0..07d656cb47 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java @@ -34,7 +34,7 @@ import androidx.media3.common.MediaMetadata; import androidx.media3.common.PlaybackParameters; import androidx.media3.common.Rating; import androidx.media3.common.TrackSelectionParameters; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.Log; import androidx.media3.test.session.common.IRemoteMediaController; import androidx.media3.test.session.common.TestHandler; @@ -325,7 +325,7 @@ public class MediaControllerProviderService extends Service { () -> { MediaController controller = mediaControllerMap.get(controllerId); controller.setMediaItems( - BundleableUtil.fromBundleList(MediaItem.CREATOR, mediaItemBundles)); + BundleCollectionUtil.fromBundleList(MediaItem::fromBundle, mediaItemBundles)); }); } @@ -337,7 +337,8 @@ public class MediaControllerProviderService extends Service { () -> { MediaController controller = mediaControllerMap.get(controllerId); controller.setMediaItems( - BundleableUtil.fromBundleList(MediaItem.CREATOR, mediaItemBundles), resetPosition); + BundleCollectionUtil.fromBundleList(MediaItem::fromBundle, mediaItemBundles), + resetPosition); }); } @@ -349,7 +350,7 @@ public class MediaControllerProviderService extends Service { () -> { MediaController controller = mediaControllerMap.get(controllerId); controller.setMediaItems( - BundleableUtil.fromBundleList(MediaItem.CREATOR, mediaItemBundles), + BundleCollectionUtil.fromBundleList(MediaItem::fromBundle, mediaItemBundles), startIndex, startPositionMs); }); @@ -407,7 +408,7 @@ public class MediaControllerProviderService extends Service { () -> { MediaController controller = mediaControllerMap.get(controllerId); controller.addMediaItems( - BundleableUtil.fromBundleList(MediaItem.CREATOR, mediaItemBundles)); + BundleCollectionUtil.fromBundleList(MediaItem::fromBundle, mediaItemBundles)); }); } @@ -418,7 +419,8 @@ public class MediaControllerProviderService extends Service { () -> { MediaController controller = mediaControllerMap.get(controllerId); controller.addMediaItems( - index, BundleableUtil.fromBundleList(MediaItem.CREATOR, mediaItemBundles)); + index, + BundleCollectionUtil.fromBundleList(MediaItem::fromBundle, mediaItemBundles)); }); } @@ -488,7 +490,9 @@ public class MediaControllerProviderService extends Service { () -> { MediaController controller = mediaControllerMap.get(controllerId); controller.replaceMediaItems( - fromIndex, toIndex, BundleableUtil.fromBundleList(MediaItem.CREATOR, mediaItems)); + fromIndex, + toIndex, + BundleCollectionUtil.fromBundleList(MediaItem::fromBundle, mediaItems)); }); } @@ -753,11 +757,11 @@ public class MediaControllerProviderService extends Service { () -> { MediaController controller = mediaControllerMap.get(controllerId); controller.setMediaItems( - BundleableUtil.fromBundleList(MediaItem.CREATOR, initialMediaItems)); + BundleCollectionUtil.fromBundleList(MediaItem::fromBundle, initialMediaItems)); controller.prepare(); controller.play(); controller.addMediaItems( - BundleableUtil.fromBundleList(MediaItem.CREATOR, addedMediaItems)); + BundleCollectionUtil.fromBundleList(MediaItem::fromBundle, addedMediaItems)); controller.seekTo(seekIndex, /* positionMs= */ 0); }); } diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java index 22b4727f28..d49ff24192 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java @@ -39,7 +39,7 @@ import androidx.media3.common.Player; import androidx.media3.common.Player.RepeatMode; import androidx.media3.common.Rating; import androidx.media3.common.TrackSelectionParameters; -import androidx.media3.common.util.BundleableUtil; +import androidx.media3.common.util.BundleCollectionUtil; import androidx.media3.common.util.Log; import androidx.media3.test.session.common.IRemoteMediaController; import androidx.media3.test.session.common.TestUtils; @@ -162,26 +162,33 @@ public class RemoteMediaController { } public void setMediaItems(List mediaItems) throws RemoteException { - binder.setMediaItems(controllerId, BundleableUtil.toBundleList(mediaItems)); + binder.setMediaItems( + controllerId, BundleCollectionUtil.toBundleList(mediaItems, MediaItem::toBundle)); } public void setMediaItemsIncludeLocalConfiguration(List mediaItems) throws RemoteException { binder.setMediaItems( controllerId, - BundleableUtil.toBundleList(mediaItems, MediaItem::toBundleIncludeLocalConfiguration)); + BundleCollectionUtil.toBundleList( + mediaItems, MediaItem::toBundleIncludeLocalConfiguration)); } public void setMediaItems(List mediaItems, boolean resetPosition) throws RemoteException { binder.setMediaItemsWithResetPosition( - controllerId, BundleableUtil.toBundleList(mediaItems), resetPosition); + controllerId, + BundleCollectionUtil.toBundleList(mediaItems, MediaItem::toBundle), + resetPosition); } public void setMediaItems(List mediaItems, int startIndex, long startPositionMs) throws RemoteException { binder.setMediaItemsWithStartIndex( - controllerId, BundleableUtil.toBundleList(mediaItems), startIndex, startPositionMs); + controllerId, + BundleCollectionUtil.toBundleList(mediaItems, MediaItem::toBundle), + startIndex, + startPositionMs); } /** @@ -211,18 +218,21 @@ public class RemoteMediaController { } public void addMediaItems(List mediaItems) throws RemoteException { - binder.addMediaItems(controllerId, BundleableUtil.toBundleList(mediaItems)); + binder.addMediaItems( + controllerId, BundleCollectionUtil.toBundleList(mediaItems, MediaItem::toBundle)); } public void addMediaItemsIncludeLocalConfiguration(List mediaItems) throws RemoteException { binder.addMediaItems( controllerId, - BundleableUtil.toBundleList(mediaItems, MediaItem::toBundleIncludeLocalConfiguration)); + BundleCollectionUtil.toBundleList( + mediaItems, MediaItem::toBundleIncludeLocalConfiguration)); } public void addMediaItems(int index, List mediaItems) throws RemoteException { - binder.addMediaItemsWithIndex(controllerId, index, BundleableUtil.toBundleList(mediaItems)); + binder.addMediaItemsWithIndex( + controllerId, index, BundleCollectionUtil.toBundleList(mediaItems, MediaItem::toBundle)); } public void removeMediaItem(int index) throws RemoteException { @@ -252,7 +262,10 @@ public class RemoteMediaController { public void replaceMediaItems(int fromIndex, int toIndex, List mediaItems) throws RemoteException { binder.replaceMediaItems( - controllerId, fromIndex, toIndex, BundleableUtil.toBundleList(mediaItems)); + controllerId, + fromIndex, + toIndex, + BundleCollectionUtil.toBundleList(mediaItems, MediaItem::toBundle)); } public void seekToPreviousMediaItem() throws RemoteException { @@ -354,8 +367,8 @@ public class RemoteMediaController { throws RemoteException { binder.setMediaItemsPreparePlayAddItemsSeek( controllerId, - BundleableUtil.toBundleList(initialMediaItems), - BundleableUtil.toBundleList(addedMediaItems), + BundleCollectionUtil.toBundleList(initialMediaItems, MediaItem::toBundle), + BundleCollectionUtil.toBundleList(addedMediaItems, MediaItem::toBundle), seekIndex); }