Support multiple DefaultDrmSessionManager listeners.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=190236842
This commit is contained in:
tonihei 2018-03-23 10:18:34 -07:00 committed by Oliver Woodman
parent 416e05f58c
commit 40947d52f0
8 changed files with 400 additions and 177 deletions

View File

@ -33,6 +33,7 @@
* Add release method to Cache interface. * Add release method to Cache interface.
* Prevent multiple instances of SimpleCache in the same folder. * Prevent multiple instances of SimpleCache in the same folder.
Previous instance must be released. Previous instance must be released.
* DRM: Allow multiple listeners for `DefaultDrmSessionManager`.
* Fix ANR issue on Redmi 4X and Redmi Note 4 * Fix ANR issue on Redmi 4X and Redmi Note 4
([#4006](https://github.com/google/ExoPlayer/issues/4006)). ([#4006](https://github.com/google/ExoPlayer/issues/4006)).
* Removed default renderer time offset of 60000000 from internal player. The * Removed default renderer time offset of 60000000 from internal player. The

View File

@ -432,8 +432,11 @@ public class PlayerActivity extends Activity
keyRequestPropertiesArray[i + 1]); keyRequestPropertiesArray[i + 1]);
} }
} }
return new DefaultDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), drmCallback, DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager =
null, mainHandler, eventLogger, multiSession); new DefaultDrmSessionManager<>(
uuid, FrameworkMediaDrm.newInstance(uuid), drmCallback, null, multiSession);
drmSessionManager.addListener(mainHandler, eventLogger);
return drmSessionManager;
} }
private void releasePlayer() { private void releasePlayer() {

View File

@ -25,6 +25,7 @@ import android.os.Message;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener.EventDispatcher;
import com.google.android.exoplayer2.drm.ExoMediaDrm.DefaultKeyRequest; import com.google.android.exoplayer2.drm.ExoMediaDrm.DefaultKeyRequest;
import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest; import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest;
import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest; import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest;
@ -80,8 +81,7 @@ import java.util.UUID;
private final String mimeType; private final String mimeType;
private final @DefaultDrmSessionManager.Mode int mode; private final @DefaultDrmSessionManager.Mode int mode;
private final HashMap<String, String> optionalKeyRequestParameters; private final HashMap<String, String> optionalKeyRequestParameters;
private final Handler eventHandler; private final EventDispatcher eventDispatcher;
private final DefaultDrmSessionManager.EventListener eventListener;
private final int initialDrmRequestRetryCount; private final int initialDrmRequestRetryCount;
/* package */ final MediaDrmCallback callback; /* package */ final MediaDrmCallback callback;
@ -109,17 +109,22 @@ import java.util.UUID;
* @param optionalKeyRequestParameters The optional key request parameters. * @param optionalKeyRequestParameters The optional key request parameters.
* @param callback The media DRM callback. * @param callback The media DRM callback.
* @param playbackLooper The playback looper. * @param playbackLooper The playback looper.
* @param eventHandler The handler to post listener events. * @param eventDispatcher The dispatcher for DRM session manager events.
* @param eventListener The DRM session manager event listener.
* @param initialDrmRequestRetryCount The number of times to retry for initial provisioning and * @param initialDrmRequestRetryCount The number of times to retry for initial provisioning and
* key request before reporting error. * key request before reporting error.
*/ */
public DefaultDrmSession(UUID uuid, ExoMediaDrm<T> mediaDrm, public DefaultDrmSession(
ProvisioningManager<T> provisioningManager, byte[] initData, String mimeType, UUID uuid,
@DefaultDrmSessionManager.Mode int mode, byte[] offlineLicenseKeySetId, ExoMediaDrm<T> mediaDrm,
HashMap<String, String> optionalKeyRequestParameters, MediaDrmCallback callback, ProvisioningManager<T> provisioningManager,
Looper playbackLooper, Handler eventHandler, byte[] initData,
DefaultDrmSessionManager.EventListener eventListener, String mimeType,
@DefaultDrmSessionManager.Mode int mode,
byte[] offlineLicenseKeySetId,
HashMap<String, String> optionalKeyRequestParameters,
MediaDrmCallback callback,
Looper playbackLooper,
EventDispatcher eventDispatcher,
int initialDrmRequestRetryCount) { int initialDrmRequestRetryCount) {
this.uuid = uuid; this.uuid = uuid;
this.provisioningManager = provisioningManager; this.provisioningManager = provisioningManager;
@ -129,9 +134,7 @@ import java.util.UUID;
this.optionalKeyRequestParameters = optionalKeyRequestParameters; this.optionalKeyRequestParameters = optionalKeyRequestParameters;
this.callback = callback; this.callback = callback;
this.initialDrmRequestRetryCount = initialDrmRequestRetryCount; this.initialDrmRequestRetryCount = initialDrmRequestRetryCount;
this.eventDispatcher = eventDispatcher;
this.eventHandler = eventHandler;
this.eventListener = eventListener;
state = STATE_OPENING; state = STATE_OPENING;
postResponseHandler = new PostResponseHandler(playbackLooper); postResponseHandler = new PostResponseHandler(playbackLooper);
@ -306,14 +309,7 @@ import java.util.UUID;
onError(new KeysExpiredException()); onError(new KeysExpiredException());
} else { } else {
state = STATE_OPENED_WITH_KEYS; state = STATE_OPENED_WITH_KEYS;
if (eventHandler != null && eventListener != null) { eventDispatcher.drmKeysRestored();
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onDrmKeysRestored();
}
});
}
} }
} }
break; break;
@ -391,14 +387,7 @@ import java.util.UUID;
} }
if (mode == DefaultDrmSessionManager.MODE_RELEASE) { if (mode == DefaultDrmSessionManager.MODE_RELEASE) {
mediaDrm.provideKeyResponse(offlineLicenseKeySetId, responseData); mediaDrm.provideKeyResponse(offlineLicenseKeySetId, responseData);
if (eventHandler != null && eventListener != null) { eventDispatcher.drmKeysRemoved();
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onDrmKeysRemoved();
}
});
}
} else { } else {
byte[] keySetId = mediaDrm.provideKeyResponse(sessionId, responseData); byte[] keySetId = mediaDrm.provideKeyResponse(sessionId, responseData);
if ((mode == DefaultDrmSessionManager.MODE_DOWNLOAD if ((mode == DefaultDrmSessionManager.MODE_DOWNLOAD
@ -407,14 +396,7 @@ import java.util.UUID;
offlineLicenseKeySetId = keySetId; offlineLicenseKeySetId = keySetId;
} }
state = STATE_OPENED_WITH_KEYS; state = STATE_OPENED_WITH_KEYS;
if (eventHandler != null && eventListener != null) { eventDispatcher.drmKeysLoaded();
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onDrmKeysLoaded();
}
});
}
} }
} catch (Exception e) { } catch (Exception e) {
onKeysError(e); onKeysError(e);
@ -438,14 +420,7 @@ import java.util.UUID;
private void onError(final Exception e) { private void onError(final Exception e) {
lastException = new DrmSessionException(e); lastException = new DrmSessionException(e);
if (eventHandler != null && eventListener != null) { eventDispatcher.drmSessionManagerError(e);
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onDrmSessionManagerError(e);
}
});
}
if (state != STATE_OPENED_WITH_KEYS) { if (state != STATE_OPENED_WITH_KEYS) {
state = STATE_ERROR; state = STATE_ERROR;
} }

