Move DRM error code assignment into DefaultDrmSession

PiperOrigin-RevId: 384280087
This commit is contained in:
aquilescanta 2021-07-12 19:36:05 +01:00 committed by Oliver Woodman
parent 8451be1b0b
commit cdaf3e4e99
3 changed files with 95 additions and 82 deletions

View File

@ -19,10 +19,6 @@ import static com.google.android.exoplayer2.util.Util.castNonNull;
import static java.lang.Math.max;
import static java.lang.Math.min;
import android.media.DeniedByServerException;
import android.media.MediaDrm;
import android.media.MediaDrmResetException;
import android.media.NotProvisionedException;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@ -43,9 +39,7 @@ import com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason;
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
import com.google.android.exoplayer2.Player.RepeatMode;
import com.google.android.exoplayer2.analytics.AnalyticsCollector;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.UnsupportedDrmException;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.MediaPeriod;
@ -590,27 +584,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
playbackInfo = playbackInfo.copyWithPlaybackError(e);
}
} catch (DrmSession.DrmSessionException e) {
@Nullable Throwable cause = e.getCause();
@ErrorCode int errorCode;
if (Util.SDK_INT >= 21 && PlatformOperationsWrapperV21.isMediaDrmStateException(cause)) {
errorCode = PlatformOperationsWrapperV21.mediaDrmStateExceptionToErrorCode(cause);
} else if (Util.SDK_INT >= 23
&& PlatformOperationsWrapperV23.isMediaDrmResetException(cause)) {
errorCode = PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR;
} else if (Util.SDK_INT >= 18
&& PlatformOperationsWrapperV18.isNotProvisionedException(cause)) {
errorCode = PlaybackException.ERROR_CODE_DRM_PROVISIONING_FAILED;
} else if (Util.SDK_INT >= 18
&& PlatformOperationsWrapperV18.isDeniedByServerException(cause)) {
errorCode = PlaybackException.ERROR_CODE_DRM_DEVICE_REVOKED;
} else if (cause instanceof UnsupportedDrmException) {
errorCode = PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED;
} else if (cause instanceof DefaultDrmSessionManager.MissingSchemeDataException) {
errorCode = PlaybackException.ERROR_CODE_DRM_CONTENT_ERROR;
} else {
errorCode = PlaybackException.ERROR_CODE_DRM_UNSPECIFIED;
}
handleIoException(e, errorCode);
handleIoException(e, e.errorCode);
} catch (FileDataSource.FileDataSourceException e) {
@Nullable Throwable cause = e.getCause();
@ErrorCode int errorCode;
@ -3092,20 +3066,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
}
@RequiresApi(18)
private static final class PlatformOperationsWrapperV18 {
@DoNotInline
public static boolean isNotProvisionedException(@Nullable Throwable throwable) {
return throwable instanceof NotProvisionedException;
}
@DoNotInline
public static boolean isDeniedByServerException(@Nullable Throwable throwable) {
return throwable instanceof DeniedByServerException;
}
}
@RequiresApi(21)
private static final class PlatformOperationsWrapperV21 {
@ -3113,28 +3073,5 @@ import java.util.concurrent.atomic.AtomicBoolean;
public static boolean isPermissionError(@Nullable Throwable e) {
return e instanceof ErrnoException && ((ErrnoException) e).errno == OsConstants.EACCES;
}
@DoNotInline
public static boolean isMediaDrmStateException(@Nullable Throwable throwable) {
return throwable instanceof MediaDrm.MediaDrmStateException;
}
@DoNotInline
@ErrorCode
public static int mediaDrmStateExceptionToErrorCode(Throwable throwable) {
@Nullable
String diagnosticsInfo = ((MediaDrm.MediaDrmStateException) throwable).getDiagnosticInfo();
int drmErrorCode = Util.getErrorCodeFromPlatformDiagnosticsInfo(diagnosticsInfo);
return C.getErrorCodeForMediaDrmErrorCode(drmErrorCode);
}
}
@RequiresApi(23)
private static final class PlatformOperationsWrapperV23 {
@DoNotInline
public static boolean isMediaDrmResetException(@Nullable Throwable throwable) {
return throwable instanceof MediaDrmResetException;
}
}
}

