Loading api/current.txt +32 −0 Original line number Diff line number Diff line Loading @@ -25476,6 +25476,7 @@ package android.media { method public java.lang.Object setAuxEffectSendLevel(float); method public java.lang.Object setDataSource(android.media.DataSourceDesc); method public java.lang.Object setDisplay(android.view.SurfaceHolder); method public void setDrmEventCallback(java.util.concurrent.Executor, android.media.MediaPlayer2.DrmEventCallback); method public java.lang.Object setNextDataSource(android.media.DataSourceDesc); method public java.lang.Object setNextDataSources(java.util.List<android.media.DataSourceDesc>); method public java.lang.Object setPlaybackParams(android.media.PlaybackParams); Loading Loading @@ -25554,6 +25555,33 @@ package android.media { field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0 } public static class MediaPlayer2.DrmEventCallback { ctor public MediaPlayer2.DrmEventCallback(); method public void onDrmConfig(android.media.MediaPlayer2, android.media.DataSourceDesc, android.media.MediaDrm); method public android.media.MediaPlayer2.DrmPreparationInfo onDrmInfo(android.media.MediaPlayer2, android.media.DataSourceDesc, android.media.MediaPlayer2.DrmInfo); method public byte[] onDrmKeyRequest(android.media.MediaPlayer2, android.media.DataSourceDesc, android.media.MediaDrm.KeyRequest); method public void onDrmPrepared(android.media.MediaPlayer2, android.media.DataSourceDesc, int, byte[]); } public static final class MediaPlayer2.DrmInfo { method public java.util.Map<java.util.UUID, byte[]> getPssh(); method public java.util.List<java.util.UUID> getSupportedSchemes(); } public static final class MediaPlayer2.DrmPreparationInfo { } public static final class MediaPlayer2.DrmPreparationInfo.Builder { ctor public MediaPlayer2.DrmPreparationInfo.Builder(); method public android.media.MediaPlayer2.DrmPreparationInfo build(); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setInitData(byte[]); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeySetId(byte[]); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeyType(int); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setMimeType(java.lang.String); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setOptionalParameters(java.util.Map<java.lang.String, java.lang.String>); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setUuid(java.util.UUID); } public static class MediaPlayer2.EventCallback { ctor public MediaPlayer2.EventCallback(); method public void onCallCompleted(android.media.MediaPlayer2, android.media.DataSourceDesc, int, int); Loading Loading @@ -25581,6 +25609,10 @@ package android.media { field public static final java.lang.String WIDTH = "android.media.mediaplayer.width"; } public static final class MediaPlayer2.NoDrmSchemeException extends android.media.MediaDrmException { ctor public MediaPlayer2.NoDrmSchemeException(java.lang.String); } public static class MediaPlayer2.TrackInfo { method public android.media.MediaFormat getFormat(); method public java.lang.String getLanguage(); media/java/android/media/MediaPlayer2.java +222 −69 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import java.net.URL; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; Loading @@ -67,6 +68,7 @@ import java.util.List; import java.util.Map; import java.util.Queue; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; Loading Loading @@ -399,8 +401,7 @@ public class MediaPlayer2 implements AutoCloseable clearSourceInfos(); // Modular DRM clean up mOnDrmConfigHelper = null; synchronized (mDrmEventCbLock) { synchronized (mDrmEventCallbackLock) { mDrmEventCallbackRecords.clear(); } Loading Loading @@ -2889,7 +2890,7 @@ public class MediaPlayer2 implements AutoCloseable } private void sendDrmEvent(final DrmEventNotifier notifier) { synchronized (mDrmEventCbLock) { synchronized (mDrmEventCallbackLock) { try { for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { cb.first.execute(() -> notifier.notify(cb.second)); Loading @@ -2901,12 +2902,28 @@ public class MediaPlayer2 implements AutoCloseable } } private <T> T sendDrmEventWait(final DrmEventNotifier<T> notifier) throws InterruptedException, ExecutionException { synchronized (mDrmEventCallbackLock) { mDrmEventCallbackRecords.get(0); for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { CompletableFuture<T> ret = new CompletableFuture<>(); cb.first.execute(() -> ret.complete(notifier.notifyWait(cb.second))); return ret.get(); } } return null; } private interface EventNotifier { void notify(EventCallback callback); } private interface DrmEventNotifier { void notify(DrmEventCallback callback); private interface DrmEventNotifier<T> { default void notify(DrmEventCallback callback) { } default T notifyWait(DrmEventCallback callback) { return null; } } /* Do not change these values without updating their counterparts Loading Loading @@ -3351,73 +3368,209 @@ public class MediaPlayer2 implements AutoCloseable // Modular DRM begin /** * Interface definition of a callback to be invoked when the app * can do DRM configuration (get/set properties) before the session * is opened. This facilitates configuration of the properties, like * 'securityLevel', which has to be set after DRM scheme creation but * before the DRM session is opened. * An immutable structure per {@link DataSourceDesc} with settings required to initiate a DRM * protected playback session. * * The only allowed DRM calls in this listener are * {@link MediaPlayer2#getDrmPropertyString(DataSourceDesc, String)} * and {@link MediaPlayer2#setDrmPropertyString(DataSourceDesc, String, String)}. * @hide * @see DrmPreparationInfo.Builder */ public interface OnDrmConfigHelper { public static final class DrmPreparationInfo { /** * Mutable builder to create a {@link MediaPlayer2.DrmPreparationInfo} object. */ public static final class Builder { private UUID mUUID; private byte[] mKeySetId; private byte[] mInitData; private String mMimeType; private int mKeyType; private Map<String, String> mOptionalParameters; /** * Called to give the app the opportunity to configure DRM before the session is created * Set UUID of the crypto scheme selected to decrypt content. An UUID can be retrieved from * the source listening to {@link MediaPlayer2.DrmEventCallback#onDrmInfo}. * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the DataSourceDesc of this data source * @param uuid of selected crypto scheme * @return this */ public void onDrmConfig(MediaPlayer2 mp, DataSourceDesc dsd); public Builder setUuid(@NonNull UUID uuid) { this.mUUID = uuid; return this; } /** * Register a callback to be invoked for configuration of the DRM object before * the session is created. * The callback will be invoked synchronously during the execution * of {@link #prepareDrm}. * Set identifier of a persisted offline key obtained from * {@link MediaPlayer2.DrmEventCallback#onDrmPrepared(MediaPlayer2, DataSourceDesc, int, byte[])}. * * @param listener the callback that will be run * @hide * A {@code keySetId} can be used to restore persisted offline keys into a new playback * session of a DRM protected data source. When {@code keySetId} is set, {@code initData}, * {@code mimeType}, {@code keyType}, {@code optionalParameters} are ignored. * * @param keySetId identifier of a persisted offline key * @return this */ // This is a synchronous call. public void setOnDrmConfigHelper(OnDrmConfigHelper listener) { mOnDrmConfigHelper = listener; public Builder setKeySetId(@Nullable byte[] keySetId) { this.mKeySetId = keySetId; return this; } /** * Set container-specific DRM initialization data. Its meaning is interpreted based on * {@code mimeType}. For example, it could contain the content ID, key ID or other data * obtained from the content metadata that is required to generate a * {@link MediaDrm.KeyRequest}. * * @param initData container-specific DRM initialization data * @return this */ public Builder setInitData(@Nullable byte[] initData) { this.mInitData = initData; return this; } /** * Set mime type of the content * * @param mimeType mime type to the content * @return this */ public Builder setMimeType(@Nullable String mimeType) { this.mMimeType = mimeType; return this; } /** * Set type of the key request. The request may be to acquire keys * for streaming, {@link MediaDrm#KEY_TYPE_STREAMING}, or for offline content, * {@link MediaDrm#KEY_TYPE_OFFLINE}. Releasing previously acquired keys * ({@link MediaDrm#KEY_TYPE_RELEASE}) is not allowed. * * @param keyType type of the key request * @return this */ public Builder setKeyType(@MediaPlayer2.MediaDrmKeyType int keyType) { this.mKeyType = keyType; return this; } /** * Set optional parameters to be included in a {@link MediaDrm.KeyRequest} message sent to * the license server. * * @param optionalParameters optional parameters to be included in a key request * @return this */ public Builder setOptionalParameters( @Nullable Map<String, String> optionalParameters) { this.mOptionalParameters = optionalParameters; return this; } /** * @return an immutable {@link MediaPlayer2.DrmPreparationInfo} representing the settings of this builder */ public MediaPlayer2.DrmPreparationInfo build() { return new MediaPlayer2.DrmPreparationInfo(mUUID, mKeySetId, mInitData, mMimeType, mKeyType, mOptionalParameters); } } private final UUID mUUID; private final byte[] mKeySetId; private final byte[] mInitData; private final String mMimeType; private final int mKeyType; private final Map<String, String> mOptionalParameters; private DrmPreparationInfo(UUID mUUID, byte[] mKeySetId, byte[] mInitData, String mMimeType, int mKeyType, Map<String, String> optionalParameters) { this.mUUID = mUUID; this.mKeySetId = mKeySetId; this.mInitData = mInitData; this.mMimeType = mMimeType; this.mKeyType = mKeyType; this.mOptionalParameters = optionalParameters; } private OnDrmConfigHelper mOnDrmConfigHelper; } /** * Interface definition for callbacks to be invoked when the player has the corresponding * DRM events. * @hide */ public static class DrmEventCallback { /** * Called to indicate DRM info is available * Called to indicate DRM info is available. Return a {@link DrmPreparationInfo} object that * bundles DRM initialization parameters. * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the DataSourceDesc of this data source * @param drmInfo DRM info of the source including PSSH, and subset * of crypto schemes supported by this device * @param dsd the {@link DataSourceDesc} of this data source * @param drmInfo DRM info of the source including PSSH, and subset of crypto schemes * supported by this device * @return a {@link DrmPreparationInfo} object to initialize DRM playback, or null to skip * DRM initialization */ public void onDrmInfo(MediaPlayer2 mp, DataSourceDesc dsd, DrmInfo drmInfo) { } public DrmPreparationInfo onDrmInfo(MediaPlayer2 mp, DataSourceDesc dsd, DrmInfo drmInfo) { return null; } /** * Called to notify the client that {@link MediaPlayer2#prepareDrm(DataSourceDesc, UUID)} * is finished and ready for key request/response. * Called to notify the client that {@code mp} is ready to decrypt DRM protected data source * {@code dsd} * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the DataSourceDesc of this data source * @param dsd the {@link DataSourceDesc} of this data source * @param status the result of DRM preparation. * @param keySetId optional identifier that can be used to restore DRM playback initiated * with a {@link MediaDrm#KEY_TYPE_OFFLINE} key request. * * @see DrmPreparationInfo.Builder#setKeySetId(byte[]) */ public void onDrmPrepared( MediaPlayer2 mp, DataSourceDesc dsd, @PrepareDrmStatusCode int status) { } public void onDrmPrepared(@NonNull MediaPlayer2 mp, @NonNull DataSourceDesc dsd, @PrepareDrmStatusCode int status, @Nullable byte[] keySetId) { } /** * Called to give the app the opportunity to configure DRM before the session is created. * * This facilitates configuration of the properties, like 'securityLevel', which * has to be set after DRM scheme creation but before the DRM session is opened. * * The only allowed DRM calls in this listener are * {@link MediaDrm#getPropertyString(String)}, * {@link MediaDrm#getPropertyByteArray(String)}, * {@link MediaDrm#setPropertyString(String, String)}, * {@link MediaDrm#setPropertyByteArray(String, byte[])}, * {@link MediaDrm#setOnExpirationUpdateListener}, * and {@link MediaDrm#setOnKeyStatusChangeListener}. * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the {@link DataSourceDesc} of this data source * @param drm handle to get/set DRM properties and listeners for this data source */ public void onDrmConfig(@NonNull MediaPlayer2 mp, @NonNull DataSourceDesc dsd, @NonNull MediaDrm drm) { } /** * Called to indicate the DRM session for {@code dsd} is ready for key request/response * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the {@link DataSourceDesc} of this data source * @param request a {@link MediaDrm.KeyRequest} prepared using the * {@link DrmPreparationInfo} returned from * {@link #onDrmInfo(MediaPlayer2, DataSourceDesc, DrmInfo)} * @return the response to {@code request} (from license server) */ public byte[] onDrmKeyRequest(@NonNull MediaPlayer2 mp, @NonNull DataSourceDesc dsd, @NonNull MediaDrm.KeyRequest request) { return null; } private final Object mDrmEventCbLock = new Object(); private ArrayList<Pair<Executor, DrmEventCallback>> mDrmEventCallbackRecords = } private final Object mDrmEventCallbackLock = new Object(); private List<Pair<Executor, DrmEventCallback>> mDrmEventCallbackRecords = new ArrayList<Pair<Executor, DrmEventCallback>>(); /** Loading @@ -3425,10 +3578,9 @@ public class MediaPlayer2 implements AutoCloseable * * @param eventCallback the callback that will be run * @param executor the executor through which the callback should be invoked * @hide */ // This is a synchronous call. public void registerDrmEventCallback(@NonNull @CallbackExecutor Executor executor, public void setDrmEventCallback(@NonNull @CallbackExecutor Executor executor, @NonNull DrmEventCallback eventCallback) { if (eventCallback == null) { throw new IllegalArgumentException("Illegal null EventCallback"); Loading @@ -3437,8 +3589,9 @@ public class MediaPlayer2 implements AutoCloseable throw new IllegalArgumentException( "Illegal null Executor for the EventCallback"); } synchronized (mDrmEventCbLock) { mDrmEventCallbackRecords.add(new Pair(executor, eventCallback)); synchronized (mDrmEventCallbackLock) { mDrmEventCallbackRecords = Collections.singletonList( new Pair<Executor, DrmEventCallback>(executor, eventCallback)); } } Loading @@ -3450,7 +3603,7 @@ public class MediaPlayer2 implements AutoCloseable */ // This is a synchronous call. public void unregisterDrmEventCallback(DrmEventCallback eventCallback) { synchronized (mDrmEventCbLock) { synchronized (mDrmEventCallbackLock) { for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { if (cb.second == eventCallback) { mDrmEventCallbackRecords.remove(cb); Loading Loading @@ -3564,7 +3717,7 @@ public class MediaPlayer2 implements AutoCloseable /** * Prepares the DRM for the given data source * <p> * If {@link OnDrmConfigHelper} is registered, it will be called during * If {@link DrmEventCallback} is registered, it will be called during * preparation to allow configuration of the DRM properties before opening the * DRM session. It should be used only for a series of * {@link #getDrmPropertyString(DataSourceDesc, String)} and Loading @@ -3587,8 +3740,7 @@ public class MediaPlayer2 implements AutoCloseable * @param dsd The DRM protected data source * * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved * from the source through {@link #getDrmInfo(DataSourceDesc)} or registering a * {@link DrmEventCallback#onDrmInfo}. * from the source listening to {@link DrmEventCallback#onDrmInfo}. * * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * @hide Loading Loading @@ -3661,8 +3813,8 @@ public class MediaPlayer2 implements AutoCloseable sendDrmEvent(new DrmEventNotifier() { @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( MediaPlayer2.this, dsd, prepareDrmStatus); callback.onDrmPrepared(MediaPlayer2.this, dsd, prepareDrmStatus, /* TODO: keySetId */ null); } }); Loading Loading @@ -3876,7 +4028,6 @@ public class MediaPlayer2 implements AutoCloseable /** * Encapsulates the DRM properties of the source. * @hide */ public static final class DrmInfo { private Map<UUID, byte[]> mMapPssh; Loading Loading @@ -4013,10 +4164,8 @@ public class MediaPlayer2 implements AutoCloseable }; // DrmInfo /** * Thrown when a DRM method is called before preparing a DRM scheme through * {@link MediaPlayer2#prepareDrm(DataSourceDesc, UUID)}. * Thrown when a DRM method is called when there is no active DRM session. * Extends MediaDrm.MediaDrmException * @hide */ public static final class NoDrmSchemeException extends MediaDrmException { public NoDrmSchemeException(String detailMessage) { Loading Loading @@ -4291,9 +4440,9 @@ public class MediaPlayer2 implements AutoCloseable } void prepare(UUID uuid) throws UnsupportedSchemeException, ResourceBusyException, NotProvisionedException { final OnDrmConfigHelper onDrmConfigHelper = mOnDrmConfigHelper; Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + onDrmConfigHelper); ResourceBusyException, NotProvisionedException, InterruptedException, ExecutionException { Log.v(TAG, "prepareDrm: uuid: " + uuid); synchronized (this) { if (mActiveDrmUUID != null) { Loading Loading @@ -4334,9 +4483,13 @@ public class MediaPlayer2 implements AutoCloseable } // synchronized // call the callback outside the lock if (onDrmConfigHelper != null) { onDrmConfigHelper.onDrmConfig(MediaPlayer2.this, mDSD); sendDrmEventWait(new DrmEventNotifier<Void>() { @Override public Void notifyWait(DrmEventCallback callback) { callback.onDrmConfig(MediaPlayer2.this, mDSD, mDrmObj); return null; } }); synchronized (this) { mDrmConfigAllowed = false; Loading Loading @@ -4506,7 +4659,7 @@ public class MediaPlayer2 implements AutoCloseable @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( MediaPlayer2.this, mDSD, finalStatus); MediaPlayer2.this, mDSD, finalStatus, /* TODO: keySetId */ null); } }); Loading Loading
api/current.txt +32 −0 Original line number Diff line number Diff line Loading @@ -25476,6 +25476,7 @@ package android.media { method public java.lang.Object setAuxEffectSendLevel(float); method public java.lang.Object setDataSource(android.media.DataSourceDesc); method public java.lang.Object setDisplay(android.view.SurfaceHolder); method public void setDrmEventCallback(java.util.concurrent.Executor, android.media.MediaPlayer2.DrmEventCallback); method public java.lang.Object setNextDataSource(android.media.DataSourceDesc); method public java.lang.Object setNextDataSources(java.util.List<android.media.DataSourceDesc>); method public java.lang.Object setPlaybackParams(android.media.PlaybackParams); Loading Loading @@ -25554,6 +25555,33 @@ package android.media { field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0 } public static class MediaPlayer2.DrmEventCallback { ctor public MediaPlayer2.DrmEventCallback(); method public void onDrmConfig(android.media.MediaPlayer2, android.media.DataSourceDesc, android.media.MediaDrm); method public android.media.MediaPlayer2.DrmPreparationInfo onDrmInfo(android.media.MediaPlayer2, android.media.DataSourceDesc, android.media.MediaPlayer2.DrmInfo); method public byte[] onDrmKeyRequest(android.media.MediaPlayer2, android.media.DataSourceDesc, android.media.MediaDrm.KeyRequest); method public void onDrmPrepared(android.media.MediaPlayer2, android.media.DataSourceDesc, int, byte[]); } public static final class MediaPlayer2.DrmInfo { method public java.util.Map<java.util.UUID, byte[]> getPssh(); method public java.util.List<java.util.UUID> getSupportedSchemes(); } public static final class MediaPlayer2.DrmPreparationInfo { } public static final class MediaPlayer2.DrmPreparationInfo.Builder { ctor public MediaPlayer2.DrmPreparationInfo.Builder(); method public android.media.MediaPlayer2.DrmPreparationInfo build(); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setInitData(byte[]); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeySetId(byte[]); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setKeyType(int); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setMimeType(java.lang.String); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setOptionalParameters(java.util.Map<java.lang.String, java.lang.String>); method public android.media.MediaPlayer2.DrmPreparationInfo.Builder setUuid(java.util.UUID); } public static class MediaPlayer2.EventCallback { ctor public MediaPlayer2.EventCallback(); method public void onCallCompleted(android.media.MediaPlayer2, android.media.DataSourceDesc, int, int); Loading Loading @@ -25581,6 +25609,10 @@ package android.media { field public static final java.lang.String WIDTH = "android.media.mediaplayer.width"; } public static final class MediaPlayer2.NoDrmSchemeException extends android.media.MediaDrmException { ctor public MediaPlayer2.NoDrmSchemeException(java.lang.String); } public static class MediaPlayer2.TrackInfo { method public android.media.MediaFormat getFormat(); method public java.lang.String getLanguage();
media/java/android/media/MediaPlayer2.java +222 −69 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import java.net.URL; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; Loading @@ -67,6 +68,7 @@ import java.util.List; import java.util.Map; import java.util.Queue; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; Loading Loading @@ -399,8 +401,7 @@ public class MediaPlayer2 implements AutoCloseable clearSourceInfos(); // Modular DRM clean up mOnDrmConfigHelper = null; synchronized (mDrmEventCbLock) { synchronized (mDrmEventCallbackLock) { mDrmEventCallbackRecords.clear(); } Loading Loading @@ -2889,7 +2890,7 @@ public class MediaPlayer2 implements AutoCloseable } private void sendDrmEvent(final DrmEventNotifier notifier) { synchronized (mDrmEventCbLock) { synchronized (mDrmEventCallbackLock) { try { for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { cb.first.execute(() -> notifier.notify(cb.second)); Loading @@ -2901,12 +2902,28 @@ public class MediaPlayer2 implements AutoCloseable } } private <T> T sendDrmEventWait(final DrmEventNotifier<T> notifier) throws InterruptedException, ExecutionException { synchronized (mDrmEventCallbackLock) { mDrmEventCallbackRecords.get(0); for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { CompletableFuture<T> ret = new CompletableFuture<>(); cb.first.execute(() -> ret.complete(notifier.notifyWait(cb.second))); return ret.get(); } } return null; } private interface EventNotifier { void notify(EventCallback callback); } private interface DrmEventNotifier { void notify(DrmEventCallback callback); private interface DrmEventNotifier<T> { default void notify(DrmEventCallback callback) { } default T notifyWait(DrmEventCallback callback) { return null; } } /* Do not change these values without updating their counterparts Loading Loading @@ -3351,73 +3368,209 @@ public class MediaPlayer2 implements AutoCloseable // Modular DRM begin /** * Interface definition of a callback to be invoked when the app * can do DRM configuration (get/set properties) before the session * is opened. This facilitates configuration of the properties, like * 'securityLevel', which has to be set after DRM scheme creation but * before the DRM session is opened. * An immutable structure per {@link DataSourceDesc} with settings required to initiate a DRM * protected playback session. * * The only allowed DRM calls in this listener are * {@link MediaPlayer2#getDrmPropertyString(DataSourceDesc, String)} * and {@link MediaPlayer2#setDrmPropertyString(DataSourceDesc, String, String)}. * @hide * @see DrmPreparationInfo.Builder */ public interface OnDrmConfigHelper { public static final class DrmPreparationInfo { /** * Mutable builder to create a {@link MediaPlayer2.DrmPreparationInfo} object. */ public static final class Builder { private UUID mUUID; private byte[] mKeySetId; private byte[] mInitData; private String mMimeType; private int mKeyType; private Map<String, String> mOptionalParameters; /** * Called to give the app the opportunity to configure DRM before the session is created * Set UUID of the crypto scheme selected to decrypt content. An UUID can be retrieved from * the source listening to {@link MediaPlayer2.DrmEventCallback#onDrmInfo}. * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the DataSourceDesc of this data source * @param uuid of selected crypto scheme * @return this */ public void onDrmConfig(MediaPlayer2 mp, DataSourceDesc dsd); public Builder setUuid(@NonNull UUID uuid) { this.mUUID = uuid; return this; } /** * Register a callback to be invoked for configuration of the DRM object before * the session is created. * The callback will be invoked synchronously during the execution * of {@link #prepareDrm}. * Set identifier of a persisted offline key obtained from * {@link MediaPlayer2.DrmEventCallback#onDrmPrepared(MediaPlayer2, DataSourceDesc, int, byte[])}. * * @param listener the callback that will be run * @hide * A {@code keySetId} can be used to restore persisted offline keys into a new playback * session of a DRM protected data source. When {@code keySetId} is set, {@code initData}, * {@code mimeType}, {@code keyType}, {@code optionalParameters} are ignored. * * @param keySetId identifier of a persisted offline key * @return this */ // This is a synchronous call. public void setOnDrmConfigHelper(OnDrmConfigHelper listener) { mOnDrmConfigHelper = listener; public Builder setKeySetId(@Nullable byte[] keySetId) { this.mKeySetId = keySetId; return this; } /** * Set container-specific DRM initialization data. Its meaning is interpreted based on * {@code mimeType}. For example, it could contain the content ID, key ID or other data * obtained from the content metadata that is required to generate a * {@link MediaDrm.KeyRequest}. * * @param initData container-specific DRM initialization data * @return this */ public Builder setInitData(@Nullable byte[] initData) { this.mInitData = initData; return this; } /** * Set mime type of the content * * @param mimeType mime type to the content * @return this */ public Builder setMimeType(@Nullable String mimeType) { this.mMimeType = mimeType; return this; } /** * Set type of the key request. The request may be to acquire keys * for streaming, {@link MediaDrm#KEY_TYPE_STREAMING}, or for offline content, * {@link MediaDrm#KEY_TYPE_OFFLINE}. Releasing previously acquired keys * ({@link MediaDrm#KEY_TYPE_RELEASE}) is not allowed. * * @param keyType type of the key request * @return this */ public Builder setKeyType(@MediaPlayer2.MediaDrmKeyType int keyType) { this.mKeyType = keyType; return this; } /** * Set optional parameters to be included in a {@link MediaDrm.KeyRequest} message sent to * the license server. * * @param optionalParameters optional parameters to be included in a key request * @return this */ public Builder setOptionalParameters( @Nullable Map<String, String> optionalParameters) { this.mOptionalParameters = optionalParameters; return this; } /** * @return an immutable {@link MediaPlayer2.DrmPreparationInfo} representing the settings of this builder */ public MediaPlayer2.DrmPreparationInfo build() { return new MediaPlayer2.DrmPreparationInfo(mUUID, mKeySetId, mInitData, mMimeType, mKeyType, mOptionalParameters); } } private final UUID mUUID; private final byte[] mKeySetId; private final byte[] mInitData; private final String mMimeType; private final int mKeyType; private final Map<String, String> mOptionalParameters; private DrmPreparationInfo(UUID mUUID, byte[] mKeySetId, byte[] mInitData, String mMimeType, int mKeyType, Map<String, String> optionalParameters) { this.mUUID = mUUID; this.mKeySetId = mKeySetId; this.mInitData = mInitData; this.mMimeType = mMimeType; this.mKeyType = mKeyType; this.mOptionalParameters = optionalParameters; } private OnDrmConfigHelper mOnDrmConfigHelper; } /** * Interface definition for callbacks to be invoked when the player has the corresponding * DRM events. * @hide */ public static class DrmEventCallback { /** * Called to indicate DRM info is available * Called to indicate DRM info is available. Return a {@link DrmPreparationInfo} object that * bundles DRM initialization parameters. * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the DataSourceDesc of this data source * @param drmInfo DRM info of the source including PSSH, and subset * of crypto schemes supported by this device * @param dsd the {@link DataSourceDesc} of this data source * @param drmInfo DRM info of the source including PSSH, and subset of crypto schemes * supported by this device * @return a {@link DrmPreparationInfo} object to initialize DRM playback, or null to skip * DRM initialization */ public void onDrmInfo(MediaPlayer2 mp, DataSourceDesc dsd, DrmInfo drmInfo) { } public DrmPreparationInfo onDrmInfo(MediaPlayer2 mp, DataSourceDesc dsd, DrmInfo drmInfo) { return null; } /** * Called to notify the client that {@link MediaPlayer2#prepareDrm(DataSourceDesc, UUID)} * is finished and ready for key request/response. * Called to notify the client that {@code mp} is ready to decrypt DRM protected data source * {@code dsd} * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the DataSourceDesc of this data source * @param dsd the {@link DataSourceDesc} of this data source * @param status the result of DRM preparation. * @param keySetId optional identifier that can be used to restore DRM playback initiated * with a {@link MediaDrm#KEY_TYPE_OFFLINE} key request. * * @see DrmPreparationInfo.Builder#setKeySetId(byte[]) */ public void onDrmPrepared( MediaPlayer2 mp, DataSourceDesc dsd, @PrepareDrmStatusCode int status) { } public void onDrmPrepared(@NonNull MediaPlayer2 mp, @NonNull DataSourceDesc dsd, @PrepareDrmStatusCode int status, @Nullable byte[] keySetId) { } /** * Called to give the app the opportunity to configure DRM before the session is created. * * This facilitates configuration of the properties, like 'securityLevel', which * has to be set after DRM scheme creation but before the DRM session is opened. * * The only allowed DRM calls in this listener are * {@link MediaDrm#getPropertyString(String)}, * {@link MediaDrm#getPropertyByteArray(String)}, * {@link MediaDrm#setPropertyString(String, String)}, * {@link MediaDrm#setPropertyByteArray(String, byte[])}, * {@link MediaDrm#setOnExpirationUpdateListener}, * and {@link MediaDrm#setOnKeyStatusChangeListener}. * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the {@link DataSourceDesc} of this data source * @param drm handle to get/set DRM properties and listeners for this data source */ public void onDrmConfig(@NonNull MediaPlayer2 mp, @NonNull DataSourceDesc dsd, @NonNull MediaDrm drm) { } /** * Called to indicate the DRM session for {@code dsd} is ready for key request/response * * @param mp the {@code MediaPlayer2} associated with this callback * @param dsd the {@link DataSourceDesc} of this data source * @param request a {@link MediaDrm.KeyRequest} prepared using the * {@link DrmPreparationInfo} returned from * {@link #onDrmInfo(MediaPlayer2, DataSourceDesc, DrmInfo)} * @return the response to {@code request} (from license server) */ public byte[] onDrmKeyRequest(@NonNull MediaPlayer2 mp, @NonNull DataSourceDesc dsd, @NonNull MediaDrm.KeyRequest request) { return null; } private final Object mDrmEventCbLock = new Object(); private ArrayList<Pair<Executor, DrmEventCallback>> mDrmEventCallbackRecords = } private final Object mDrmEventCallbackLock = new Object(); private List<Pair<Executor, DrmEventCallback>> mDrmEventCallbackRecords = new ArrayList<Pair<Executor, DrmEventCallback>>(); /** Loading @@ -3425,10 +3578,9 @@ public class MediaPlayer2 implements AutoCloseable * * @param eventCallback the callback that will be run * @param executor the executor through which the callback should be invoked * @hide */ // This is a synchronous call. public void registerDrmEventCallback(@NonNull @CallbackExecutor Executor executor, public void setDrmEventCallback(@NonNull @CallbackExecutor Executor executor, @NonNull DrmEventCallback eventCallback) { if (eventCallback == null) { throw new IllegalArgumentException("Illegal null EventCallback"); Loading @@ -3437,8 +3589,9 @@ public class MediaPlayer2 implements AutoCloseable throw new IllegalArgumentException( "Illegal null Executor for the EventCallback"); } synchronized (mDrmEventCbLock) { mDrmEventCallbackRecords.add(new Pair(executor, eventCallback)); synchronized (mDrmEventCallbackLock) { mDrmEventCallbackRecords = Collections.singletonList( new Pair<Executor, DrmEventCallback>(executor, eventCallback)); } } Loading @@ -3450,7 +3603,7 @@ public class MediaPlayer2 implements AutoCloseable */ // This is a synchronous call. public void unregisterDrmEventCallback(DrmEventCallback eventCallback) { synchronized (mDrmEventCbLock) { synchronized (mDrmEventCallbackLock) { for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { if (cb.second == eventCallback) { mDrmEventCallbackRecords.remove(cb); Loading Loading @@ -3564,7 +3717,7 @@ public class MediaPlayer2 implements AutoCloseable /** * Prepares the DRM for the given data source * <p> * If {@link OnDrmConfigHelper} is registered, it will be called during * If {@link DrmEventCallback} is registered, it will be called during * preparation to allow configuration of the DRM properties before opening the * DRM session. It should be used only for a series of * {@link #getDrmPropertyString(DataSourceDesc, String)} and Loading @@ -3587,8 +3740,7 @@ public class MediaPlayer2 implements AutoCloseable * @param dsd The DRM protected data source * * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved * from the source through {@link #getDrmInfo(DataSourceDesc)} or registering a * {@link DrmEventCallback#onDrmInfo}. * from the source listening to {@link DrmEventCallback#onDrmInfo}. * * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * @hide Loading Loading @@ -3661,8 +3813,8 @@ public class MediaPlayer2 implements AutoCloseable sendDrmEvent(new DrmEventNotifier() { @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( MediaPlayer2.this, dsd, prepareDrmStatus); callback.onDrmPrepared(MediaPlayer2.this, dsd, prepareDrmStatus, /* TODO: keySetId */ null); } }); Loading Loading @@ -3876,7 +4028,6 @@ public class MediaPlayer2 implements AutoCloseable /** * Encapsulates the DRM properties of the source. * @hide */ public static final class DrmInfo { private Map<UUID, byte[]> mMapPssh; Loading Loading @@ -4013,10 +4164,8 @@ public class MediaPlayer2 implements AutoCloseable }; // DrmInfo /** * Thrown when a DRM method is called before preparing a DRM scheme through * {@link MediaPlayer2#prepareDrm(DataSourceDesc, UUID)}. * Thrown when a DRM method is called when there is no active DRM session. * Extends MediaDrm.MediaDrmException * @hide */ public static final class NoDrmSchemeException extends MediaDrmException { public NoDrmSchemeException(String detailMessage) { Loading Loading @@ -4291,9 +4440,9 @@ public class MediaPlayer2 implements AutoCloseable } void prepare(UUID uuid) throws UnsupportedSchemeException, ResourceBusyException, NotProvisionedException { final OnDrmConfigHelper onDrmConfigHelper = mOnDrmConfigHelper; Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + onDrmConfigHelper); ResourceBusyException, NotProvisionedException, InterruptedException, ExecutionException { Log.v(TAG, "prepareDrm: uuid: " + uuid); synchronized (this) { if (mActiveDrmUUID != null) { Loading Loading @@ -4334,9 +4483,13 @@ public class MediaPlayer2 implements AutoCloseable } // synchronized // call the callback outside the lock if (onDrmConfigHelper != null) { onDrmConfigHelper.onDrmConfig(MediaPlayer2.this, mDSD); sendDrmEventWait(new DrmEventNotifier<Void>() { @Override public Void notifyWait(DrmEventCallback callback) { callback.onDrmConfig(MediaPlayer2.this, mDSD, mDrmObj); return null; } }); synchronized (this) { mDrmConfigAllowed = false; Loading Loading @@ -4506,7 +4659,7 @@ public class MediaPlayer2 implements AutoCloseable @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( MediaPlayer2.this, mDSD, finalStatus); MediaPlayer2.this, mDSD, finalStatus, /* TODO: keySetId */ null); } }); Loading