mirror of
https://github.com/androidx/media.git
synced 2025-05-13 02:29:52 +08:00
Move requiresSecureDecoder
logic into ExoMediaDrm
The result is plumbed back to `MediaCodecRenderer` via a new `DrmSession#requiresSecureDecoder` method. This allows us to use the `MediaDrm#requiresSecureDecoder` method added in Android 12: https://developer.android.com/reference/android/media/MediaDrm#requiresSecureDecoder(java.lang.String) This change also removes `FrameworkMediaCrypto#forceAllowInsecureDecoderComponents`, replacing it with equivalent logic in `FrameworkMediaDrm#requiresSecureDecoder`. PiperOrigin-RevId: 389616038
This commit is contained in:
parent
0097a79c2d
commit
849c307402
@ -16,6 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.drm;
|
package com.google.android.exoplayer2.drm;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.util.Assertions.checkState;
|
import static com.google.android.exoplayer2.util.Assertions.checkState;
|
||||||
|
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
|
||||||
import static java.lang.Math.min;
|
import static java.lang.Math.min;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
@ -285,6 +286,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
return offlineLicenseKeySetId;
|
return offlineLicenseKeySetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresSecureDecoder(String mimeType) {
|
||||||
|
return mediaDrm.requiresSecureDecoder(checkStateNotNull(sessionId), mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acquire(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
|
public void acquire(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
|
||||||
checkState(referenceCount >= 0);
|
checkState(referenceCount >= 0);
|
||||||
|
@ -137,6 +137,15 @@ public interface DrmSession {
|
|||||||
@Nullable
|
@Nullable
|
||||||
byte[] getOfflineLicenseKeySetId();
|
byte[] getOfflineLicenseKeySetId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this session requires use of a secure decoder for the given MIME type. Assumes
|
||||||
|
* a license policy that requires the highest level of security supported by the session.
|
||||||
|
*
|
||||||
|
* <p>The session must be in {@link #getState() state} {@link #STATE_OPENED} or {@link
|
||||||
|
* #STATE_OPENED_WITH_KEYS}.
|
||||||
|
*/
|
||||||
|
boolean requiresSecureDecoder(String mimeType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the reference count. When the caller no longer needs to use the instance, it must
|
* Increments the reference count. When the caller no longer needs to use the instance, it must
|
||||||
* call {@link #release(DrmSessionEventListener.EventDispatcher)} to decrement the reference
|
* call {@link #release(DrmSessionEventListener.EventDispatcher)} to decrement the reference
|
||||||
|
@ -93,6 +93,12 @@ public final class DummyExoMediaDrm implements ExoMediaDrm {
|
|||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresSecureDecoder(byte[] sessionId, String mimeType) {
|
||||||
|
// Should not be invoked. No session should exist.
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acquire() {
|
public void acquire() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
@ -69,6 +69,11 @@ public final class ErrorStateDrmSession implements DrmSession {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresSecureDecoder(String mimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acquire(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
|
public void acquire(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
@ -460,6 +460,15 @@ public interface ExoMediaDrm {
|
|||||||
*/
|
*/
|
||||||
Map<String, String> queryKeyStatus(byte[] sessionId);
|
Map<String, String> queryKeyStatus(byte[] sessionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given session requires use of a secure decoder for the given MIME type.
|
||||||
|
* Assumes a license policy that requires the highest level of security supported by the session.
|
||||||
|
*
|
||||||
|
* @param sessionId The ID of the session.
|
||||||
|
* @param mimeType The content MIME type to query.
|
||||||
|
*/
|
||||||
|
boolean requiresSecureDecoder(byte[] sessionId, String mimeType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the reference count. When the caller no longer needs to use the instance, it must
|
* Increments the reference count. When the caller no longer needs to use the instance, it must
|
||||||
* call {@link #release()} to decrement the reference count.
|
* call {@link #release()} to decrement the reference count.
|
||||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.drm;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.media.DeniedByServerException;
|
import android.media.DeniedByServerException;
|
||||||
|
import android.media.MediaCrypto;
|
||||||
import android.media.MediaCryptoException;
|
import android.media.MediaCryptoException;
|
||||||
import android.media.MediaDrm;
|
import android.media.MediaDrm;
|
||||||
import android.media.MediaDrmException;
|
import android.media.MediaDrmException;
|
||||||
@ -24,6 +25,7 @@ import android.media.NotProvisionedException;
|
|||||||
import android.media.UnsupportedSchemeException;
|
import android.media.UnsupportedSchemeException;
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import androidx.annotation.DoNotInline;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
@ -244,6 +246,26 @@ public final class FrameworkMediaDrm implements ExoMediaDrm {
|
|||||||
return mediaDrm.queryKeyStatus(sessionId);
|
return mediaDrm.queryKeyStatus(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresSecureDecoder(byte[] sessionId, String mimeType) {
|
||||||
|
if (Util.SDK_INT >= 31) {
|
||||||
|
return Api31.requiresSecureDecoder(mediaDrm, mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaCrypto mediaCrypto;
|
||||||
|
try {
|
||||||
|
mediaCrypto = new MediaCrypto(uuid, sessionId);
|
||||||
|
} catch (MediaCryptoException e) {
|
||||||
|
// This shouldn't happen, but if it does then assume that a secure decoder may be required.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return mediaCrypto.requiresSecureDecoderComponent(mimeType);
|
||||||
|
} finally {
|
||||||
|
mediaCrypto.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void acquire() {
|
public synchronized void acquire() {
|
||||||
Assertions.checkState(referenceCount > 0);
|
Assertions.checkState(referenceCount > 0);
|
||||||
@ -476,4 +498,12 @@ public final class FrameworkMediaDrm implements ExoMediaDrm {
|
|||||||
newData.put(xmlWithMockLaUrl.getBytes(Charsets.UTF_16LE));
|
newData.put(xmlWithMockLaUrl.getBytes(Charsets.UTF_16LE));
|
||||||
return newData.array();
|
return newData.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(31)
|
||||||
|
private static class Api31 {
|
||||||
|
@DoNotInline
|
||||||
|
public static boolean requiresSecureDecoder(MediaDrm mediaDrm, String mimeType) {
|
||||||
|
return mediaDrm.requiresSecureDecoder(mimeType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2099,7 +2099,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
// the case is to occur, so we re-initialize in this case.
|
// the case is to occur, so we re-initialize in this case.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!codecInfo.secure && maybeRequiresSecureDecoder(newMediaCrypto, newFormat)) {
|
|
||||||
|
boolean requiresSecureDecoder;
|
||||||
|
if (newMediaCrypto.forceAllowInsecureDecoderComponents) {
|
||||||
|
requiresSecureDecoder = false;
|
||||||
|
} else {
|
||||||
|
requiresSecureDecoder = newSession.requiresSecureDecoder(newFormat.sampleMimeType);
|
||||||
|
}
|
||||||
|
if (!codecInfo.secure && requiresSecureDecoder) {
|
||||||
// Re-initialization is required because newSession might require switching to the secure
|
// Re-initialization is required because newSession might require switching to the secure
|
||||||
// output path.
|
// output path.
|
||||||
return true;
|
return true;
|
||||||
@ -2108,32 +2115,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a {@link DrmSession} may require a secure decoder for a given {@link Format}.
|
|
||||||
*
|
|
||||||
* @param sessionMediaCrypto The {@link DrmSession}'s {@link FrameworkMediaCrypto}.
|
|
||||||
* @param format The {@link Format}.
|
|
||||||
* @return Whether a secure decoder may be required.
|
|
||||||
*/
|
|
||||||
private boolean maybeRequiresSecureDecoder(
|
|
||||||
FrameworkMediaCrypto sessionMediaCrypto, Format format) {
|
|
||||||
if (sessionMediaCrypto.forceAllowInsecureDecoderComponents) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
MediaCrypto mediaCrypto;
|
|
||||||
try {
|
|
||||||
mediaCrypto = new MediaCrypto(sessionMediaCrypto.uuid, sessionMediaCrypto.sessionId);
|
|
||||||
} catch (MediaCryptoException e) {
|
|
||||||
// This shouldn't happen, but if it does then assume that a secure decoder may be required.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return mediaCrypto.requiresSecureDecoderComponent(format.sampleMimeType);
|
|
||||||
} finally {
|
|
||||||
mediaCrypto.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reinitializeCodec() throws ExoPlaybackException {
|
private void reinitializeCodec() throws ExoPlaybackException {
|
||||||
releaseCodec();
|
releaseCodec();
|
||||||
maybeInitCodecOrBypass();
|
maybeInitCodecOrBypass();
|
||||||
|
@ -272,6 +272,11 @@ public final class FakeExoMediaDrm implements ExoMediaDrm {
|
|||||||
: KEY_STATUS_UNAVAILABLE);
|
: KEY_STATUS_UNAVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresSecureDecoder(byte[] sessionId, String mimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acquire() {
|
public void acquire() {
|
||||||
Assertions.checkState(referenceCount > 0);
|
Assertions.checkState(referenceCount > 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user