View File

@ -19,6 +19,9 @@ import static com.google.android.exoplayer2.util.Assertions.checkState;
import static java.lang.Math.min;
import android.annotation.SuppressLint;
import android.media.DeniedByServerException;
import android.media.MediaDrm;
import android.media.MediaDrmResetException;
import android.media.NotProvisionedException;
import android.os.Handler;
import android.os.HandlerThread;
@ -26,6 +29,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Pair;
import androidx.annotation.DoNotInline;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
@ -83,8 +87,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* Called by a session when it fails to perform a provisioning operation.
*
* @param error The error that occurred.
* @param thrownByExoMediaDrm Whether the error originated in an {@link ExoMediaDrm} operation.
* False when the error originated in the provisioning request.
*/
void onProvisionError(Exception error);
void onProvisionError(Exception error, boolean thrownByExoMediaDrm);
/** Called by a session when it successfully completes a provisioning operation. */
void onProvisionCompleted();
@ -236,8 +242,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
}
public void onProvisionError(Exception error) {
onError(error);
public void onProvisionError(Exception error, boolean thrownByExoMediaDrm) {
onError(error, thrownByExoMediaDrm);
}
// DrmSession implementation.
@ -360,7 +366,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} catch (NotProvisionedException e) {
provisioningManager.provisionRequired(this);
} catch (Exception e) {
onError(e);
onError(e, /* thrownByExoMediaDrm= */ true);
}
return false;
@ -374,14 +380,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
currentProvisionRequest = null;
if (response instanceof Exception) {
provisioningManager.onProvisionError((Exception) response);
provisioningManager.onProvisionError((Exception) response, /* thrownByExoMediaDrm= */ false);
return;
}
try {
mediaDrm.provideProvisionResponse((byte[]) response);
} catch (Exception e) {
provisioningManager.onProvisionError(e);
provisioningManager.onProvisionError(e, /* thrownByExoMediaDrm= */ true);
return;
}
@ -410,7 +416,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
+ licenseDurationRemainingSec);
postKeyRequest(sessionId, ExoMediaDrm.KEY_TYPE_OFFLINE, allowRetry);
} else if (licenseDurationRemainingSec <= 0) {
onError(new KeysExpiredException());
onError(new KeysExpiredException(), /* thrownByExoMediaDrm= */ false);
} else {
state = STATE_OPENED_WITH_KEYS;
dispatchEvent(DrmSessionEventListener.EventDispatcher::drmKeysRestored);
@ -438,7 +444,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
mediaDrm.restoreKeys(sessionId, offlineLicenseKeySetId);
return true;
} catch (Exception e) {
onError(e);
onError(e, /* thrownByExoMediaDrm= */ true);
}
return false;
}
@ -458,7 +464,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
Util.castNonNull(requestHandler)
.post(MSG_KEYS, Assertions.checkNotNull(currentKeyRequest), allowRetry);
} catch (Exception e) {
onKeysError(e);
onKeysError(e, /* thrownByExoMediaDrm= */ true);
}
}
@ -470,7 +476,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
currentKeyRequest = null;
if (response instanceof Exception) {
onKeysError((Exception) response);
onKeysError((Exception) response, /* thrownByExoMediaDrm= */ false);
return;
}
@ -492,7 +498,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
dispatchEvent(DrmSessionEventListener.EventDispatcher::drmKeysLoaded);
}
} catch (Exception e) {
onKeysError(e);
onKeysError(e, /* thrownByExoMediaDrm= */ true);
}
}
@ -503,17 +509,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
}
private void onKeysError(Exception e) {
private void onKeysError(Exception e, boolean thrownByExoMediaDrm) {
if (e instanceof NotProvisionedException) {
provisioningManager.provisionRequired(this);
} else {
onError(e);
onError(e, thrownByExoMediaDrm);
}
}
private void onError(final Exception e) {
// TODO(internal b/184262323): Add an argument here which takes the error code from the caller.
lastException = new DrmSessionException(e, PlaybackException.ERROR_CODE_DRM_UNSPECIFIED);
private void onError(Exception e, boolean thrownByExoMediaDrm) {
lastException =
new DrmSessionException(e, getErrorCodeForMediaDrmException(e, thrownByExoMediaDrm));
Log.e(TAG, "DRM session error", e);
dispatchEvent(eventDispatcher -> eventDispatcher.drmSessionManagerError(e));
if (state != STATE_OPENED_WITH_KEYS) {
@ -533,6 +539,35 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
}
@PlaybackException.ErrorCode
private static int getErrorCodeForMediaDrmException(
Exception exception, boolean thrownByExoMediaDrm) {
if (Util.SDK_INT >= 21 && PlatformOperationsWrapperV21.isMediaDrmStateException(exception)) {
return PlatformOperationsWrapperV21.mediaDrmStateExceptionToErrorCode(exception);
} else if (Util.SDK_INT >= 23
&& PlatformOperationsWrapperV23.isMediaDrmResetException(exception)) {
return PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR;
} else if (Util.SDK_INT >= 18
&& PlatformOperationsWrapperV18.isNotProvisionedException(exception)) {
return PlaybackException.ERROR_CODE_DRM_PROVISIONING_FAILED;
} else if (Util.SDK_INT >= 18
&& PlatformOperationsWrapperV18.isDeniedByServerException(exception)) {
return PlaybackException.ERROR_CODE_DRM_DEVICE_REVOKED;
} else if (exception instanceof UnsupportedDrmException) {
return PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED;
} else if (exception instanceof DefaultDrmSessionManager.MissingSchemeDataException) {
return PlaybackException.ERROR_CODE_DRM_CONTENT_ERROR;
} else if (exception instanceof KeysExpiredException) {
return PlaybackException.ERROR_CODE_DRM_LICENSE_EXPIRED;
} else if (thrownByExoMediaDrm) {
// A MediaDrm exception was thrown but it was impossible to determine the cause. Because no
// better diagnosis tools were provided, we treat this as a system error.
return PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR;
} else {
return PlaybackException.ERROR_CODE_DRM_UNSPECIFIED;
}
}
// Internal classes.
@SuppressLint("HandlerLeak")
@ -678,4 +713,45 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
this.request = request;
}
}
@RequiresApi(18)
private static final class PlatformOperationsWrapperV18 {
@DoNotInline
public static boolean isNotProvisionedException(@Nullable Throwable throwable) {
return throwable instanceof NotProvisionedException;
}
@DoNotInline
public static boolean isDeniedByServerException(@Nullable Throwable throwable) {
return throwable instanceof DeniedByServerException;
}
}
@RequiresApi(21)
private static final class PlatformOperationsWrapperV21 {
@DoNotInline
public static boolean isMediaDrmStateException(@Nullable Throwable throwable) {
return throwable instanceof MediaDrm.MediaDrmStateException;
}
@DoNotInline
@PlaybackException.ErrorCode
public static int mediaDrmStateExceptionToErrorCode(Throwable throwable) {
@Nullable
String diagnosticsInfo = ((MediaDrm.MediaDrmStateException) throwable).getDiagnosticInfo();
int drmErrorCode = Util.getErrorCodeFromPlatformDiagnosticsInfo(diagnosticsInfo);
return C.getErrorCodeForMediaDrmErrorCode(drmErrorCode);
}
}
@RequiresApi(23)
private static final class PlatformOperationsWrapperV23 {
@DoNotInline
public static boolean isMediaDrmResetException(@Nullable Throwable throwable) {
return throwable instanceof MediaDrmResetException;
}
}
}

View File

@ -876,14 +876,14 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
}
@Override
public void onProvisionError(Exception error) {
public void onProvisionError(Exception error, boolean thrownByExoMediaDrm) {
provisioningSession = null;
ImmutableList<DefaultDrmSession> sessionsToNotify =
ImmutableList.copyOf(sessionsAwaitingProvisioning);
// Clear the list before calling onProvisionError in case provisioning is re-requested.
sessionsAwaitingProvisioning.clear();
for (DefaultDrmSession session : sessionsToNotify) {
session.onProvisionError(error);
session.onProvisionError(error, thrownByExoMediaDrm);
}
}