Don't require playback Looper to build DRM session manager.

This is required because in V2 we'll be instantiating DRM
session managers before the ExoPlayer instance (and hence
we wont have the Looper). This logic will be further cleaned
up in later CLs that overhaul DrmSessionManager in more
depth.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=122453765
This commit is contained in:
olly 2016-05-16 13:46:34 -07:00 committed by Oliver Woodman
parent 537f193c88
commit a43144decf
6 changed files with 46 additions and 60 deletions

View File

@ -224,13 +224,6 @@ public interface ExoPlayer {
*/ */
long UNKNOWN_TIME = -1; long UNKNOWN_TIME = -1;
/**
* Gets the {@link Looper} associated with the playback thread.
*
* @return The {@link Looper} associated with the playback thread.
*/
Looper getPlaybackLooper();
/** /**
* Register a listener to receive events from the player. The listener's methods will be invoked * Register a listener to receive events from the player. The listener's methods will be invoked
* on the thread that was used to construct the player. * on the thread that was used to construct the player.

View File

@ -70,11 +70,6 @@ import java.util.concurrent.CopyOnWriteArraySet;
playWhenReady, eventHandler); playWhenReady, eventHandler);
} }
@Override
public Looper getPlaybackLooper() {
return internalPlayer.getPlaybackLooper();
}
@Override @Override
public void addListener(Listener listener) { public void addListener(Listener listener) {
listeners.add(listener); listeners.add(listener);

View File

@ -23,7 +23,6 @@ import com.google.android.exoplayer.util.Util;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.Process; import android.os.Process;
import android.os.SystemClock; import android.os.SystemClock;
@ -121,10 +120,6 @@ import java.util.concurrent.atomic.AtomicInteger;
handler = new Handler(internalPlaybackThread.getLooper(), this); handler = new Handler(internalPlaybackThread.getLooper(), this);
} }
public Looper getPlaybackLooper() {
return internalPlaybackThread.getLooper();
}
public long getCurrentPosition() { public long getCurrentPosition() {
return pendingSeekCount.get() > 0 ? lastSeekPositionMs : (positionUs / 1000); return pendingSeekCount.get() > 0 ? lastSeekPositionMs : (positionUs / 1000);
} }

View File

@ -28,6 +28,7 @@ import android.media.MediaCodec.CodecException;
import android.media.MediaCodec.CryptoException; import android.media.MediaCodec.CryptoException;
import android.media.MediaCrypto; import android.media.MediaCrypto;
import android.os.Handler; import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock; import android.os.SystemClock;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -290,7 +291,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
new IllegalStateException("Media requires a DrmSessionManager"), getIndex()); new IllegalStateException("Media requires a DrmSessionManager"), getIndex());
} }
if (!openedDrmSession) { if (!openedDrmSession) {
drmSessionManager.open(format.drmInitData); drmSessionManager.open(Looper.myLooper(), format.drmInitData);
openedDrmSession = true; openedDrmSession = true;
} }
int drmSessionState = drmSessionManager.getState(); int drmSessionState = drmSessionManager.getState();

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer.drm;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.media.MediaCrypto; import android.media.MediaCrypto;
import android.os.Looper;
/** /**
* Manages a DRM session. * Manages a DRM session.
@ -33,8 +34,8 @@ public interface DrmSessionManager {
*/ */
int STATE_CLOSED = 1; int STATE_CLOSED = 1;
/** /**
* The session is being opened (i.e. {@link #open(DrmInitData)} has been called, but the session * The session is being opened (i.e. {@link #open(Looper, DrmInitData)} has been called, but the
* is not yet open). * session is not yet open).
*/ */
int STATE_OPENING = 2; int STATE_OPENING = 2;
/** /**
@ -49,9 +50,10 @@ public interface DrmSessionManager {
/** /**
* Opens the session, possibly asynchronously. * Opens the session, possibly asynchronously.
* *
* @param playbackLooper The looper associated with the media playback thread.
* @param drmInitData DRM initialization data. * @param drmInitData DRM initialization data.
*/ */
void open(DrmInitData drmInitData); void open(Looper playbackLooper, DrmInitData drmInitData);
/** /**
* Closes the session. * Closes the session.

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer.drm;
import com.google.android.exoplayer.C; import com.google.android.exoplayer.C;
import com.google.android.exoplayer.drm.DrmInitData.SchemeData; import com.google.android.exoplayer.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer.extractor.mp4.PsshAtomUtil; import com.google.android.exoplayer.extractor.mp4.PsshAtomUtil;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.Util; import com.google.android.exoplayer.util.Util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@ -79,11 +80,13 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
private final MediaDrm mediaDrm; private final MediaDrm mediaDrm;
private final HashMap<String, String> optionalKeyRequestParameters; private final HashMap<String, String> optionalKeyRequestParameters;
/* package */ final MediaDrmHandler mediaDrmHandler;
/* package */ final MediaDrmCallback callback; /* package */ final MediaDrmCallback callback;
/* package */ final PostResponseHandler postResponseHandler;
/* package */ final UUID uuid; /* package */ final UUID uuid;
/* package */ MediaDrmHandler mediaDrmHandler;
/* package */ PostResponseHandler postResponseHandler;
private Looper playbackLooper;
private HandlerThread requestHandlerThread; private HandlerThread requestHandlerThread;
private Handler postRequestHandler; private Handler postRequestHandler;
@ -98,8 +101,6 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
/** /**
* Instantiates a new instance using the Widevine scheme. * Instantiates a new instance using the Widevine scheme.
* *
* @param playbackLooper The looper associated with the media playback thread. Should usually be
* obtained using {@link com.google.android.exoplayer.ExoPlayer#getPlaybackLooper()}.
* @param callback Performs key and provisioning requests. * @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument * @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null. * to {@link MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
@ -108,11 +109,11 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported. * @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/ */
public static StreamingDrmSessionManager newWidevineInstance(Looper playbackLooper, public static StreamingDrmSessionManager newWidevineInstance(MediaDrmCallback callback,
MediaDrmCallback callback, HashMap<String, String> optionalKeyRequestParameters, HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler,
Handler eventHandler, EventListener eventListener) throws UnsupportedDrmException { EventListener eventListener) throws UnsupportedDrmException {
return new StreamingDrmSessionManager(C.WIDEVINE_UUID, playbackLooper, callback, return new StreamingDrmSessionManager(C.WIDEVINE_UUID, callback, optionalKeyRequestParameters,
optionalKeyRequestParameters, eventHandler, eventListener); eventHandler, eventListener);
} }
/** /**
@ -121,8 +122,6 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
* Note that PlayReady is unsupported by most Android devices, with the exception of Android TV * Note that PlayReady is unsupported by most Android devices, with the exception of Android TV
* devices, which do provide support. * devices, which do provide support.
* *
* @param playbackLooper The looper associated with the media playback thread. Should usually be
* obtained using {@link com.google.android.exoplayer.ExoPlayer#getPlaybackLooper()}.
* @param callback Performs key and provisioning requests. * @param callback Performs key and provisioning requests.
* @param customData Optional custom data to include in requests generated by the instance. * @param customData Optional custom data to include in requests generated by the instance.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
@ -130,9 +129,9 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported. * @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/ */
public static StreamingDrmSessionManager newPlayReadyInstance(Looper playbackLooper, public static StreamingDrmSessionManager newPlayReadyInstance(MediaDrmCallback callback,
MediaDrmCallback callback, String customData, Handler eventHandler, String customData, Handler eventHandler, EventListener eventListener)
EventListener eventListener) throws UnsupportedDrmException { throws UnsupportedDrmException {
HashMap<String, String> optionalKeyRequestParameters; HashMap<String, String> optionalKeyRequestParameters;
if (!TextUtils.isEmpty(customData)) { if (!TextUtils.isEmpty(customData)) {
optionalKeyRequestParameters = new HashMap<>(); optionalKeyRequestParameters = new HashMap<>();
@ -140,14 +139,12 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
} else { } else {
optionalKeyRequestParameters = null; optionalKeyRequestParameters = null;
} }
return new StreamingDrmSessionManager(C.PLAYREADY_UUID, playbackLooper, callback, return new StreamingDrmSessionManager(C.PLAYREADY_UUID, callback, optionalKeyRequestParameters,
optionalKeyRequestParameters, eventHandler, eventListener); eventHandler, eventListener);
} }
/** /**
* @param uuid The UUID of the drm scheme. * @param uuid The UUID of the drm scheme.
* @param playbackLooper The looper associated with the media playback thread. Should usually be
* obtained using {@link com.google.android.exoplayer.ExoPlayer#getPlaybackLooper()}.
* @param callback Performs key and provisioning requests. * @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument * @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null. * to {@link MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
@ -156,7 +153,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported. * @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/ */
public StreamingDrmSessionManager(UUID uuid, Looper playbackLooper, MediaDrmCallback callback, public StreamingDrmSessionManager(UUID uuid, MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler, HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler,
EventListener eventListener) throws UnsupportedDrmException { EventListener eventListener) throws UnsupportedDrmException {
this.uuid = uuid; this.uuid = uuid;
@ -172,8 +169,6 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
throw new UnsupportedDrmException(UnsupportedDrmException.REASON_INSTANTIATION_ERROR, e); throw new UnsupportedDrmException(UnsupportedDrmException.REASON_INSTANTIATION_ERROR, e);
} }
mediaDrm.setOnEventListener(new MediaDrmEventListener()); mediaDrm.setOnEventListener(new MediaDrmEventListener());
mediaDrmHandler = new MediaDrmHandler(playbackLooper);
postResponseHandler = new PostResponseHandler(playbackLooper);
state = STATE_CLOSED; state = STATE_CLOSED;
} }
@ -252,29 +247,34 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
} }
@Override @Override
public void open(DrmInitData drmInitData) { public void open(Looper playbackLooper, DrmInitData drmInitData) {
Assertions.checkState(this.playbackLooper == null || this.playbackLooper == playbackLooper);
if (++openCount != 1) { if (++openCount != 1) {
return; return;
} }
if (postRequestHandler == null) {
requestHandlerThread = new HandlerThread("DrmRequestHandler"); if (this.playbackLooper == null) {
requestHandlerThread.start(); this.playbackLooper = playbackLooper;
postRequestHandler = new PostRequestHandler(requestHandlerThread.getLooper()); mediaDrmHandler = new MediaDrmHandler(playbackLooper);
postResponseHandler = new PostResponseHandler(playbackLooper);
} }
requestHandlerThread = new HandlerThread("DrmRequestHandler");
requestHandlerThread.start();
postRequestHandler = new PostRequestHandler(requestHandlerThread.getLooper());
schemeData = drmInitData.get(uuid);
if (schemeData == null) { if (schemeData == null) {
schemeData = drmInitData.get(uuid); onError(new IllegalStateException("Media does not support uuid: " + uuid));
if (schemeData == null) { return;
onError(new IllegalStateException("Media does not support uuid: " + uuid)); }
return; if (Util.SDK_INT < 21) {
} // Prior to L the Widevine CDM required data to be extracted from the PSSH atom.
if (Util.SDK_INT < 21) { byte[] psshData = PsshAtomUtil.parseSchemeSpecificData(schemeData.data, C.WIDEVINE_UUID);
// Prior to L the Widevine CDM required data to be extracted from the PSSH atom. if (psshData == null) {
byte[] psshData = PsshAtomUtil.parseSchemeSpecificData(schemeData.data, C.WIDEVINE_UUID); // Extraction failed. schemeData isn't a Widevine PSSH atom, so leave it unchanged.
if (psshData == null) { } else {
// Extraction failed. schemeData isn't a Widevine PSSH atom, so leave it unchanged. schemeData = new SchemeData(C.WIDEVINE_UUID, schemeData.mimeType, psshData);
} else {
schemeData = new SchemeData(C.WIDEVINE_UUID, schemeData.mimeType, psshData);
}
} }
} }
state = STATE_OPENING; state = STATE_OPENING;