diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java index df262e5c8c..692fad5c9a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java @@ -33,6 +33,7 @@ import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.EventDispatcher; import com.google.android.exoplayer2.util.Log; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import com.google.android.exoplayer2.util.Util; import java.io.IOException; import java.util.Arrays; @@ -258,7 +259,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } @Override - public void acquire() { + public void acquire(@Nullable MediaSourceEventDispatcher eventDispatcher) { Assertions.checkState(referenceCount >= 0); if (++referenceCount == 1) { Assertions.checkState(state == STATE_OPENING); @@ -272,7 +273,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } @Override - public void release() { + public void release(@Nullable MediaSourceEventDispatcher eventDispatcher) { if (--referenceCount == 0) { // Assigning null to various non-null variables for clean-up. state = STATE_RELEASED; @@ -288,7 +289,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; if (sessionId != null) { mediaDrm.closeSession(sessionId); sessionId = null; - eventDispatcher.dispatch(DefaultDrmSessionEventListener::onDrmSessionReleased); + this.eventDispatcher.dispatch(DefaultDrmSessionEventListener::onDrmSessionReleased); } releaseCallback.onSessionReleased(this); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java index 76fa19af52..b510413d84 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java @@ -31,6 +31,7 @@ import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.EventDispatcher; import com.google.android.exoplayer2.util.Log; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import com.google.android.exoplayer2.util.Util; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -386,8 +387,8 @@ public class DefaultDrmSessionManager implements DrmSe /** * Sets the mode, which determines the role of sessions acquired from the instance. This must be - * called before {@link #acquireSession(Looper, DrmInitData)} or {@link - * #acquirePlaceholderSession} is called. + * called before {@link #acquireSession(Looper, MediaSourceEventDispatcher, DrmInitData)} or + * {@link #acquirePlaceholderSession} is called. * *

By default, the mode is {@link #MODE_PLAYBACK} and a streaming license is requested when * required. @@ -490,12 +491,15 @@ public class DefaultDrmSessionManager implements DrmSe sessions.add(placeholderDrmSession); this.placeholderDrmSession = placeholderDrmSession; } - placeholderDrmSession.acquire(); + placeholderDrmSession.acquire(/* eventDispatcher= */ null); return placeholderDrmSession; } @Override - public DrmSession acquireSession(Looper playbackLooper, DrmInitData drmInitData) { + public DrmSession acquireSession( + Looper playbackLooper, + @Nullable MediaSourceEventDispatcher eventDispatcher, + DrmInitData drmInitData) { assertExpectedPlaybackLooper(playbackLooper); maybeCreateMediaDrmHandler(playbackLooper); @@ -504,7 +508,7 @@ public class DefaultDrmSessionManager implements DrmSe schemeDatas = getSchemeDatas(drmInitData, uuid, false); if (schemeDatas.isEmpty()) { final MissingSchemeDataException error = new MissingSchemeDataException(uuid); - eventDispatcher.dispatch(listener -> listener.onDrmSessionManagerError(error)); + this.eventDispatcher.dispatch(listener -> listener.onDrmSessionManagerError(error)); return new ErrorStateDrmSession<>(new DrmSessionException(error)); } } @@ -531,7 +535,7 @@ public class DefaultDrmSessionManager implements DrmSe } sessions.add(session); } - session.acquire(); + session.acquire(eventDispatcher); return session; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java index 35358f04f7..950b612f16 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java @@ -18,6 +18,7 @@ package com.google.android.exoplayer2.drm; import android.media.MediaDrm; import androidx.annotation.IntDef; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import java.io.IOException; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -30,8 +31,11 @@ import java.util.Map; public interface DrmSession { /** - * Invokes {@code newSession's} {@link #acquire()} and {@code previousSession's} {@link - * #release()} in that order. Null arguments are ignored. Does nothing if {@code previousSession} + * Acquires {@code newSession} then releases {@code previousSession}. + * + *

Invokes {@code newSession's} {@link #acquire(MediaSourceEventDispatcher)} and {@code + * previousSession's} {@link #release(MediaSourceEventDispatcher)} in that order (passing {@code + * eventDispatcher = null}). Null arguments are ignored. Does nothing if {@code previousSession} * and {@code newSession} are the same session. */ static void replaceSession( @@ -41,10 +45,10 @@ public interface DrmSession { return; } if (newSession != null) { - newSession.acquire(); + newSession.acquire(/* eventDispatcher= */ null); } if (previousSession != null) { - previousSession.release(); + previousSession.release(/* eventDispatcher= */ null); } } @@ -132,13 +136,20 @@ public interface DrmSession { /** * Increments the reference count. When the caller no longer needs to use the instance, it must - * call {@link #release()} to decrement the reference count. + * call {@link #release(MediaSourceEventDispatcher)} to decrement the reference count. + * + * @param eventDispatcher The {@link MediaSourceEventDispatcher} used to route DRM-related events + * dispatched from this session, or null if no event handling is needed. */ - void acquire(); + void acquire(@Nullable MediaSourceEventDispatcher eventDispatcher); /** * Decrements the reference count. If the reference count drops to 0 underlying resources are * released, and the instance cannot be re-used. + * + * @param eventDispatcher The {@link MediaSourceEventDispatcher} to disconnect when the session is + * released (the same instance (possibly null) that was passed by the caller to {@link + * #acquire(MediaSourceEventDispatcher)}). */ - void release(); + void release(@Nullable MediaSourceEventDispatcher eventDispatcher); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java index 146c5d704d..47ee4bb495 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java @@ -19,6 +19,7 @@ import android.os.Looper; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; /** * Manages a DRM session. @@ -42,7 +43,9 @@ public interface DrmSessionManager { @Override public DrmSession acquireSession( - Looper playbackLooper, DrmInitData drmInitData) { + Looper playbackLooper, + @Nullable MediaSourceEventDispatcher eventDispatcher, + DrmInitData drmInitData) { return new ErrorStateDrmSession<>( new DrmSession.DrmSessionException( new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME))); @@ -83,7 +86,7 @@ public interface DrmSessionManager { /** * Returns a {@link DrmSession} that does not execute key requests, with an incremented reference * count. When the caller no longer needs to use the instance, it must call {@link - * DrmSession#release()} to decrement the reference count. + * DrmSession#release(MediaSourceEventDispatcher)} to decrement the reference count. * *

Placeholder {@link DrmSession DrmSessions} may be used to configure secure decoders for * playback of clear content periods. This can reduce the cost of transitioning between clear and @@ -103,14 +106,19 @@ public interface DrmSessionManager { /** * Returns a {@link DrmSession} for the specified {@link DrmInitData}, with an incremented * reference count. When the caller no longer needs to use the instance, it must call {@link - * DrmSession#release()} to decrement the reference count. + * DrmSession#release(MediaSourceEventDispatcher)} to decrement the reference count. * * @param playbackLooper The looper associated with the media playback thread. + * @param eventDispatcher The {@link MediaSourceEventDispatcher} used to distribute events, and + * passed on to {@link DrmSession#acquire(MediaSourceEventDispatcher)}. * @param drmInitData DRM initialization data. All contained {@link SchemeData}s must contain * non-null {@link SchemeData#data}. * @return The DRM session. */ - DrmSession acquireSession(Looper playbackLooper, DrmInitData drmInitData); + DrmSession acquireSession( + Looper playbackLooper, + @Nullable MediaSourceEventDispatcher eventDispatcher, + DrmInitData drmInitData); /** * Returns the {@link ExoMediaCrypto} type returned by sessions acquired using the given {@link diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java index 0028e47987..d7b33bbc26 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer2.drm; import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import java.util.Map; /** A {@link DrmSession} that's in a terminal error state. */ @@ -63,12 +64,12 @@ public final class ErrorStateDrmSession implements Drm } @Override - public void acquire() { + public void acquire(@Nullable MediaSourceEventDispatcher eventDispatcher) { // Do nothing. } @Override - public void release() { + public void release(@Nullable MediaSourceEventDispatcher eventDispatcher) { // Do nothing. } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java index 72cc586ded..d3d1fc3219 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java @@ -26,8 +26,8 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.Mode; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.upstream.HttpDataSource; -import com.google.android.exoplayer2.upstream.HttpDataSource.Factory; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import java.util.Collections; import java.util.Map; import java.util.UUID; @@ -41,6 +41,7 @@ public final class OfflineLicenseHelper { private final ConditionVariable conditionVariable; private final DefaultDrmSessionManager drmSessionManager; private final HandlerThread handlerThread; + private final MediaSourceEventDispatcher eventDispatcher; /** * Instantiates a new instance which uses Widevine CDM. Call {@link #release()} when the instance @@ -49,14 +50,18 @@ public final class OfflineLicenseHelper { * @param defaultLicenseUrl The default license URL. Used for key requests that do not specify * their own license URL. * @param httpDataSourceFactory A factory from which to obtain {@link HttpDataSource} instances. + * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related + * events. * @return A new instance which uses Widevine CDM. * @throws UnsupportedDrmException If the Widevine DRM scheme is unsupported or cannot be * instantiated. */ public static OfflineLicenseHelper newWidevineInstance( - String defaultLicenseUrl, Factory httpDataSourceFactory) + String defaultLicenseUrl, + HttpDataSource.Factory httpDataSourceFactory, + MediaSourceEventDispatcher eventDispatcher) throws UnsupportedDrmException { - return newWidevineInstance(defaultLicenseUrl, false, httpDataSourceFactory, null); + return newWidevineInstance(defaultLicenseUrl, false, httpDataSourceFactory, eventDispatcher); } /** @@ -68,15 +73,24 @@ public final class OfflineLicenseHelper { * @param forceDefaultLicenseUrl Whether to use {@code defaultLicenseUrl} for key requests that * include their own license URL. * @param httpDataSourceFactory A factory from which to obtain {@link HttpDataSource} instances. + * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related + * events. * @return A new instance which uses Widevine CDM. * @throws UnsupportedDrmException If the Widevine DRM scheme is unsupported or cannot be * instantiated. */ public static OfflineLicenseHelper newWidevineInstance( - String defaultLicenseUrl, boolean forceDefaultLicenseUrl, Factory httpDataSourceFactory) + String defaultLicenseUrl, + boolean forceDefaultLicenseUrl, + HttpDataSource.Factory httpDataSourceFactory, + MediaSourceEventDispatcher eventDispatcher) throws UnsupportedDrmException { - return newWidevineInstance(defaultLicenseUrl, forceDefaultLicenseUrl, httpDataSourceFactory, - null); + return newWidevineInstance( + defaultLicenseUrl, + forceDefaultLicenseUrl, + httpDataSourceFactory, + /* optionalKeyRequestParameters= */ null, + eventDispatcher); } /** @@ -89,6 +103,8 @@ public final class OfflineLicenseHelper { * include their own license URL. * @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument * to {@link MediaDrm#getKeyRequest}. May be null. + * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related + * events. * @return A new instance which uses Widevine CDM. * @throws UnsupportedDrmException If the Widevine DRM scheme is unsupported or cannot be * instantiated. @@ -97,14 +113,16 @@ public final class OfflineLicenseHelper { public static OfflineLicenseHelper newWidevineInstance( String defaultLicenseUrl, boolean forceDefaultLicenseUrl, - Factory httpDataSourceFactory, - @Nullable Map optionalKeyRequestParameters) + HttpDataSource.Factory httpDataSourceFactory, + @Nullable Map optionalKeyRequestParameters, + MediaSourceEventDispatcher eventDispatcher) throws UnsupportedDrmException { return new OfflineLicenseHelper<>( C.WIDEVINE_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER, new HttpMediaDrmCallback(defaultLicenseUrl, forceDefaultLicenseUrl, httpDataSourceFactory), - optionalKeyRequestParameters); + optionalKeyRequestParameters, + eventDispatcher); } /** @@ -115,6 +133,8 @@ public final class OfflineLicenseHelper { * @param callback Performs key and provisioning requests. * @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument * to {@link MediaDrm#getKeyRequest}. May be null. + * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related + * events. * @see DefaultDrmSessionManager.Builder */ @SuppressWarnings("unchecked") @@ -122,7 +142,8 @@ public final class OfflineLicenseHelper { UUID uuid, ExoMediaDrm.Provider mediaDrmProvider, MediaDrmCallback callback, - @Nullable Map optionalKeyRequestParameters) { + @Nullable Map optionalKeyRequestParameters, + MediaSourceEventDispatcher eventDispatcher) { handlerThread = new HandlerThread("OfflineLicenseHelper"); handlerThread.start(); conditionVariable = new ConditionVariable(); @@ -158,6 +179,7 @@ public final class OfflineLicenseHelper { .setKeyRequestParameters(optionalKeyRequestParameters) .build(callback); drmSessionManager.addListener(new Handler(handlerThread.getLooper()), eventListener); + this.eventDispatcher = eventDispatcher; } /** @@ -216,7 +238,7 @@ public final class OfflineLicenseHelper { DrmSessionException error = drmSession.getError(); Pair licenseDurationRemainingSec = WidevineUtil.getLicenseDurationRemainingSec(drmSession); - drmSession.release(); + drmSession.release(eventDispatcher); drmSessionManager.release(); if (error != null) { if (error.getCause() instanceof KeysExpiredException) { @@ -242,7 +264,7 @@ public final class OfflineLicenseHelper { drmInitData); DrmSessionException error = drmSession.getError(); byte[] keySetId = drmSession.getOfflineLicenseKeySetId(); - drmSession.release(); + drmSession.release(eventDispatcher); drmSessionManager.release(); if (error != null) { throw error; @@ -254,8 +276,8 @@ public final class OfflineLicenseHelper { @Mode int licenseMode, @Nullable byte[] offlineLicenseKeySetId, DrmInitData drmInitData) { drmSessionManager.setMode(licenseMode, offlineLicenseKeySetId); conditionVariable.close(); - DrmSession drmSession = drmSessionManager.acquireSession(handlerThread.getLooper(), - drmInitData); + DrmSession drmSession = + drmSessionManager.acquireSession(handlerThread.getLooper(), eventDispatcher, drmInitData); // Block current thread until key loading is finished conditionVariable.block(); return drmSession; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java index b5f1e29b8f..c7387efd34 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java @@ -675,7 +675,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; return sampleQueues[i]; } } - SampleQueue trackOutput = new SampleQueue(allocator, drmSessionManager); + SampleQueue trackOutput = new SampleQueue(allocator, drmSessionManager, eventDispatcher); trackOutput.setUpstreamFormatChangeListener(this); @NullableType TrackId[] sampleQueueTrackIds = Arrays.copyOf(this.sampleQueueTrackIds, trackCount + 1); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index 306915e65e..ccbed81124 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -30,6 +30,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.DataReader; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; @@ -55,6 +56,7 @@ public class SampleQueue implements TrackOutput { private final SampleDataQueue sampleDataQueue; private final SampleExtrasHolder extrasHolder; private final DrmSessionManager drmSessionManager; + private final MediaSourceEventDispatcher eventDispatcher; @Nullable private UpstreamFormatChangedListener upstreamFormatChangeListener; @Nullable private Format downstreamFormat; @@ -94,10 +96,16 @@ public class SampleQueue implements TrackOutput { * @param allocator An {@link Allocator} from which allocations for sample data can be obtained. * @param drmSessionManager The {@link DrmSessionManager} to obtain {@link DrmSession DrmSessions} * from. The created instance does not take ownership of this {@link DrmSessionManager}. + * @param eventDispatcher A {@link MediaSourceEventDispatcher} to notify of events related to this + * SampleQueue. */ - public SampleQueue(Allocator allocator, DrmSessionManager drmSessionManager) { + public SampleQueue( + Allocator allocator, + DrmSessionManager drmSessionManager, + MediaSourceEventDispatcher eventDispatcher) { sampleDataQueue = new SampleDataQueue(allocator); this.drmSessionManager = drmSessionManager; + this.eventDispatcher = eventDispatcher; extrasHolder = new SampleExtrasHolder(); capacity = SAMPLE_CAPACITY_INCREMENT; sourceIds = new int[capacity]; @@ -647,7 +655,7 @@ public class SampleQueue implements TrackOutput { private void releaseDrmSessionReferences() { if (currentDrmSession != null) { - currentDrmSession.release(); + currentDrmSession.release(eventDispatcher); currentDrmSession = null; // Clear downstream format to avoid violating the assumption that downstreamFormat.drmInitData // != null implies currentSession != null @@ -791,13 +799,13 @@ public class SampleQueue implements TrackOutput { Looper playbackLooper = Assertions.checkNotNull(Looper.myLooper()); currentDrmSession = newDrmInitData != null - ? drmSessionManager.acquireSession(playbackLooper, newDrmInitData) + ? drmSessionManager.acquireSession(playbackLooper, eventDispatcher, newDrmInitData) : drmSessionManager.acquirePlaceholderSession( playbackLooper, MimeTypes.getTrackType(newFormat.sampleMimeType)); outputFormatHolder.drmSession = currentDrmSession; if (previousSession != null) { - previousSession.release(); + previousSession.release(eventDispatcher); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index 577d98792d..6d61cac9f3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -131,13 +131,14 @@ public class ChunkSampleStream implements SampleStream, S int[] trackTypes = new int[1 + embeddedTrackCount]; SampleQueue[] sampleQueues = new SampleQueue[1 + embeddedTrackCount]; - primarySampleQueue = new SampleQueue(allocator, drmSessionManager); + primarySampleQueue = new SampleQueue(allocator, drmSessionManager, eventDispatcher); trackTypes[0] = primaryTrackType; sampleQueues[0] = primarySampleQueue; for (int i = 0; i < embeddedTrackCount; i++) { SampleQueue sampleQueue = - new SampleQueue(allocator, DrmSessionManager.getDummyDrmSessionManager()); + new SampleQueue( + allocator, DrmSessionManager.getDummyDrmSessionManager(), eventDispatcher); embeddedSampleQueues[i] = sampleQueue; sampleQueues[i + 1] = sampleQueue; trackTypes[i + 1] = this.embeddedTrackTypes[i]; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/drm/OfflineLicenseHelperTest.java b/library/core/src/test/java/com/google/android/exoplayer2/drm/OfflineLicenseHelperTest.java index 599d137584..af0922fa4a 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/drm/OfflineLicenseHelperTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/drm/OfflineLicenseHelperTest.java @@ -25,6 +25,7 @@ import android.util.Pair; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import java.util.HashMap; import org.junit.After; import org.junit.Before; @@ -55,7 +56,8 @@ public class OfflineLicenseHelperTest { C.WIDEVINE_UUID, new ExoMediaDrm.AppManagedProvider<>(mediaDrm), mediaDrmCallback, - null); + /* optionalKeyRequestParameters= */ null, + new MediaSourceEventDispatcher()); } @After diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java index 6d03bc674c..f9eb243524 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java @@ -40,6 +40,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.DefaultAllocator; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.IOException; import java.util.Arrays; @@ -125,6 +126,7 @@ public final class SampleQueueTest { private Allocator allocator; private DrmSessionManager mockDrmSessionManager; private DrmSession mockDrmSession; + private MediaSourceEventDispatcher eventDispatcher; private SampleQueue sampleQueue; private FormatHolder formatHolder; private DecoderInputBuffer inputBuffer; @@ -136,9 +138,11 @@ public final class SampleQueueTest { mockDrmSessionManager = (DrmSessionManager) Mockito.mock(DrmSessionManager.class); mockDrmSession = (DrmSession) Mockito.mock(DrmSession.class); - when(mockDrmSessionManager.acquireSession(ArgumentMatchers.any(), ArgumentMatchers.any())) + when(mockDrmSessionManager.acquireSession( + ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())) .thenReturn(mockDrmSession); - sampleQueue = new SampleQueue(allocator, mockDrmSessionManager); + eventDispatcher = new MediaSourceEventDispatcher(); + sampleQueue = new SampleQueue(allocator, mockDrmSessionManager, eventDispatcher); formatHolder = new FormatHolder(); inputBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL); } @@ -355,7 +359,7 @@ public final class SampleQueueTest { public void isReadyReturnsTrueForClearSampleAndPlayClearSamplesWithoutKeysIsTrue() { when(mockDrmSession.playClearSamplesWithoutKeys()).thenReturn(true); // We recreate the queue to ensure the mock DRM session manager flags are taken into account. - sampleQueue = new SampleQueue(allocator, mockDrmSessionManager); + sampleQueue = new SampleQueue(allocator, mockDrmSessionManager, eventDispatcher); writeTestDataWithEncryptedSections(); assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isTrue(); } @@ -535,7 +539,7 @@ public final class SampleQueueTest { public void allowPlayClearSamplesWithoutKeysReadsClearSamples() { when(mockDrmSession.playClearSamplesWithoutKeys()).thenReturn(true); // We recreate the queue to ensure the mock DRM session manager flags are taken into account. - sampleQueue = new SampleQueue(allocator, mockDrmSessionManager); + sampleQueue = new SampleQueue(allocator, mockDrmSessionManager, eventDispatcher); when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED); writeTestDataWithEncryptedSections(); @@ -925,7 +929,7 @@ public final class SampleQueueTest { public void adjustUpstreamFormat() { String label = "label"; sampleQueue = - new SampleQueue(allocator, mockDrmSessionManager) { + new SampleQueue(allocator, mockDrmSessionManager, eventDispatcher) { @Override public Format getAdjustedUpstreamFormat(Format format) { return super.getAdjustedUpstreamFormat(copyWithLabel(format, label)); @@ -941,7 +945,7 @@ public final class SampleQueueTest { public void invalidateUpstreamFormatAdjustment() { AtomicReference label = new AtomicReference<>("label1"); sampleQueue = - new SampleQueue(allocator, mockDrmSessionManager) { + new SampleQueue(allocator, mockDrmSessionManager, eventDispatcher) { @Override public Format getAdjustedUpstreamFormat(Format format) { return super.getAdjustedUpstreamFormat(copyWithLabel(format, label.get())); diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java index b6cbcf6c82..504b2f4c27 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java @@ -35,6 +35,7 @@ import com.google.android.exoplayer2.source.chunk.Chunk; import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.DataReader; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; import java.io.IOException; @@ -284,7 +285,11 @@ public final class PlayerEmsgHandler implements Handler.Callback { private final MetadataInputBuffer buffer; /* package */ PlayerTrackEmsgHandler(Allocator allocator) { - this.sampleQueue = new SampleQueue(allocator, DrmSessionManager.getDummyDrmSessionManager()); + this.sampleQueue = + new SampleQueue( + allocator, + DrmSessionManager.getDummyDrmSessionManager(), + new MediaSourceEventDispatcher()); formatHolder = new FormatHolder(); buffer = new MetadataInputBuffer(); } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index d349927ee7..3a717ec2cd 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -53,6 +53,7 @@ import com.google.android.exoplayer2.upstream.Loader; import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; @@ -907,7 +908,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; boolean isAudioVideo = type == C.TRACK_TYPE_AUDIO || type == C.TRACK_TYPE_VIDEO; FormatAdjustingSampleQueue trackOutput = - new FormatAdjustingSampleQueue(allocator, drmSessionManager, overridingDrmInitData); + new FormatAdjustingSampleQueue( + allocator, drmSessionManager, eventDispatcher, overridingDrmInitData); if (isAudioVideo) { trackOutput.setDrmInitData(drmInitData); } @@ -1348,8 +1350,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; public FormatAdjustingSampleQueue( Allocator allocator, DrmSessionManager drmSessionManager, + MediaSourceEventDispatcher eventDispatcher, Map overridingDrmInitData) { - super(allocator, drmSessionManager); + super(allocator, drmSessionManager, eventDispatcher); this.overridingDrmInitData = overridingDrmInitData; } diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java index d7b66d4021..ae08669936 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java @@ -35,6 +35,7 @@ import com.google.android.exoplayer2.testutil.ActionSchedule; import com.google.android.exoplayer2.testutil.HostActivity; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; +import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import java.io.IOException; @@ -75,8 +76,9 @@ public final class DashWidevineOfflineTest { String widevineLicenseUrl = DashTestData.getWidevineLicenseUrl(true, useL1Widevine); httpDataSourceFactory = new DefaultHttpDataSourceFactory(USER_AGENT); if (Util.SDK_INT >= 18) { - offlineLicenseHelper = OfflineLicenseHelper.newWidevineInstance(widevineLicenseUrl, - httpDataSourceFactory); + offlineLicenseHelper = + OfflineLicenseHelper.newWidevineInstance( + widevineLicenseUrl, httpDataSourceFactory, new MediaSourceEventDispatcher()); } }