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 org.mozilla.thirdparty.com.google.android.exoplayer2.drm;
17 
18 import android.media.MediaDrm;
19 import androidx.annotation.IntDef;
20 import androidx.annotation.Nullable;
21 import java.io.IOException;
22 import java.lang.annotation.Documented;
23 import java.lang.annotation.Retention;
24 import java.lang.annotation.RetentionPolicy;
25 import java.util.Map;
26 
27 /**
28  * A DRM session.
29  */
30 public interface DrmSession<T extends ExoMediaCrypto> {
31 
32   /**
33    * Invokes {@code newSession's} {@link #acquire()} and {@code previousSession's} {@link
34    * #release()} in that order. Null arguments are ignored. Does nothing if {@code previousSession}
35    * and {@code newSession} are the same session.
36    */
replaceSession( @ullable DrmSession<T> previousSession, @Nullable DrmSession<T> newSession)37   static <T extends ExoMediaCrypto> void replaceSession(
38       @Nullable DrmSession<T> previousSession, @Nullable DrmSession<T> newSession) {
39     if (previousSession == newSession) {
40       // Do nothing.
41       return;
42     }
43     if (newSession != null) {
44       newSession.acquire();
45     }
46     if (previousSession != null) {
47       previousSession.release();
48     }
49   }
50 
51   /** Wraps the throwable which is the cause of the error state. */
52   class DrmSessionException extends IOException {
53 
DrmSessionException(Throwable cause)54     public DrmSessionException(Throwable cause) {
55       super(cause);
56     }
57 
58   }
59 
60   /**
61    * The state of the DRM session. One of {@link #STATE_RELEASED}, {@link #STATE_ERROR}, {@link
62    * #STATE_OPENING}, {@link #STATE_OPENED} or {@link #STATE_OPENED_WITH_KEYS}.
63    */
64   @Documented
65   @Retention(RetentionPolicy.SOURCE)
66   @IntDef({STATE_RELEASED, STATE_ERROR, STATE_OPENING, STATE_OPENED, STATE_OPENED_WITH_KEYS})
67   @interface State {}
68   /**
69    * The session has been released.
70    */
71   int STATE_RELEASED = 0;
72   /**
73    * The session has encountered an error. {@link #getError()} can be used to retrieve the cause.
74    */
75   int STATE_ERROR = 1;
76   /**
77    * The session is being opened.
78    */
79   int STATE_OPENING = 2;
80   /** The session is open, but does not have keys required for decryption. */
81   int STATE_OPENED = 3;
82   /** The session is open and has keys required for decryption. */
83   int STATE_OPENED_WITH_KEYS = 4;
84 
85   /**
86    * Returns the current state of the session, which is one of {@link #STATE_ERROR},
87    * {@link #STATE_RELEASED}, {@link #STATE_OPENING}, {@link #STATE_OPENED} and
88    * {@link #STATE_OPENED_WITH_KEYS}.
89    */
getState()90   @State int getState();
91 
92   /** Returns whether this session allows playback of clear samples prior to keys being loaded. */
playClearSamplesWithoutKeys()93   default boolean playClearSamplesWithoutKeys() {
94     return false;
95   }
96 
97   /**
98    * Returns the cause of the error state, or null if {@link #getState()} is not {@link
99    * #STATE_ERROR}.
100    */
101   @Nullable
getError()102   DrmSessionException getError();
103 
104   /**
105    * Returns a {@link ExoMediaCrypto} for the open session, or null if called before the session has
106    * been opened or after it's been released.
107    */
108   @Nullable
getMediaCrypto()109   T getMediaCrypto();
110 
111   /**
112    * Returns a map describing the key status for the session, or null if called before the session
113    * has been opened or after it's been released.
114    *
115    * <p>Since DRM license policies vary by vendor, the specific status field names are determined by
116    * each DRM vendor. Refer to your DRM provider documentation for definitions of the field names
117    * for a particular DRM engine plugin.
118    *
119    * @return A map describing the key status for the session, or null if called before the session
120    *     has been opened or after it's been released.
121    * @see MediaDrm#queryKeyStatus(byte[])
122    */
123   @Nullable
queryKeyStatus()124   Map<String, String> queryKeyStatus();
125 
126   /**
127    * Returns the key set id of the offline license loaded into this session, or null if there isn't
128    * one.
129    */
130   @Nullable
getOfflineLicenseKeySetId()131   byte[] getOfflineLicenseKeySetId();
132 
133   /**
134    * Increments the reference count. When the caller no longer needs to use the instance, it must
135    * call {@link #release()} to decrement the reference count.
136    */
acquire()137   void acquire();
138 
139   /**
140    * Decrements the reference count. If the reference count drops to 0 underlying resources are
141    * released, and the instance cannot be re-used.
142    */
release()143   void release();
144 }
145