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