View File

@ -0,0 +1,139 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.drm;
import android.os.Handler;
import com.google.android.exoplayer2.Player;
import java.util.concurrent.CopyOnWriteArrayList;
/** Listener of {@link DefaultDrmSessionManager} events. */
public interface DefaultDrmSessionEventListener {
/** Called each time keys are loaded. */
void onDrmKeysLoaded();
/**
* Called when a drm error occurs.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error and continue. Hence applications should
* <em>not</em> implement this method to display a user visible error or initiate an application
* level retry ({@link Player.EventListener#onPlayerError} is the appropriate place to implement
* such behavior). This method is called to provide the application with an opportunity to log the
* error if it wishes to do so.
*
* @param error The corresponding exception.
*/
void onDrmSessionManagerError(Exception error);
/** Called each time offline keys are restored. */
void onDrmKeysRestored();
/** Called each time offline keys are removed. */
void onDrmKeysRemoved();
/** Dispatches drm events to all registered listeners. */
final class EventDispatcher {
private final CopyOnWriteArrayList<HandlerAndListener> listeners;
/** Creates event dispatcher. */
public EventDispatcher() {
listeners = new CopyOnWriteArrayList<>();
}
/** Adds listener to event dispatcher. */
public void addListener(Handler handler, DefaultDrmSessionEventListener eventListener) {
listeners.add(new HandlerAndListener(handler, eventListener));
}
/** Removes listener from event dispatcher. */
public void removeListener(DefaultDrmSessionEventListener eventListener) {
for (HandlerAndListener handlerAndListener : listeners) {
if (handlerAndListener.listener == eventListener) {
listeners.remove(handlerAndListener);
}
}
}
/** Dispatches {@link DefaultDrmSessionEventListener#onDrmKeysLoaded()}. */
public void drmKeysLoaded() {
for (HandlerAndListener handlerAndListener : listeners) {
final DefaultDrmSessionEventListener listener = handlerAndListener.listener;
handlerAndListener.handler.post(
new Runnable() {
@Override
public void run() {
listener.onDrmKeysLoaded();
}
});
}
}
/** Dispatches {@link DefaultDrmSessionEventListener#onDrmSessionManagerError(Exception)}. */
public void drmSessionManagerError(final Exception e) {
for (HandlerAndListener handlerAndListener : listeners) {
final DefaultDrmSessionEventListener listener = handlerAndListener.listener;
handlerAndListener.handler.post(
new Runnable() {
@Override
public void run() {
listener.onDrmSessionManagerError(e);
}
});
}
}
/** Dispatches {@link DefaultDrmSessionEventListener#onDrmKeysRestored()}. */
public void drmKeysRestored() {
for (HandlerAndListener handlerAndListener : listeners) {
final DefaultDrmSessionEventListener listener = handlerAndListener.listener;
handlerAndListener.handler.post(
new Runnable() {
@Override
public void run() {
listener.onDrmKeysRestored();
}
});
}
}
/** Dispatches {@link DefaultDrmSessionEventListener#onDrmKeysRemoved()}. */
public void drmKeysRemoved() {
for (HandlerAndListener handlerAndListener : listeners) {
final DefaultDrmSessionEventListener listener = handlerAndListener.listener;
handlerAndListener.handler.post(
new Runnable() {
@Override
public void run() {
listener.onDrmKeysRemoved();
}
});
}
}
private static final class HandlerAndListener {
public final Handler handler;
public final DefaultDrmSessionEventListener listener;
public HandlerAndListener(Handler handler, DefaultDrmSessionEventListener eventListener) {
this.handler = handler;
this.listener = eventListener;
}
}
}
}

