From 3480a27994ef9e06bd7574bad4656eb8c7677971 Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 31 Mar 2023 09:56:59 +0100 Subject: [PATCH] Add warning logs if `DefaultDrmSessionManager` is used on wrong thread Issue: google/ExoPlayer#11008 PiperOrigin-RevId: 520864579 (cherry picked from commit 7ca966842185dd6f07563f28058d78537b916731) --- .../exoplayer/drm/DefaultDrmSession.java | 31 +++++++++++++++++-- .../drm/DefaultDrmSessionManager.java | 22 +++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/DefaultDrmSession.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/DefaultDrmSession.java index c64eb57dabc..b04c5b1cd88 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/DefaultDrmSession.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/DefaultDrmSession.java @@ -136,9 +136,10 @@ public interface ReferenceCountListener { private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; private final PlayerId playerId; - /* package */ final MediaDrmCallback callback; - /* package */ final UUID uuid; - /* package */ final ResponseHandler responseHandler; + private final MediaDrmCallback callback; + private final UUID uuid; + private final Looper playbackLooper; + private final ResponseHandler responseHandler; private @DrmSession.State int state; private int referenceCount; @@ -209,10 +210,12 @@ public DefaultDrmSession( this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.playerId = playerId; state = STATE_OPENING; + this.playbackLooper = playbackLooper; responseHandler = new ResponseHandler(playbackLooper); } public boolean hasSessionId(byte[] sessionId) { + verifyPlaybackThread(); return Arrays.equals(this.sessionId, sessionId); } @@ -255,50 +258,59 @@ public void onProvisionError(Exception error, boolean thrownByExoMediaDrm) { @Override public final @DrmSession.State int getState() { + verifyPlaybackThread(); return state; } @Override public boolean playClearSamplesWithoutKeys() { + verifyPlaybackThread(); return playClearSamplesWithoutKeys; } @Override @Nullable public final DrmSessionException getError() { + verifyPlaybackThread(); return state == STATE_ERROR ? lastException : null; } @Override public final UUID getSchemeUuid() { + verifyPlaybackThread(); return uuid; } @Override @Nullable public final CryptoConfig getCryptoConfig() { + verifyPlaybackThread(); return cryptoConfig; } @Override @Nullable public Map queryKeyStatus() { + verifyPlaybackThread(); return sessionId == null ? null : mediaDrm.queryKeyStatus(sessionId); } @Override @Nullable public byte[] getOfflineLicenseKeySetId() { + verifyPlaybackThread(); return offlineLicenseKeySetId; } @Override public boolean requiresSecureDecoder(String mimeType) { + verifyPlaybackThread(); return mediaDrm.requiresSecureDecoder(checkStateNotNull(sessionId), mimeType); } @Override public void acquire(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) { + verifyPlaybackThread(); if (referenceCount < 0) { Log.e(TAG, "Session reference count less than zero: " + referenceCount); referenceCount = 0; @@ -326,6 +338,7 @@ && isOpen() @Override public void release(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) { + verifyPlaybackThread(); if (referenceCount <= 0) { Log.e(TAG, "release() called on a session that's already fully released."); return; @@ -561,6 +574,18 @@ private void dispatchEvent(Consumer eve } } + private void verifyPlaybackThread() { + if (Thread.currentThread() != playbackLooper.getThread()) { + Log.w( + TAG, + "DefaultDrmSession accessed on the wrong thread.\nCurrent thread: " + + Thread.currentThread().getName() + + "\nExpected thread: " + + playbackLooper.getThread().getName(), + new IllegalStateException()); + } + } + // Internal classes. @SuppressLint("HandlerLeak") diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/DefaultDrmSessionManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/DefaultDrmSessionManager.java index 9a345ffff73..05ab52a0395 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/DefaultDrmSessionManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/DefaultDrmSessionManager.java @@ -471,6 +471,7 @@ public void setMode(@Mode int mode, @Nullable byte[] offlineLicenseKeySetId) { @Override public final void prepare() { + verifyPlaybackThread(/* allowBeforeSetPlayer= */ true); if (prepareCallsCount++ != 0) { return; } @@ -487,6 +488,7 @@ public final void prepare() { @Override public final void release() { + verifyPlaybackThread(/* allowBeforeSetPlayer= */ true); if (--prepareCallsCount != 0) { return; } @@ -513,6 +515,7 @@ public void setPlayer(Looper playbackLooper, PlayerId playerId) { @Override public DrmSessionReference preacquireSession( @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher, Format format) { + // Don't verify the playback thread, preacquireSession can be called from any thread. checkState(prepareCallsCount > 0); checkStateNotNull(playbackLooper); PreacquiredSessionReference preacquiredSessionReference = @@ -525,6 +528,7 @@ public DrmSessionReference preacquireSession( @Nullable public DrmSession acquireSession( @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher, Format format) { + verifyPlaybackThread(/* allowBeforeSetPlayer= */ false); checkState(prepareCallsCount > 0); checkStateNotNull(playbackLooper); return acquireSession( @@ -599,6 +603,7 @@ private DrmSession acquireSession( @Override public @C.CryptoType int getCryptoType(Format format) { + verifyPlaybackThread(/* allowBeforeSetPlayer= */ false); @C.CryptoType int cryptoType = checkNotNull(exoMediaDrm).getCryptoType(); if (format.drmInitData == null) { int trackType = MimeTypes.getTrackType(format.sampleMimeType); @@ -817,6 +822,23 @@ private void maybeReleaseMediaDrm() { } } + private void verifyPlaybackThread(boolean allowBeforeSetPlayer) { + if (allowBeforeSetPlayer && playbackLooper == null) { + Log.w( + TAG, + "DefaultDrmSessionManager accessed before setPlayer(), possibly on the wrong thread.", + new IllegalStateException()); + } else if (Thread.currentThread() != checkNotNull(playbackLooper).getThread()) { + Log.w( + TAG, + "DefaultDrmSessionManager accessed on the wrong thread.\nCurrent thread: " + + Thread.currentThread().getName() + + "\nExpected thread: " + + playbackLooper.getThread().getName(), + new IllegalStateException()); + } + } + /** * Extracts {@link SchemeData} instances suitable for the given DRM scheme {@link UUID}. *