From a479afff5f45f21810e0345f705fb07a14657ca8 Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 14 Sep 2017 10:34:30 -0700 Subject: [PATCH] Fix potential NPE/ThreadSafety issues with MediaDrm listener - MediaDrmEventListener.onEvent is typically called on the app's main thread. mediaDrmHandler is instantiated on the playback thread. Hence mediaDrmHandler should be volatile to ensure visibility. - Nulling mediaDrmHandler could result in a NPE in onEvent. Instantiate mediaDrmHandler (and don't null it again) to avoid this. MediaDrmHandler.handleMessage will correctly discard any events for sessions that are now closed. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=168707938 --- .../drm/DefaultDrmSessionManager.java | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) 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 029b41fde8..cff9f9da0f 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 @@ -98,21 +98,22 @@ public class DefaultDrmSessionManager implements DrmSe /** Releases an existing offline license. */ public static final int MODE_RELEASE = 3; + private final UUID uuid; + private final ExoMediaDrm mediaDrm; + private final MediaDrmCallback callback; + private final HashMap optionalKeyRequestParameters; private final Handler eventHandler; private final EventListener eventListener; - private final ExoMediaDrm mediaDrm; - private final HashMap optionalKeyRequestParameters; - private final MediaDrmCallback callback; - private final UUID uuid; private final boolean multiSession; + private final List> sessions; + private final AtomicBoolean provisioningInProgress; + private Looper playbackLooper; private int mode; private byte[] offlineLicenseKeySetId; - private final List> sessions; - private final AtomicBoolean provisioningInProgress; - /* package */ MediaDrmHandler mediaDrmHandler; + /* package */ volatile MediaDrmHandler mediaDrmHandler; /** * Instantiates a new instance using the Widevine scheme. @@ -226,6 +227,7 @@ public class DefaultDrmSessionManager implements DrmSe if (multiSession) { mediaDrm.setPropertyString("sessionSharing", "enable"); } + mediaDrm.setOnEventListener(new MediaDrmEventListener()); } /** @@ -334,8 +336,9 @@ public class DefaultDrmSessionManager implements DrmSe Assertions.checkState(this.playbackLooper == null || this.playbackLooper == playbackLooper); if (sessions.isEmpty()) { this.playbackLooper = playbackLooper; - mediaDrmHandler = new MediaDrmHandler(playbackLooper); - mediaDrm.setOnEventListener(new MediaDrmEventListener()); + if (mediaDrmHandler == null) { + mediaDrmHandler = new MediaDrmHandler(playbackLooper); + } } DefaultDrmSession session = null; @@ -383,13 +386,6 @@ public class DefaultDrmSessionManager implements DrmSe if (drmSession.release()) { sessions.remove(drmSession); } - - if (sessions.isEmpty()) { - mediaDrm.setOnEventListener(null); - mediaDrmHandler.removeCallbacksAndMessages(null); - mediaDrmHandler = null; - playbackLooper = null; - } } @Override