View File

@ -25,8 +25,8 @@ import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.drm.DefaultDrmSession.ProvisioningManager; import com.google.android.exoplayer2.drm.DefaultDrmSession.ProvisioningManager;
import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener.EventDispatcher;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener; import com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener;
@ -48,41 +48,9 @@ import java.util.UUID;
public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSessionManager<T>, public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSessionManager<T>,
ProvisioningManager<T> { ProvisioningManager<T> {
/** /** @deprecated Use {@link DefaultDrmSessionEventListener}. */
* Listener of {@link DefaultDrmSessionManager} events. @Deprecated
*/ public interface EventListener extends DefaultDrmSessionEventListener {}
public interface EventListener {
/**
* Called each time keys are loaded.
*/
void onDrmKeysLoaded();
/**
* Called when a drm error occurs.
* <p>
* This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error and continue. Hence applications should
* <em>not</em> implement this method to display a user visible error or initiate an application
* level retry ({@link Player.EventListener#onPlayerError} is the appropriate place to implement
* such behavior). This method is called to provide the application with an opportunity to log
* the error if it wishes to do so.
*
* @param e The corresponding exception.
*/
void onDrmSessionManagerError(Exception e);
/**
* Called each time offline keys are restored.
*/
void onDrmKeysRestored();
/**
* Called each time offline keys are removed.
*/
void onDrmKeysRemoved();
}
/** /**
* Signals that the {@link DrmInitData} passed to {@link #acquireSession} does not contain does * Signals that the {@link DrmInitData} passed to {@link #acquireSession} does not contain does
@ -127,8 +95,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
private final ExoMediaDrm<T> mediaDrm; private final ExoMediaDrm<T> mediaDrm;
private final MediaDrmCallback callback; private final MediaDrmCallback callback;
private final HashMap<String, String> optionalKeyRequestParameters; private final HashMap<String, String> optionalKeyRequestParameters;
private final Handler eventHandler; private final EventDispatcher eventDispatcher;
private final EventListener eventListener;
private final boolean multiSession; private final boolean multiSession;
private final int initialDrmRequestRetryCount; private final int initialDrmRequestRetryCount;
@ -141,40 +108,66 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
/* package */ volatile MediaDrmHandler mediaDrmHandler; /* package */ volatile MediaDrmHandler mediaDrmHandler;
/**
* @deprecated Use {@link #newWidevineInstance(MediaDrmCallback, HashMap)} and {@link
* #addListener(Handler, DefaultDrmSessionEventListener)}.
*/
@Deprecated
public static DefaultDrmSessionManager<FrameworkMediaCrypto> newWidevineInstance(
MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters,
Handler eventHandler,
DefaultDrmSessionEventListener eventListener)
throws UnsupportedDrmException {
DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager =
newWidevineInstance(callback, optionalKeyRequestParameters);
drmSessionManager.addListener(eventHandler, eventListener);
return drmSessionManager;
}
/** /**
* Instantiates a new instance using the Widevine scheme. * Instantiates a new instance using the Widevine scheme.
* *
* @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 ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null. * to {@link ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. 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 DefaultDrmSessionManager<FrameworkMediaCrypto> newWidevineInstance( public static DefaultDrmSessionManager<FrameworkMediaCrypto> newWidevineInstance(
MediaDrmCallback callback, HashMap<String, String> optionalKeyRequestParameters, MediaDrmCallback callback, HashMap<String, String> optionalKeyRequestParameters)
Handler eventHandler, EventListener eventListener) throws UnsupportedDrmException { throws UnsupportedDrmException {
return newFrameworkInstance(C.WIDEVINE_UUID, callback, optionalKeyRequestParameters, return newFrameworkInstance(C.WIDEVINE_UUID, callback, optionalKeyRequestParameters);
eventHandler, eventListener); }
/**
* @deprecated Use {@link #newPlayReadyInstance(MediaDrmCallback, String)} and {@link
* #addListener(Handler, DefaultDrmSessionEventListener)}.
*/
@Deprecated
public static DefaultDrmSessionManager<FrameworkMediaCrypto> newPlayReadyInstance(
MediaDrmCallback callback,
String customData,
Handler eventHandler,
DefaultDrmSessionEventListener eventListener)
throws UnsupportedDrmException {
DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager =
newPlayReadyInstance(callback, customData);
drmSessionManager.addListener(eventHandler, eventListener);
return drmSessionManager;
} }
/** /**
* Instantiates a new instance using the PlayReady scheme. * Instantiates a new instance using the PlayReady scheme.
* <p> *
* Note that PlayReady is unsupported by most Android devices, with the exception of Android TV * <p>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 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
* 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 DefaultDrmSessionManager<FrameworkMediaCrypto> newPlayReadyInstance( public static DefaultDrmSessionManager<FrameworkMediaCrypto> newPlayReadyInstance(
MediaDrmCallback callback, String customData, Handler eventHandler, MediaDrmCallback callback, String customData) throws UnsupportedDrmException {
EventListener eventListener) throws UnsupportedDrmException {
HashMap<String, String> optionalKeyRequestParameters; HashMap<String, String> optionalKeyRequestParameters;
if (!TextUtils.isEmpty(customData)) { if (!TextUtils.isEmpty(customData)) {
optionalKeyRequestParameters = new HashMap<>(); optionalKeyRequestParameters = new HashMap<>();
@ -182,8 +175,25 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
} else { } else {
optionalKeyRequestParameters = null; optionalKeyRequestParameters = null;
} }
return newFrameworkInstance(C.PLAYREADY_UUID, callback, optionalKeyRequestParameters, return newFrameworkInstance(C.PLAYREADY_UUID, callback, optionalKeyRequestParameters);
eventHandler, eventListener); }
/**
* @deprecated Use {@link #newFrameworkInstance(UUID, MediaDrmCallback, HashMap)} and {@link
* #addListener(Handler, DefaultDrmSessionEventListener)}.
*/
@Deprecated
public static DefaultDrmSessionManager<FrameworkMediaCrypto> newFrameworkInstance(
UUID uuid,
MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters,
Handler eventHandler,
DefaultDrmSessionEventListener eventListener)
throws UnsupportedDrmException {
DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager =
newFrameworkInstance(uuid, callback, optionalKeyRequestParameters);
drmSessionManager.addListener(eventHandler, eventListener);
return drmSessionManager;
} }
/** /**
@ -193,34 +203,72 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
* @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 ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null. * to {@link ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. 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 DefaultDrmSessionManager<FrameworkMediaCrypto> newFrameworkInstance( public static DefaultDrmSessionManager<FrameworkMediaCrypto> newFrameworkInstance(
UUID uuid, MediaDrmCallback callback, HashMap<String, String> optionalKeyRequestParameters, UUID uuid, MediaDrmCallback callback, HashMap<String, String> optionalKeyRequestParameters)
Handler eventHandler, EventListener eventListener) throws UnsupportedDrmException { throws UnsupportedDrmException {
return new DefaultDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), callback, return new DefaultDrmSessionManager<>(
optionalKeyRequestParameters, eventHandler, eventListener, false, uuid,
FrameworkMediaDrm.newInstance(uuid),
callback,
optionalKeyRequestParameters,
/* multiSession= */ false,
INITIAL_DRM_REQUEST_RETRY_COUNT); INITIAL_DRM_REQUEST_RETRY_COUNT);
} }
/** /**
* @param uuid The UUID of the drm scheme. * @deprecated Use {@link #DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap)}
* @param mediaDrm An underlying {@link ExoMediaDrm} for use by the manager. * and {@link #addListener(Handler, DefaultDrmSessionEventListener)}.
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. 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.
*/ */
public DefaultDrmSessionManager(UUID uuid, ExoMediaDrm<T> mediaDrm, MediaDrmCallback callback, @Deprecated
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler, public DefaultDrmSessionManager(
EventListener eventListener) { UUID uuid,
this(uuid, mediaDrm, callback, optionalKeyRequestParameters, eventHandler, eventListener, ExoMediaDrm<T> mediaDrm,
false, INITIAL_DRM_REQUEST_RETRY_COUNT); MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters,
Handler eventHandler,
DefaultDrmSessionEventListener eventListener) {
this(uuid, mediaDrm, callback, optionalKeyRequestParameters);
addListener(eventHandler, eventListener);
}
/**
* @param uuid The UUID of the drm scheme.
* @param mediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
*/
public DefaultDrmSessionManager(
UUID uuid,
ExoMediaDrm<T> mediaDrm,
MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters) {
this(
uuid,
mediaDrm,
callback,
optionalKeyRequestParameters,
/* multiSession= */ false,
INITIAL_DRM_REQUEST_RETRY_COUNT);
}
/**
* @deprecated Use {@link #DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap,
* boolean)} and {@link #addListener(Handler, DefaultDrmSessionEventListener)}.
*/
@Deprecated
public DefaultDrmSessionManager(
UUID uuid,
ExoMediaDrm<T> mediaDrm,
MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters,
Handler eventHandler,
DefaultDrmSessionEventListener eventListener,
boolean multiSession) {
this(uuid, mediaDrm, callback, optionalKeyRequestParameters, multiSession);
addListener(eventHandler, eventListener);
} }
/** /**
@ -229,17 +277,46 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
* @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 ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null. * to {@link ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. 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.
* @param multiSession A boolean that specify whether multiple key session support is enabled. * @param multiSession A boolean that specify whether multiple key session support is enabled.
* Default is false. * Default is false.
*/ */
public DefaultDrmSessionManager(UUID uuid, ExoMediaDrm<T> mediaDrm, MediaDrmCallback callback, public DefaultDrmSessionManager(
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler, UUID uuid,
EventListener eventListener, boolean multiSession) { ExoMediaDrm<T> mediaDrm,
this(uuid, mediaDrm, callback, optionalKeyRequestParameters, eventHandler, eventListener, MediaDrmCallback callback,
multiSession, INITIAL_DRM_REQUEST_RETRY_COUNT); HashMap<String, String> optionalKeyRequestParameters,
boolean multiSession) {
this(
uuid,
mediaDrm,
callback,
optionalKeyRequestParameters,
multiSession,
INITIAL_DRM_REQUEST_RETRY_COUNT);
}
/**
* @deprecated Use {@link #DefaultDrmSessionManager(UUID, ExoMediaDrm, MediaDrmCallback, HashMap,
* boolean, int)} and {@link #addListener(Handler, DefaultDrmSessionEventListener)}.
*/
@Deprecated
public DefaultDrmSessionManager(
UUID uuid,
ExoMediaDrm<T> mediaDrm,
MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters,
Handler eventHandler,
DefaultDrmSessionEventListener eventListener,
boolean multiSession,
int initialDrmRequestRetryCount) {
this(
uuid,
mediaDrm,
callback,
optionalKeyRequestParameters,
multiSession,
initialDrmRequestRetryCount);
addListener(eventHandler, eventListener);
} }
/** /**
@ -248,17 +325,18 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
* @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 ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null. * to {@link ExoMediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. 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.
* @param multiSession A boolean that specify whether multiple key session support is enabled. * @param multiSession A boolean that specify whether multiple key session support is enabled.
* Default is false. * Default is false.
* @param initialDrmRequestRetryCount The number of times to retry for initial provisioning and * @param initialDrmRequestRetryCount The number of times to retry for initial provisioning and
* key request before reporting error. * key request before reporting error.
*/ */
public DefaultDrmSessionManager(UUID uuid, ExoMediaDrm<T> mediaDrm, MediaDrmCallback callback, public DefaultDrmSessionManager(
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler, UUID uuid,
EventListener eventListener, boolean multiSession, int initialDrmRequestRetryCount) { ExoMediaDrm<T> mediaDrm,
MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters,
boolean multiSession,
int initialDrmRequestRetryCount) {
Assertions.checkNotNull(uuid); Assertions.checkNotNull(uuid);
Assertions.checkNotNull(mediaDrm); Assertions.checkNotNull(mediaDrm);
Assertions.checkArgument(!C.COMMON_PSSH_UUID.equals(uuid), "Use C.CLEARKEY_UUID instead"); Assertions.checkArgument(!C.COMMON_PSSH_UUID.equals(uuid), "Use C.CLEARKEY_UUID instead");
@ -266,8 +344,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
this.mediaDrm = mediaDrm; this.mediaDrm = mediaDrm;
this.callback = callback; this.callback = callback;
this.optionalKeyRequestParameters = optionalKeyRequestParameters; this.optionalKeyRequestParameters = optionalKeyRequestParameters;
this.eventHandler = eventHandler; this.eventDispatcher = new EventDispatcher();
this.eventListener = eventListener;
this.multiSession = multiSession; this.multiSession = multiSession;
this.initialDrmRequestRetryCount = initialDrmRequestRetryCount; this.initialDrmRequestRetryCount = initialDrmRequestRetryCount;
mode = MODE_PLAYBACK; mode = MODE_PLAYBACK;
@ -279,6 +356,25 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
mediaDrm.setOnEventListener(new MediaDrmEventListener()); mediaDrm.setOnEventListener(new MediaDrmEventListener());
} }
/**
* Adds a {@link DefaultDrmSessionEventListener} to listen to drm session events.
*
* @param handler A handler to use when delivering events to {@code eventListener}.
* @param eventListener A listener of events.
*/
public final void addListener(Handler handler, DefaultDrmSessionEventListener eventListener) {
eventDispatcher.addListener(handler, eventListener);
}
/**
* Removes a {@link DefaultDrmSessionEventListener} from the list of drm session event listeners.
*
* @param eventListener The listener to remove.
*/
public final void removeListener(DefaultDrmSessionEventListener eventListener) {
eventDispatcher.removeListener(eventListener);
}
/** /**
* Provides access to {@link ExoMediaDrm#getPropertyString(String)}. * Provides access to {@link ExoMediaDrm#getPropertyString(String)}.
* <p> * <p>
@ -406,15 +502,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
SchemeData data = getSchemeData(drmInitData, uuid, false); SchemeData data = getSchemeData(drmInitData, uuid, false);
if (data == null) { if (data == null) {
final MissingSchemeDataException error = new MissingSchemeDataException(uuid); final MissingSchemeDataException error = new MissingSchemeDataException(uuid);
if (eventHandler != null && eventListener != null) { eventDispatcher.drmSessionManagerError(error);
eventHandler.post(
new Runnable() {
@Override
public void run() {
eventListener.onDrmSessionManagerError(error);
}
});
}
return new ErrorStateDrmSession<>(new DrmSessionException(error)); return new ErrorStateDrmSession<>(new DrmSessionException(error));
} }
initData = getSchemeInitData(data, uuid); initData = getSchemeInitData(data, uuid);
@ -437,9 +525,20 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
if (session == null) { if (session == null) {
// Create a new session. // Create a new session.
session = new DefaultDrmSession<>(uuid, mediaDrm, this, initData, mimeType, mode, session =
offlineLicenseKeySetId, optionalKeyRequestParameters, callback, playbackLooper, new DefaultDrmSession<>(
eventHandler, eventListener, initialDrmRequestRetryCount); uuid,
mediaDrm,
this,
initData,
mimeType,
mode,
offlineLicenseKeySetId,
optionalKeyRequestParameters,
callback,
playbackLooper,
eventDispatcher,
initialDrmRequestRetryCount);
sessions.add(session); sessions.add(session);
} }
session.acquire(); session.acquire();

View File

@ -21,7 +21,6 @@ import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.util.Pair; import android.util.Pair;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.EventListener;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.Mode; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.Mode;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource;
@ -90,10 +89,12 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
* @throws UnsupportedDrmException If the Widevine DRM scheme is unsupported or cannot be * @throws UnsupportedDrmException If the Widevine DRM scheme is unsupported or cannot be
* instantiated. * instantiated.
* @see DefaultDrmSessionManager#DefaultDrmSessionManager(java.util.UUID, ExoMediaDrm, * @see DefaultDrmSessionManager#DefaultDrmSessionManager(java.util.UUID, ExoMediaDrm,
* MediaDrmCallback, HashMap, Handler, EventListener) * MediaDrmCallback, HashMap, Handler, DefaultDrmSessionEventListener)
*/ */
public static OfflineLicenseHelper<FrameworkMediaCrypto> newWidevineInstance( public static OfflineLicenseHelper<FrameworkMediaCrypto> newWidevineInstance(
String defaultLicenseUrl, boolean forceDefaultLicenseUrl, Factory httpDataSourceFactory, String defaultLicenseUrl,
boolean forceDefaultLicenseUrl,
Factory httpDataSourceFactory,
HashMap<String, String> optionalKeyRequestParameters) HashMap<String, String> optionalKeyRequestParameters)
throws UnsupportedDrmException { throws UnsupportedDrmException {
return new OfflineLicenseHelper<>(C.WIDEVINE_UUID, return new OfflineLicenseHelper<>(C.WIDEVINE_UUID,
@ -111,36 +112,41 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
* @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.
* @see DefaultDrmSessionManager#DefaultDrmSessionManager(java.util.UUID, ExoMediaDrm, * @see DefaultDrmSessionManager#DefaultDrmSessionManager(java.util.UUID, ExoMediaDrm,
* MediaDrmCallback, HashMap, Handler, EventListener) * MediaDrmCallback, HashMap, Handler, DefaultDrmSessionEventListener)
*/ */
public OfflineLicenseHelper(UUID uuid, ExoMediaDrm<T> mediaDrm, MediaDrmCallback callback, public OfflineLicenseHelper(
UUID uuid,
ExoMediaDrm<T> mediaDrm,
MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters) { HashMap<String, String> optionalKeyRequestParameters) {
handlerThread = new HandlerThread("OfflineLicenseHelper"); handlerThread = new HandlerThread("OfflineLicenseHelper");
handlerThread.start(); handlerThread.start();
conditionVariable = new ConditionVariable(); conditionVariable = new ConditionVariable();
EventListener eventListener = new EventListener() { DefaultDrmSessionEventListener eventListener =
@Override new DefaultDrmSessionEventListener() {
public void onDrmKeysLoaded() { @Override
conditionVariable.open(); public void onDrmKeysLoaded() {
} conditionVariable.open();
}
@Override @Override
public void onDrmSessionManagerError(Exception e) { public void onDrmSessionManagerError(Exception e) {
conditionVariable.open(); conditionVariable.open();
} }
@Override @Override
public void onDrmKeysRestored() { public void onDrmKeysRestored() {
conditionVariable.open(); conditionVariable.open();
} }
@Override @Override
public void onDrmKeysRemoved() { public void onDrmKeysRemoved() {
conditionVariable.open(); conditionVariable.open();
} }
}; };
drmSessionManager = new DefaultDrmSessionManager<>(uuid, mediaDrm, callback, drmSessionManager =
optionalKeyRequestParameters, new Handler(handlerThread.getLooper()), eventListener); new DefaultDrmSessionManager<>(uuid, mediaDrm, callback, optionalKeyRequestParameters);
drmSessionManager.addListener(new Handler(handlerThread.getLooper()), eventListener);
} }
/** /**

View File

@ -27,7 +27,7 @@ import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.audio.AudioRendererEventListener; import com.google.android.exoplayer2.audio.AudioRendererEventListener;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataOutput; import com.google.android.exoplayer2.metadata.MetadataOutput;
import com.google.android.exoplayer2.metadata.emsg.EventMessage; import com.google.android.exoplayer2.metadata.emsg.EventMessage;
@ -60,7 +60,7 @@ public class EventLogger
VideoRendererEventListener, VideoRendererEventListener,
MediaSourceEventListener, MediaSourceEventListener,
AdsMediaSource.EventListener, AdsMediaSource.EventListener,
DefaultDrmSessionManager.EventListener { DefaultDrmSessionEventListener {
private static final String TAG = "EventLogger"; private static final String TAG = "EventLogger";
private static final int MAX_TIMELINE_ITEM_LINES = 3; private static final int MAX_TIMELINE_ITEM_LINES = 3;

View File

@ -279,7 +279,7 @@ public final class DashTestRunner {
MediaDrmCallback drmCallback = new HttpMediaDrmCallback(widevineLicenseUrl, MediaDrmCallback drmCallback = new HttpMediaDrmCallback(widevineLicenseUrl,
new DefaultHttpDataSourceFactory(userAgent)); new DefaultHttpDataSourceFactory(userAgent));
DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager = DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager =
DefaultDrmSessionManager.newWidevineInstance(drmCallback, null, null, null); DefaultDrmSessionManager.newWidevineInstance(drmCallback, null);
if (!useL1Widevine) { if (!useL1Widevine) {
drmSessionManager.setPropertyString( drmSessionManager.setPropertyString(
SECURITY_LEVEL_PROPERTY, WIDEVINE_SECURITY_LEVEL_3); SECURITY_LEVEL_PROPERTY, WIDEVINE_SECURITY_LEVEL_3);