Make AdsLoader.State implement Bundleable
This allows the AdsLoader.State to be stored in savedInstanceState #minor-release PiperOrigin-RevId: 429057697
This commit is contained in:
parent
1af841698f
commit
0842295a88
@ -28,17 +28,22 @@ import static androidx.media3.exoplayer.ima.ImaUtil.updateAdDurationAndPropagate
|
||||
import static androidx.media3.exoplayer.ima.ImaUtil.updateAdDurationInAdGroup;
|
||||
import static androidx.media3.exoplayer.source.ads.ServerSideAdInsertionUtil.addAdGroupToAdPlaybackState;
|
||||
import static java.lang.Math.min;
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Pair;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.media3.common.AdOverlayInfo;
|
||||
import androidx.media3.common.AdPlaybackState;
|
||||
import androidx.media3.common.AdViewProvider;
|
||||
import androidx.media3.common.Bundleable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.Metadata;
|
||||
@ -88,6 +93,10 @@ import com.google.ads.interactivemedia.v3.api.player.VideoStreamPlayer;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@ -285,13 +294,67 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
|
||||
}
|
||||
|
||||
/** The state of the {@link AdsLoader}. */
|
||||
public static class State {
|
||||
public static class State implements Bundleable {
|
||||
|
||||
private final ImmutableMap<String, AdPlaybackState> adPlaybackStates;
|
||||
|
||||
private State(ImmutableMap<String, AdPlaybackState> adPlaybackStates) {
|
||||
@VisibleForTesting
|
||||
/* package */ State(ImmutableMap<String, AdPlaybackState> adPlaybackStates) {
|
||||
this.adPlaybackStates = adPlaybackStates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof State)) {
|
||||
return false;
|
||||
}
|
||||
State state = (State) o;
|
||||
return adPlaybackStates.equals(state.adPlaybackStates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return adPlaybackStates.hashCode();
|
||||
}
|
||||
|
||||
// Bundleable implementation.
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(TYPE_USE)
|
||||
@IntDef({FIELD_AD_PLAYBACK_STATES})
|
||||
private @interface FieldNumber {}
|
||||
|
||||
private static final int FIELD_AD_PLAYBACK_STATES = 1;
|
||||
|
||||
@Override
|
||||
public Bundle toBundle() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(keyForField(FIELD_AD_PLAYBACK_STATES), adPlaybackStates);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/** Object that can restore {@link AdsLoader.State} from a {@link Bundle}. */
|
||||
public static final Bundleable.Creator<State> CREATOR = State::fromBundle;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static State fromBundle(Bundle bundle) {
|
||||
@Nullable
|
||||
Map<String, AdPlaybackState> adPlaybackStateMap =
|
||||
(Map<String, AdPlaybackState>)
|
||||
bundle.getSerializable(keyForField(FIELD_AD_PLAYBACK_STATES));
|
||||
return new State(
|
||||
adPlaybackStateMap != null
|
||||
? ImmutableMap.copyOf(adPlaybackStateMap)
|
||||
: ImmutableMap.of());
|
||||
}
|
||||
|
||||
private static String keyForField(@FieldNumber int field) {
|
||||
return Integer.toString(field, Character.MAX_RADIX);
|
||||
}
|
||||
}
|
||||
|
||||
private final ImaUtil.ServerSideAdInsertionConfiguration configuration;
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package androidx.media3.exoplayer.ima;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.media3.common.AdPlaybackState;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.AdsLoader.State;
|
||||
import androidx.media3.exoplayer.source.ads.ServerSideAdInsertionUtil;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/** Unit tests for {@link ImaServerSideAdInsertionMediaSource}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ImaServerSideAdInsertionMediaSourceTest {
|
||||
|
||||
@Test
|
||||
public void adsLoaderStateToBundle_marshallAndUnmarshalling_resultIsEqual() {
|
||||
AdPlaybackState firstAdPlaybackState =
|
||||
ServerSideAdInsertionUtil.addAdGroupToAdPlaybackState(
|
||||
new AdPlaybackState("adsId1"),
|
||||
/* fromPositionUs= */ 0,
|
||||
/* contentResumeOffsetUs= */ 10,
|
||||
/* adDurationsUs...= */ 5_000_000,
|
||||
10_000_000,
|
||||
20_000_000);
|
||||
AdPlaybackState secondAdPlaybackState =
|
||||
ServerSideAdInsertionUtil.addAdGroupToAdPlaybackState(
|
||||
new AdPlaybackState("adsId2"),
|
||||
/* fromPositionUs= */ 0,
|
||||
/* contentResumeOffsetUs= */ 10,
|
||||
/* adDurationsUs...= */ 10_000_000)
|
||||
.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||
AdPlaybackState thirdAdPlaybackState =
|
||||
ServerSideAdInsertionUtil.addAdGroupToAdPlaybackState(
|
||||
new AdPlaybackState("adsId3"),
|
||||
/* fromPositionUs= */ C.TIME_END_OF_SOURCE,
|
||||
/* contentResumeOffsetUs= */ 10,
|
||||
/* adDurationsUs...= */ 10_000_000);
|
||||
thirdAdPlaybackState =
|
||||
ServerSideAdInsertionUtil.addAdGroupToAdPlaybackState(
|
||||
thirdAdPlaybackState,
|
||||
/* fromPositionUs= */ 0,
|
||||
/* contentResumeOffsetUs= */ 10,
|
||||
/* adDurationsUs...= */ 10_000_000)
|
||||
.withRemovedAdGroupCount(1);
|
||||
State state =
|
||||
new State(
|
||||
ImmutableMap.<String, AdPlaybackState>builder()
|
||||
.put("adsId1", firstAdPlaybackState)
|
||||
.put("adsId2", secondAdPlaybackState)
|
||||
.put("adsId3", thirdAdPlaybackState)
|
||||
.buildOrThrow());
|
||||
|
||||
assertThat(State.CREATOR.fromBundle(state.toBundle())).isEqualTo(state);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user