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
This commit is contained in:
olly 2017-09-14 10:34:30 -07:00 committed by Oliver Woodman
parent 58293abc11
commit a479afff5f

View File

@ -98,21 +98,22 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
/** Releases an existing offline license. */ /** Releases an existing offline license. */
public static final int MODE_RELEASE = 3; public static final int MODE_RELEASE = 3;
private final UUID uuid;
private final ExoMediaDrm<T> mediaDrm;
private final MediaDrmCallback callback;
private final HashMap<String, String> optionalKeyRequestParameters;
private final Handler eventHandler; private final Handler eventHandler;
private final EventListener eventListener; private final EventListener eventListener;
private final ExoMediaDrm<T> mediaDrm;
private final HashMap<String, String> optionalKeyRequestParameters;
private final MediaDrmCallback callback;
private final UUID uuid;
private final boolean multiSession; private final boolean multiSession;
private final List<DefaultDrmSession<T>> sessions;
private final AtomicBoolean provisioningInProgress;
private Looper playbackLooper; private Looper playbackLooper;
private int mode; private int mode;
private byte[] offlineLicenseKeySetId; private byte[] offlineLicenseKeySetId;
private final List<DefaultDrmSession<T>> sessions; /* package */ volatile MediaDrmHandler mediaDrmHandler;
private final AtomicBoolean provisioningInProgress;
/* package */ MediaDrmHandler mediaDrmHandler;
/** /**
* Instantiates a new instance using the Widevine scheme. * Instantiates a new instance using the Widevine scheme.
@ -226,6 +227,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
if (multiSession) { if (multiSession) {
mediaDrm.setPropertyString("sessionSharing", "enable"); mediaDrm.setPropertyString("sessionSharing", "enable");
} }
mediaDrm.setOnEventListener(new MediaDrmEventListener());
} }
/** /**
@ -334,8 +336,9 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
Assertions.checkState(this.playbackLooper == null || this.playbackLooper == playbackLooper); Assertions.checkState(this.playbackLooper == null || this.playbackLooper == playbackLooper);
if (sessions.isEmpty()) { if (sessions.isEmpty()) {
this.playbackLooper = playbackLooper; this.playbackLooper = playbackLooper;
if (mediaDrmHandler == null) {
mediaDrmHandler = new MediaDrmHandler(playbackLooper); mediaDrmHandler = new MediaDrmHandler(playbackLooper);
mediaDrm.setOnEventListener(new MediaDrmEventListener()); }
} }
DefaultDrmSession<T> session = null; DefaultDrmSession<T> session = null;
@ -383,13 +386,6 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
if (drmSession.release()) { if (drmSession.release()) {
sessions.remove(drmSession); sessions.remove(drmSession);
} }
if (sessions.isEmpty()) {
mediaDrm.setOnEventListener(null);
mediaDrmHandler.removeCallbacksAndMessages(null);
mediaDrmHandler = null;
playbackLooper = null;
}
} }
@Override @Override