1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.exoplayer2.drm; 17 18 import android.media.MediaDrm; 19 import androidx.annotation.IntDef; 20 import androidx.annotation.Nullable; 21 import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; 22 import java.io.IOException; 23 import java.lang.annotation.Documented; 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 import java.util.Map; 27 28 /** A DRM session. */ 29 public interface DrmSession { 30 31 /** 32 * Acquires {@code newSession} then releases {@code previousSession}. 33 * 34 * <p>Invokes {@code newSession's} {@link #acquire(MediaSourceEventDispatcher)} and {@code 35 * previousSession's} {@link #release(MediaSourceEventDispatcher)} in that order (passing {@code 36 * eventDispatcher = null}). Null arguments are ignored. Does nothing if {@code previousSession} 37 * and {@code newSession} are the same session. 38 */ replaceSession( @ullable DrmSession previousSession, @Nullable DrmSession newSession)39 static void replaceSession( 40 @Nullable DrmSession previousSession, @Nullable DrmSession newSession) { 41 if (previousSession == newSession) { 42 // Do nothing. 43 return; 44 } 45 if (newSession != null) { 46 newSession.acquire(/* eventDispatcher= */ null); 47 } 48 if (previousSession != null) { 49 previousSession.release(/* eventDispatcher= */ null); 50 } 51 } 52 53 /** Wraps the throwable which is the cause of the error state. */ 54 class DrmSessionException extends IOException { 55 DrmSessionException(Throwable cause)56 public DrmSessionException(Throwable cause) { 57 super(cause); 58 } 59 60 } 61 62 /** 63 * The state of the DRM session. One of {@link #STATE_RELEASED}, {@link #STATE_ERROR}, {@link 64 * #STATE_OPENING}, {@link #STATE_OPENED} or {@link #STATE_OPENED_WITH_KEYS}. 65 */ 66 @Documented 67 @Retention(RetentionPolicy.SOURCE) 68 @IntDef({STATE_RELEASED, STATE_ERROR, STATE_OPENING, STATE_OPENED, STATE_OPENED_WITH_KEYS}) 69 @interface State {} 70 /** 71 * The session has been released. 72 */ 73 int STATE_RELEASED = 0; 74 /** 75 * The session has encountered an error. {@link #getError()} can be used to retrieve the cause. 76 */ 77 int STATE_ERROR = 1; 78 /** 79 * The session is being opened. 80 */ 81 int STATE_OPENING = 2; 82 /** The session is open, but does not have keys required for decryption. */ 83 int STATE_OPENED = 3; 84 /** The session is open and has keys required for decryption. */ 85 int STATE_OPENED_WITH_KEYS = 4; 86 87 /** 88 * Returns the current state of the session, which is one of {@link #STATE_ERROR}, 89 * {@link #STATE_RELEASED}, {@link #STATE_OPENING}, {@link #STATE_OPENED} and 90 * {@link #STATE_OPENED_WITH_KEYS}. 91 */ getState()92 @State int getState(); 93 94 /** Returns whether this session allows playback of clear samples prior to keys being loaded. */ playClearSamplesWithoutKeys()95 default boolean playClearSamplesWithoutKeys() { 96 return false; 97 } 98 99 /** 100 * Returns the cause of the error state, or null if {@link #getState()} is not {@link 101 * #STATE_ERROR}. 102 */ 103 @Nullable getError()104 DrmSessionException getError(); 105 106 /** 107 * Returns an {@link ExoMediaCrypto} for the open session, or null if called before the session 108 * has been opened or after it's been released. 109 */ 110 @Nullable getMediaCrypto()111 ExoMediaCrypto getMediaCrypto(); 112 113 /** 114 * Returns a map describing the key status for the session, or null if called before the session 115 * has been opened or after it's been released. 116 * 117 * <p>Since DRM license policies vary by vendor, the specific status field names are determined by 118 * each DRM vendor. Refer to your DRM provider documentation for definitions of the field names 119 * for a particular DRM engine plugin. 120 * 121 * @return A map describing the key status for the session, or null if called before the session 122 * has been opened or after it's been released. 123 * @see MediaDrm#queryKeyStatus(byte[]) 124 */ 125 @Nullable queryKeyStatus()126 Map<String, String> queryKeyStatus(); 127 128 /** 129 * Returns the key set id of the offline license loaded into this session, or null if there isn't 130 * one. 131 */ 132 @Nullable getOfflineLicenseKeySetId()133 byte[] getOfflineLicenseKeySetId(); 134 135 /** 136 * Increments the reference count. When the caller no longer needs to use the instance, it must 137 * call {@link #release(MediaSourceEventDispatcher)} to decrement the reference count. 138 * 139 * @param eventDispatcher The {@link MediaSourceEventDispatcher} used to route DRM-related events 140 * dispatched from this session, or null if no event handling is needed. 141 */ acquire(@ullable MediaSourceEventDispatcher eventDispatcher)142 void acquire(@Nullable MediaSourceEventDispatcher eventDispatcher); 143 144 /** 145 * Decrements the reference count. If the reference count drops to 0 underlying resources are 146 * released, and the instance cannot be re-used. 147 * 148 * @param eventDispatcher The {@link MediaSourceEventDispatcher} to disconnect when the session is 149 * released (the same instance (possibly null) that was passed by the caller to {@link 150 * #acquire(MediaSourceEventDispatcher)}). 151 */ release(@ullable MediaSourceEventDispatcher eventDispatcher)152 void release(@Nullable MediaSourceEventDispatcher eventDispatcher); 153 } 154