• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 
17 package android.media;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.StringDef;
23 import android.annotation.SystemApi;
24 import android.app.ActivityThread;
25 import android.os.Handler;
26 import android.os.Looper;
27 import android.os.Message;
28 import android.os.Parcel;
29 import android.os.PersistableBundle;
30 import android.util.Log;
31 import dalvik.system.CloseGuard;
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 import java.lang.ref.WeakReference;
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.UUID;
39 import java.util.concurrent.atomic.AtomicBoolean;
40 
41 
42 /**
43  * MediaDrm can be used to obtain keys for decrypting protected media streams, in
44  * conjunction with {@link android.media.MediaCrypto}.  The MediaDrm APIs
45  * are designed to support the ISO/IEC 23001-7: Common Encryption standard, but
46  * may also be used to implement other encryption schemes.
47  * <p>
48  * Encrypted content is prepared using an encryption server and stored in a content
49  * library. The encrypted content is streamed or downloaded from the content library to
50  * client devices via content servers.  Licenses to view the content are obtained from
51  * a License Server.
52  * <p>
53  * <p><img src="../../../images/mediadrm_overview.png"
54  *      alt="MediaDrm Overview diagram"
55  *      border="0" /></p>
56  * <p>
57  * Keys are requested from the license server using a key request. The key
58  * response is delivered to the client app, which provides the response to the
59  * MediaDrm API.
60  * <p>
61  * A Provisioning server may be required to distribute device-unique credentials to
62  * the devices.
63  * <p>
64  * Enforcing requirements related to the number of devices that may play content
65  * simultaneously can be performed either through key renewal or using the secure
66  * stop methods.
67  * <p>
68  * The following sequence diagram shows the interactions between the objects
69  * involved while playing back encrypted content:
70  * <p>
71  * <p><img src="../../../images/mediadrm_decryption_sequence.png"
72  *         alt="MediaDrm Overview diagram"
73  *         border="0" /></p>
74  * <p>
75  * The app first constructs {@link android.media.MediaExtractor} and
76  * {@link android.media.MediaCodec} objects. It accesses the DRM-scheme-identifying UUID,
77  * typically from metadata in the content, and uses this UUID to construct an instance
78  * of a MediaDrm object that is able to support the DRM scheme required by the content.
79  * Crypto schemes are assigned 16 byte UUIDs.  The method {@link #isCryptoSchemeSupported}
80  * can be used to query if a given scheme is supported on the device.
81  * <p>
82  * The app calls {@link #openSession} to generate a sessionId that will uniquely identify
83  * the session in subsequent interactions. The app next uses the MediaDrm object to
84  * obtain a key request message and send it to the license server, then provide
85  * the server's response to the MediaDrm object.
86  * <p>
87  * Once the app has a sessionId, it can construct a MediaCrypto object from the UUID and
88  * sessionId.  The MediaCrypto object is registered with the MediaCodec in the
89  * {@link MediaCodec#configure} method to enable the codec to decrypt content.
90  * <p>
91  * When the app has constructed {@link android.media.MediaExtractor},
92  * {@link android.media.MediaCodec} and {@link android.media.MediaCrypto} objects,
93  * it proceeds to pull samples from the extractor and queue them into the decoder.  For
94  * encrypted content, the samples returned from the extractor remain encrypted, they
95  * are only decrypted when the samples are delivered to the decoder.
96  * <p>
97  * MediaDrm methods throw {@link android.media.MediaDrm.MediaDrmStateException}
98  * when a method is called on a MediaDrm object that has had an unrecoverable failure
99  * in the DRM plugin or security hardware.
100  * {@link android.media.MediaDrm.MediaDrmStateException} extends
101  * {@link java.lang.IllegalStateException} with the addition of a developer-readable
102  * diagnostic information string associated with the exception.
103  * <p>
104  * In the event of a mediaserver process crash or restart while a MediaDrm object
105  * is active, MediaDrm methods may throw {@link android.media.MediaDrmResetException}.
106  * To recover, the app must release the MediaDrm object, then create and initialize
107  * a new one.
108  * <p>
109  * As {@link android.media.MediaDrmResetException} and
110  * {@link android.media.MediaDrm.MediaDrmStateException} both extend
111  * {@link java.lang.IllegalStateException}, they should be in an earlier catch()
112  * block than {@link java.lang.IllegalStateException} if handled separately.
113  * <p>
114  * <a name="Callbacks"></a>
115  * <h3>Callbacks</h3>
116  * <p>Applications should register for informational events in order
117  * to be informed of key state updates during playback or streaming.
118  * Registration for these events is done via a call to
119  * {@link #setOnEventListener}. In order to receive the respective
120  * callback associated with this listener, applications are required to create
121  * MediaDrm objects on a thread with its own Looper running (main UI
122  * thread by default has a Looper running).
123  */
124 public final class MediaDrm implements AutoCloseable {
125 
126     private static final String TAG = "MediaDrm";
127 
128     private final AtomicBoolean mClosed = new AtomicBoolean();
129     private final CloseGuard mCloseGuard = CloseGuard.get();
130 
131     private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
132 
133     private EventHandler mEventHandler;
134     private EventHandler mOnKeyStatusChangeEventHandler;
135     private EventHandler mOnExpirationUpdateEventHandler;
136     private OnEventListener mOnEventListener;
137     private OnKeyStatusChangeListener mOnKeyStatusChangeListener;
138     private OnExpirationUpdateListener mOnExpirationUpdateListener;
139 
140     private long mNativeContext;
141 
142     /**
143      * Specify no certificate type
144      *
145      * @hide - not part of the public API at this time
146      */
147     public static final int CERTIFICATE_TYPE_NONE = 0;
148 
149     /**
150      * Specify X.509 certificate type
151      *
152      * @hide - not part of the public API at this time
153      */
154     public static final int CERTIFICATE_TYPE_X509 = 1;
155 
156     /** @hide */
157     @IntDef({
158         CERTIFICATE_TYPE_NONE,
159         CERTIFICATE_TYPE_X509,
160     })
161     @Retention(RetentionPolicy.SOURCE)
162     public @interface CertificateType {}
163 
164     /**
165      * Query if the given scheme identified by its UUID is supported on
166      * this device.
167      * @param uuid The UUID of the crypto scheme.
168      */
isCryptoSchemeSupported(@onNull UUID uuid)169     public static final boolean isCryptoSchemeSupported(@NonNull UUID uuid) {
170         return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), null);
171     }
172 
173     /**
174      * Query if the given scheme identified by its UUID is supported on
175      * this device, and whether the DRM plugin is able to handle the
176      * media container format specified by mimeType.
177      * @param uuid The UUID of the crypto scheme.
178      * @param mimeType The MIME type of the media container, e.g. "video/mp4"
179      *   or "video/webm"
180      */
isCryptoSchemeSupported( @onNull UUID uuid, @NonNull String mimeType)181     public static final boolean isCryptoSchemeSupported(
182             @NonNull UUID uuid, @NonNull String mimeType) {
183         return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), mimeType);
184     }
185 
getByteArrayFromUUID(@onNull UUID uuid)186     private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
187         long msb = uuid.getMostSignificantBits();
188         long lsb = uuid.getLeastSignificantBits();
189 
190         byte[] uuidBytes = new byte[16];
191         for (int i = 0; i < 8; ++i) {
192             uuidBytes[i] = (byte)(msb >>> (8 * (7 - i)));
193             uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i)));
194         }
195 
196         return uuidBytes;
197     }
198 
isCryptoSchemeSupportedNative( @onNull byte[] uuid, @Nullable String mimeType)199     private static final native boolean isCryptoSchemeSupportedNative(
200             @NonNull byte[] uuid, @Nullable String mimeType);
201 
202     /**
203      * Instantiate a MediaDrm object
204      *
205      * @param uuid The UUID of the crypto scheme.
206      *
207      * @throws UnsupportedSchemeException if the device does not support the
208      * specified scheme UUID
209      */
MediaDrm(@onNull UUID uuid)210     public MediaDrm(@NonNull UUID uuid) throws UnsupportedSchemeException {
211         Looper looper;
212         if ((looper = Looper.myLooper()) != null) {
213             mEventHandler = new EventHandler(this, looper);
214         } else if ((looper = Looper.getMainLooper()) != null) {
215             mEventHandler = new EventHandler(this, looper);
216         } else {
217             mEventHandler = null;
218         }
219 
220         /* Native setup requires a weak reference to our object.
221          * It's easier to create it here than in C++.
222          */
223         native_setup(new WeakReference<MediaDrm>(this),
224                 getByteArrayFromUUID(uuid),  ActivityThread.currentOpPackageName());
225 
226         mCloseGuard.open("release");
227     }
228 
229     /**
230      * Thrown when an unrecoverable failure occurs during a MediaDrm operation.
231      * Extends java.lang.IllegalStateException with the addition of an error
232      * code that may be useful in diagnosing the failure.
233      */
234     public static final class MediaDrmStateException extends java.lang.IllegalStateException {
235         private final int mErrorCode;
236         private final String mDiagnosticInfo;
237 
238         /**
239          * @hide
240          */
MediaDrmStateException(int errorCode, @Nullable String detailMessage)241         public MediaDrmStateException(int errorCode, @Nullable String detailMessage) {
242             super(detailMessage);
243             mErrorCode = errorCode;
244 
245             // TODO get this from DRM session
246             final String sign = errorCode < 0 ? "neg_" : "";
247             mDiagnosticInfo =
248                 "android.media.MediaDrm.error_" + sign + Math.abs(errorCode);
249 
250         }
251 
252         /**
253          * Retrieve the associated error code
254          *
255          * @hide
256          */
257         public int getErrorCode() {
258             return mErrorCode;
259         }
260 
261         /**
262          * Retrieve a developer-readable diagnostic information string
263          * associated with the exception. Do not show this to end-users,
264          * since this string will not be localized or generally comprehensible
265          * to end-users.
266          */
267         @NonNull
268         public String getDiagnosticInfo() {
269             return mDiagnosticInfo;
270         }
271     }
272 
273     /**
274      * Register a callback to be invoked when a session expiration update
275      * occurs.  The app's OnExpirationUpdateListener will be notified
276      * when the expiration time of the keys in the session have changed.
277      * @param listener the callback that will be run, or {@code null} to unregister the
278      *     previously registered callback.
279      * @param handler the handler on which the listener should be invoked, or
280      *     {@code null} if the listener should be invoked on the calling thread's looper.
281      */
282     public void setOnExpirationUpdateListener(
283             @Nullable OnExpirationUpdateListener listener, @Nullable Handler handler) {
284         if (listener != null) {
285             Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
286             if (looper != null) {
287                 if (mEventHandler == null || mEventHandler.getLooper() != looper) {
288                     mEventHandler = new EventHandler(this, looper);
289                 }
290             }
291         }
292         mOnExpirationUpdateListener = listener;
293     }
294 
295     /**
296      * Interface definition for a callback to be invoked when a drm session
297      * expiration update occurs
298      */
299     public interface OnExpirationUpdateListener
300     {
301         /**
302          * Called when a session expiration update occurs, to inform the app
303          * about the change in expiration time
304          *
305          * @param md the MediaDrm object on which the event occurred
306          * @param sessionId the DRM session ID on which the event occurred
307          * @param expirationTime the new expiration time for the keys in the session.
308          *     The time is in milliseconds, relative to the Unix epoch.  A time of
309          *     0 indicates that the keys never expire.
310          */
311         void onExpirationUpdate(
312                 @NonNull MediaDrm md, @NonNull byte[] sessionId, long expirationTime);
313     }
314 
315     /**
316      * Register a callback to be invoked when the state of keys in a session
317      * change, e.g. when a license update occurs or when a license expires.
318      *
319      * @param listener the callback that will be run when key status changes, or
320      *     {@code null} to unregister the previously registered callback.
321      * @param handler the handler on which the listener should be invoked, or
322      *     null if the listener should be invoked on the calling thread's looper.
323      */
324     public void setOnKeyStatusChangeListener(
325             @Nullable OnKeyStatusChangeListener listener, @Nullable Handler handler) {
326         if (listener != null) {
327             Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
328             if (looper != null) {
329                 if (mEventHandler == null || mEventHandler.getLooper() != looper) {
330                     mEventHandler = new EventHandler(this, looper);
331                 }
332             }
333         }
334         mOnKeyStatusChangeListener = listener;
335     }
336 
337     /**
338      * Interface definition for a callback to be invoked when the keys in a drm
339      * session change states.
340      */
341     public interface OnKeyStatusChangeListener
342     {
343         /**
344          * Called when the keys in a session change status, such as when the license
345          * is renewed or expires.
346          *
347          * @param md the MediaDrm object on which the event occurred
348          * @param sessionId the DRM session ID on which the event occurred
349          * @param keyInformation a list of {@link MediaDrm.KeyStatus}
350          *     instances indicating the status for each key in the session
351          * @param hasNewUsableKey indicates if a key has been added that is usable,
352          *     which may trigger an attempt to resume playback on the media stream
353          *     if it is currently blocked waiting for a key.
354          */
355         void onKeyStatusChange(
356                 @NonNull MediaDrm md, @NonNull byte[] sessionId,
357                 @NonNull List<KeyStatus> keyInformation,
358                 boolean hasNewUsableKey);
359     }
360 
361     /**
362      * Defines the status of a key.
363      * A KeyStatus for each key in a session is provided to the
364      * {@link OnKeyStatusChangeListener#onKeyStatusChange}
365      * listener.
366      */
367     public static final class KeyStatus {
368         private final byte[] mKeyId;
369         private final int mStatusCode;
370 
371         /**
372          * The key is currently usable to decrypt media data
373          */
374         public static final int STATUS_USABLE = 0;
375 
376         /**
377          * The key is no longer usable to decrypt media data because its
378          * expiration time has passed.
379          */
380         public static final int STATUS_EXPIRED = 1;
381 
382         /**
383          * The key is not currently usable to decrypt media data because its
384          * output requirements cannot currently be met.
385          */
386         public static final int STATUS_OUTPUT_NOT_ALLOWED = 2;
387 
388         /**
389          * The status of the key is not yet known and is being determined.
390          * The status will be updated with the actual status when it has
391          * been determined.
392          */
393         public static final int STATUS_PENDING = 3;
394 
395         /**
396          * The key is not currently usable to decrypt media data because of an
397          * internal error in processing unrelated to input parameters.  This error
398          * is not actionable by an app.
399          */
400         public static final int STATUS_INTERNAL_ERROR = 4;
401 
402         /** @hide */
403         @IntDef({
404             STATUS_USABLE,
405             STATUS_EXPIRED,
406             STATUS_OUTPUT_NOT_ALLOWED,
407             STATUS_PENDING,
408             STATUS_INTERNAL_ERROR,
409         })
410         @Retention(RetentionPolicy.SOURCE)
411         public @interface KeyStatusCode {}
412 
413         KeyStatus(@NonNull byte[] keyId, @KeyStatusCode int statusCode) {
414             mKeyId = keyId;
415             mStatusCode = statusCode;
416         }
417 
418         /**
419          * Returns the status code for the key
420          * @return one of {@link #STATUS_USABLE}, {@link #STATUS_EXPIRED},
421          * {@link #STATUS_OUTPUT_NOT_ALLOWED}, {@link #STATUS_PENDING}
422          * or {@link #STATUS_INTERNAL_ERROR}.
423          */
424         @KeyStatusCode
425         public int getStatusCode() { return mStatusCode; }
426 
427         /**
428          * Returns the id for the key
429          */
430         @NonNull
431         public byte[] getKeyId() { return mKeyId; }
432     }
433 
434     /**
435      * Register a callback to be invoked when an event occurs
436      *
437      * @param listener the callback that will be run.  Use {@code null} to
438      *        stop receiving event callbacks.
439      */
440     public void setOnEventListener(@Nullable OnEventListener listener)
441     {
442         mOnEventListener = listener;
443     }
444 
445     /**
446      * Interface definition for a callback to be invoked when a drm event
447      * occurs
448      */
449     public interface OnEventListener
450     {
451         /**
452          * Called when an event occurs that requires the app to be notified
453          *
454          * @param md the MediaDrm object on which the event occurred
455          * @param sessionId the DRM session ID on which the event occurred,
456          *        or {@code null} if there is no session ID associated with the event.
457          * @param event indicates the event type
458          * @param extra an secondary error code
459          * @param data optional byte array of data that may be associated with the event
460          */
461         void onEvent(
462                 @NonNull MediaDrm md, @Nullable byte[] sessionId,
463                 @DrmEvent int event, int extra,
464                 @Nullable byte[] data);
465     }
466 
467     /**
468      * This event type indicates that the app needs to request a certificate from
469      * the provisioning server.  The request message data is obtained using
470      * {@link #getProvisionRequest}
471      *
472      * @deprecated Handle provisioning via {@link android.media.NotProvisionedException}
473      * instead.
474      */
475     public static final int EVENT_PROVISION_REQUIRED = 1;
476 
477     /**
478      * This event type indicates that the app needs to request keys from a license
479      * server.  The request message data is obtained using {@link #getKeyRequest}.
480      */
481     public static final int EVENT_KEY_REQUIRED = 2;
482 
483     /**
484      * This event type indicates that the licensed usage duration for keys in a session
485      * has expired.  The keys are no longer valid.
486      * @deprecated Use {@link OnKeyStatusChangeListener#onKeyStatusChange}
487      * and check for {@link MediaDrm.KeyStatus#STATUS_EXPIRED} in the {@link MediaDrm.KeyStatus}
488      * instead.
489      */
490     public static final int EVENT_KEY_EXPIRED = 3;
491 
492     /**
493      * This event may indicate some specific vendor-defined condition, see your
494      * DRM provider documentation for details
495      */
496     public static final int EVENT_VENDOR_DEFINED = 4;
497 
498     /**
499      * This event indicates that a session opened by the app has been reclaimed by the resource
500      * manager.
501      */
502     public static final int EVENT_SESSION_RECLAIMED = 5;
503 
504     /** @hide */
505     @IntDef({
506         EVENT_PROVISION_REQUIRED,
507         EVENT_KEY_REQUIRED,
508         EVENT_KEY_EXPIRED,
509         EVENT_VENDOR_DEFINED,
510         EVENT_SESSION_RECLAIMED,
511     })
512     @Retention(RetentionPolicy.SOURCE)
513     public @interface DrmEvent {}
514 
515     private static final int DRM_EVENT = 200;
516     private static final int EXPIRATION_UPDATE = 201;
517     private static final int KEY_STATUS_CHANGE = 202;
518 
519     private class EventHandler extends Handler
520     {
521         private MediaDrm mMediaDrm;
522 
523         public EventHandler(@NonNull MediaDrm md, @NonNull Looper looper) {
524             super(looper);
525             mMediaDrm = md;
526         }
527 
528         @Override
529         public void handleMessage(@NonNull Message msg) {
530             if (mMediaDrm.mNativeContext == 0) {
531                 Log.w(TAG, "MediaDrm went away with unhandled events");
532                 return;
533             }
534             switch(msg.what) {
535 
536             case DRM_EVENT:
537                 if (mOnEventListener != null) {
538                     if (msg.obj != null && msg.obj instanceof Parcel) {
539                         Parcel parcel = (Parcel)msg.obj;
540                         byte[] sessionId = parcel.createByteArray();
541                         if (sessionId.length == 0) {
542                             sessionId = null;
543                         }
544                         byte[] data = parcel.createByteArray();
545                         if (data.length == 0) {
546                             data = null;
547                         }
548 
549                         Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")");
550                         mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data);
551                     }
552                 }
553                 return;
554 
555             case KEY_STATUS_CHANGE:
556                 if (mOnKeyStatusChangeListener != null) {
557                     if (msg.obj != null && msg.obj instanceof Parcel) {
558                         Parcel parcel = (Parcel)msg.obj;
559                         byte[] sessionId = parcel.createByteArray();
560                         if (sessionId.length > 0) {
561                             List<KeyStatus> keyStatusList = keyStatusListFromParcel(parcel);
562                             boolean hasNewUsableKey = (parcel.readInt() != 0);
563 
564                             Log.i(TAG, "Drm key status changed");
565                             mOnKeyStatusChangeListener.onKeyStatusChange(mMediaDrm, sessionId,
566                                     keyStatusList, hasNewUsableKey);
567                         }
568                     }
569                 }
570                 return;
571 
572             case EXPIRATION_UPDATE:
573                 if (mOnExpirationUpdateListener != null) {
574                     if (msg.obj != null && msg.obj instanceof Parcel) {
575                         Parcel parcel = (Parcel)msg.obj;
576                         byte[] sessionId = parcel.createByteArray();
577                         if (sessionId.length > 0) {
578                             long expirationTime = parcel.readLong();
579 
580                             Log.i(TAG, "Drm key expiration update: " + expirationTime);
581                             mOnExpirationUpdateListener.onExpirationUpdate(mMediaDrm, sessionId,
582                                     expirationTime);
583                         }
584                     }
585                 }
586                 return;
587 
588             default:
589                 Log.e(TAG, "Unknown message type " + msg.what);
590                 return;
591             }
592         }
593     }
594 
595     /**
596      * Parse a list of KeyStatus objects from an event parcel
597      */
598     @NonNull
keyStatusListFromParcel(@onNull Parcel parcel)599     private List<KeyStatus> keyStatusListFromParcel(@NonNull Parcel parcel) {
600         int nelems = parcel.readInt();
601         List<KeyStatus> keyStatusList = new ArrayList(nelems);
602         while (nelems-- > 0) {
603             byte[] keyId = parcel.createByteArray();
604             int keyStatusCode = parcel.readInt();
605             keyStatusList.add(new KeyStatus(keyId, keyStatusCode));
606         }
607         return keyStatusList;
608     }
609 
610     /**
611      * This method is called from native code when an event occurs.  This method
612      * just uses the EventHandler system to post the event back to the main app thread.
613      * We use a weak reference to the original MediaPlayer object so that the native
614      * code is safe from the object disappearing from underneath it.  (This is
615      * the cookie passed to native_setup().)
616      */
postEventFromNative(@onNull Object mediadrm_ref, int what, int eventType, int extra, @Nullable Object obj)617     private static void postEventFromNative(@NonNull Object mediadrm_ref,
618             int what, int eventType, int extra, @Nullable Object obj)
619     {
620         MediaDrm md = (MediaDrm)((WeakReference<MediaDrm>)mediadrm_ref).get();
621         if (md == null) {
622             return;
623         }
624         if (md.mEventHandler != null) {
625             Message m = md.mEventHandler.obtainMessage(what, eventType, extra, obj);
626             md.mEventHandler.sendMessage(m);
627         }
628     }
629 
630     /**
631      * Open a new session with the MediaDrm object. A session ID is returned.
632      * By default, sessions are opened at the native security level of the device.
633      *
634      * @throws NotProvisionedException if provisioning is needed
635      * @throws ResourceBusyException if required resources are in use
636      */
637     @NonNull
openSession()638     public byte[] openSession() throws NotProvisionedException,
639             ResourceBusyException {
640         return openSession(getMaxSecurityLevel());
641     }
642 
643     /**
644      * Open a new session at a requested security level. The security level
645      * represents the robustness of the device's DRM implementation. By default,
646      * sessions are opened at the native security level of the device.
647      * Overriding the security level is necessary when the decrypted frames need
648      * to be manipulated, such as for image compositing. The security level
649      * parameter must be lower than the native level. Reducing the security
650      * level will typically limit the content to lower resolutions, as
651      * determined by the license policy. If the requested level is not
652      * supported, the next lower supported security level will be set. The level
653      * can be queried using {@link #getSecurityLevel}. A session
654      * ID is returned.
655      *
656      * @param level the new security level, one of
657      * {@link #SECURITY_LEVEL_SW_SECURE_CRYPTO},
658      * {@link #SECURITY_LEVEL_SW_SECURE_DECODE},
659      * {@link #SECURITY_LEVEL_HW_SECURE_CRYPTO},
660      * {@link #SECURITY_LEVEL_HW_SECURE_DECODE} or
661      * {@link #SECURITY_LEVEL_HW_SECURE_ALL}.
662      *
663      * @throws NotProvisionedException if provisioning is needed
664      * @throws ResourceBusyException if required resources are in use
665      * @throws IllegalArgumentException if the requested security level is
666      * higher than the native level or lower than the lowest supported level or
667      * if the device does not support specifying the security level when opening
668      * a session
669      */
670     @NonNull
openSession(@ecurityLevel int level)671     public native byte[] openSession(@SecurityLevel int level) throws
672             NotProvisionedException, ResourceBusyException;
673 
674     /**
675      * Close a session on the MediaDrm object that was previously opened
676      * with {@link #openSession}.
677      */
closeSession(@onNull byte[] sessionId)678     public native void closeSession(@NonNull byte[] sessionId);
679 
680     /**
681      * This key request type species that the keys will be for online use, they will
682      * not be saved to the device for subsequent use when the device is not connected
683      * to a network.
684      */
685     public static final int KEY_TYPE_STREAMING = 1;
686 
687     /**
688      * This key request type specifies that the keys will be for offline use, they
689      * will be saved to the device for use when the device is not connected to a network.
690      */
691     public static final int KEY_TYPE_OFFLINE = 2;
692 
693     /**
694      * This key request type specifies that previously saved offline keys should be released.
695      */
696     public static final int KEY_TYPE_RELEASE = 3;
697 
698     /** @hide */
699     @IntDef({
700         KEY_TYPE_STREAMING,
701         KEY_TYPE_OFFLINE,
702         KEY_TYPE_RELEASE,
703     })
704     @Retention(RetentionPolicy.SOURCE)
705     public @interface KeyType {}
706 
707     /**
708      * Contains the opaque data an app uses to request keys from a license server.
709      * These request types may or may not be generated by a given plugin. Refer
710      * to plugin vendor documentation for more information.
711      */
712     public static final class KeyRequest {
713         private byte[] mData;
714         private String mDefaultUrl;
715         private int mRequestType;
716 
717         /**
718          * Key request type is initial license request. A license request
719          * is necessary to load keys.
720          */
721         public static final int REQUEST_TYPE_INITIAL = 0;
722 
723         /**
724          * Key request type is license renewal. A license request is
725          * necessary to prevent the keys from expiring.
726          */
727         public static final int REQUEST_TYPE_RENEWAL = 1;
728 
729         /**
730          * Key request type is license release
731          */
732         public static final int REQUEST_TYPE_RELEASE = 2;
733 
734         /**
735          * Keys are already loaded and are available for use. No license request is necessary, and
736          * no key request data is returned.
737          */
738         public static final int REQUEST_TYPE_NONE = 3;
739 
740         /**
741          * Keys have been loaded but an additional license request is needed
742          * to update their values.
743          */
744         public static final int REQUEST_TYPE_UPDATE = 4;
745 
746         /** @hide */
747         @IntDef({
748             REQUEST_TYPE_INITIAL,
749             REQUEST_TYPE_RENEWAL,
750             REQUEST_TYPE_RELEASE,
751             REQUEST_TYPE_NONE,
752             REQUEST_TYPE_UPDATE,
753         })
754         @Retention(RetentionPolicy.SOURCE)
755         public @interface RequestType {}
756 
KeyRequest()757         KeyRequest() {}
758 
759         /**
760          * Get the opaque message data
761          */
762         @NonNull
getData()763         public byte[] getData() {
764             if (mData == null) {
765                 // this should never happen as mData is initialized in
766                 // JNI after construction of the KeyRequest object. The check
767                 // is needed here to guarantee @NonNull annotation.
768                 throw new RuntimeException("KeyRequest is not initialized");
769             }
770             return mData;
771         }
772 
773         /**
774          * Get the default URL to use when sending the key request message to a
775          * server, if known.  The app may prefer to use a different license
776          * server URL from other sources.
777          * This method returns an empty string if the default URL is not known.
778          */
779         @NonNull
getDefaultUrl()780         public String getDefaultUrl() {
781             if (mDefaultUrl == null) {
782                 // this should never happen as mDefaultUrl is initialized in
783                 // JNI after construction of the KeyRequest object. The check
784                 // is needed here to guarantee @NonNull annotation.
785                 throw new RuntimeException("KeyRequest is not initialized");
786             }
787             return mDefaultUrl;
788         }
789 
790         /**
791          * Get the type of the request
792          * @return one of {@link #REQUEST_TYPE_INITIAL},
793          * {@link #REQUEST_TYPE_RENEWAL}, {@link #REQUEST_TYPE_RELEASE},
794          * {@link #REQUEST_TYPE_NONE} or {@link #REQUEST_TYPE_UPDATE}
795          */
796         @RequestType
getRequestType()797         public int getRequestType() { return mRequestType; }
798     };
799 
800     /**
801      * A key request/response exchange occurs between the app and a license server
802      * to obtain or release keys used to decrypt encrypted content.
803      * <p>
804      * getKeyRequest() is used to obtain an opaque key request byte array that is
805      * delivered to the license server.  The opaque key request byte array is returned
806      * in KeyRequest.data.  The recommended URL to deliver the key request to is
807      * returned in KeyRequest.defaultUrl.
808      * <p>
809      * After the app has received the key request response from the server,
810      * it should deliver to the response to the MediaDrm instance using the method
811      * {@link #provideKeyResponse}.
812      *
813      * @param scope may be a sessionId or a keySetId, depending on the specified keyType.
814      * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE,
815      * scope should be set to the sessionId the keys will be provided to.  When the keyType
816      * is KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys
817      * being released. Releasing keys from a device invalidates them for all sessions.
818      * @param init container-specific data, its meaning is interpreted based on the
819      * mime type provided in the mimeType parameter.  It could contain, for example,
820      * the content ID, key ID or other data obtained from the content metadata that is
821      * required in generating the key request. May be null when keyType is
822      * KEY_TYPE_RELEASE or if the request is a renewal, i.e. not the first key
823      * request for the session.
824      * @param mimeType identifies the mime type of the content. May be null if the
825      * keyType is KEY_TYPE_RELEASE or if the request is a renewal, i.e. not the
826      * first key request for the session.
827      * @param keyType specifes the type of the request. The request may be to acquire
828      * keys for streaming or offline content, or to release previously acquired
829      * keys, which are identified by a keySetId.
830      * @param optionalParameters are included in the key request message to
831      * allow a client application to provide additional message parameters to the server.
832      * This may be {@code null} if no additional parameters are to be sent.
833      * @throws NotProvisionedException if reprovisioning is needed, due to a
834      * problem with the certifcate
835      */
836     @NonNull
getKeyRequest( @onNull byte[] scope, @Nullable byte[] init, @Nullable String mimeType, @KeyType int keyType, @Nullable HashMap<String, String> optionalParameters)837     public native KeyRequest getKeyRequest(
838             @NonNull byte[] scope, @Nullable byte[] init,
839             @Nullable String mimeType, @KeyType int keyType,
840             @Nullable HashMap<String, String> optionalParameters)
841             throws NotProvisionedException;
842 
843 
844     /**
845      * A key response is received from the license server by the app, then it is
846      * provided to the MediaDrm instance using provideKeyResponse.  When the
847      * response is for an offline key request, a keySetId is returned that can be
848      * used to later restore the keys to a new session with the method
849      * {@link #restoreKeys}.
850      * When the response is for a streaming or release request, an empty byte array
851      * is returned.
852      *
853      * @param scope may be a sessionId or keySetId depending on the type of the
854      * response.  Scope should be set to the sessionId when the response is for either
855      * streaming or offline key requests.  Scope should be set to the keySetId when
856      * the response is for a release request.
857      * @param response the byte array response from the server
858      * @return If the response is for an offline request, the keySetId for the offline
859      * keys will be returned. If the response is for a streaming or release request
860      * an empty byte array will be returned.
861      *
862      * @throws NotProvisionedException if the response indicates that
863      * reprovisioning is required
864      * @throws DeniedByServerException if the response indicates that the
865      * server rejected the request
866      */
867     @Nullable
provideKeyResponse( @onNull byte[] scope, @NonNull byte[] response)868     public native byte[] provideKeyResponse(
869             @NonNull byte[] scope, @NonNull byte[] response)
870             throws NotProvisionedException, DeniedByServerException;
871 
872 
873     /**
874      * Restore persisted offline keys into a new session.  keySetId identifies the
875      * keys to load, obtained from a prior call to {@link #provideKeyResponse}.
876      *
877      * @param sessionId the session ID for the DRM session
878      * @param keySetId identifies the saved key set to restore
879      */
restoreKeys(@onNull byte[] sessionId, @NonNull byte[] keySetId)880     public native void restoreKeys(@NonNull byte[] sessionId, @NonNull byte[] keySetId);
881 
882     /**
883      * Remove the current keys from a session.
884      *
885      * @param sessionId the session ID for the DRM session
886      */
removeKeys(@onNull byte[] sessionId)887     public native void removeKeys(@NonNull byte[] sessionId);
888 
889     /**
890      * Request an informative description of the key status for the session.  The status is
891      * in the form of {name, value} pairs.  Since DRM license policies vary by vendor,
892      * the specific status field names are determined by each DRM vendor.  Refer to your
893      * DRM provider documentation for definitions of the field names for a particular
894      * DRM plugin.
895      *
896      * @param sessionId the session ID for the DRM session
897      */
898     @NonNull
queryKeyStatus(@onNull byte[] sessionId)899     public native HashMap<String, String> queryKeyStatus(@NonNull byte[] sessionId);
900 
901     /**
902      * Contains the opaque data an app uses to request a certificate from a provisioning
903      * server
904      */
905     public static final class ProvisionRequest {
ProvisionRequest()906         ProvisionRequest() {}
907 
908         /**
909          * Get the opaque message data
910          */
911         @NonNull
getData()912         public byte[] getData() {
913             if (mData == null) {
914                 // this should never happen as mData is initialized in
915                 // JNI after construction of the KeyRequest object. The check
916                 // is needed here to guarantee @NonNull annotation.
917                 throw new RuntimeException("ProvisionRequest is not initialized");
918             }
919             return mData;
920         }
921 
922         /**
923          * Get the default URL to use when sending the provision request
924          * message to a server, if known. The app may prefer to use a different
925          * provisioning server URL obtained from other sources.
926          * This method returns an empty string if the default URL is not known.
927          */
928         @NonNull
getDefaultUrl()929         public String getDefaultUrl() {
930             if (mDefaultUrl == null) {
931                 // this should never happen as mDefaultUrl is initialized in
932                 // JNI after construction of the ProvisionRequest object. The check
933                 // is needed here to guarantee @NonNull annotation.
934                 throw new RuntimeException("ProvisionRequest is not initialized");
935             }
936             return mDefaultUrl;
937         }
938 
939         private byte[] mData;
940         private String mDefaultUrl;
941     }
942 
943     /**
944      * A provision request/response exchange occurs between the app and a provisioning
945      * server to retrieve a device certificate.  If provisionining is required, the
946      * EVENT_PROVISION_REQUIRED event will be sent to the event handler.
947      * getProvisionRequest is used to obtain the opaque provision request byte array that
948      * should be delivered to the provisioning server. The provision request byte array
949      * is returned in ProvisionRequest.data. The recommended URL to deliver the provision
950      * request to is returned in ProvisionRequest.defaultUrl.
951      */
952     @NonNull
getProvisionRequest()953     public ProvisionRequest getProvisionRequest() {
954         return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, "");
955     }
956 
957     @NonNull
getProvisionRequestNative(int certType, @NonNull String certAuthority)958     private native ProvisionRequest getProvisionRequestNative(int certType,
959            @NonNull String certAuthority);
960 
961     /**
962      * After a provision response is received by the app, it is provided to the
963      * MediaDrm instance using this method.
964      *
965      * @param response the opaque provisioning response byte array to provide to the
966      * MediaDrm instance.
967      *
968      * @throws DeniedByServerException if the response indicates that the
969      * server rejected the request
970      */
provideProvisionResponse(@onNull byte[] response)971     public void provideProvisionResponse(@NonNull byte[] response)
972             throws DeniedByServerException {
973         provideProvisionResponseNative(response);
974     }
975 
976     @NonNull
provideProvisionResponseNative(@onNull byte[] response)977     private native Certificate provideProvisionResponseNative(@NonNull byte[] response)
978             throws DeniedByServerException;
979 
980     /**
981      * Secure stops are a way to enforce limits on the number of concurrent
982      * streams per subscriber across devices. They provide secure monitoring of
983      * the lifetime of content decryption keys in MediaDrm sessions.
984      * <p>
985      * A secure stop is written to secure persistent memory when keys are loaded
986      * into a MediaDrm session. The secure stop state indicates that the keys
987      * are available for use. When playback completes and the keys are removed
988      * or the session is destroyed, the secure stop state is updated to indicate
989      * that keys are no longer usable.
990      * <p>
991      * After playback, the app can query the secure stop and send it in a
992      * message to the license server confirming that the keys are no longer
993      * active. The license server returns a secure stop release response
994      * message to the app which then deletes the secure stop from persistent
995      * memory using {@link #releaseSecureStops}.
996      * <p>
997      * Each secure stop has a unique ID that can be used to identify it during
998      * enumeration, access and removal.
999      * @return a list of all secure stops from secure persistent memory
1000      */
1001     @NonNull
getSecureStops()1002     public native List<byte[]> getSecureStops();
1003 
1004     /**
1005      * Return a list of all secure stop IDs currently in persistent memory.
1006      * The secure stop ID can be used to access or remove the corresponding
1007      * secure stop.
1008      *
1009      * @return a list of secure stop IDs
1010      */
1011     @NonNull
getSecureStopIds()1012     public native List<byte[]> getSecureStopIds();
1013 
1014     /**
1015      * Access a specific secure stop given its secure stop ID.
1016      * Each secure stop has a unique ID.
1017      *
1018      * @param ssid the ID of the secure stop to return
1019      * @return the secure stop identified by ssid
1020      */
1021     @NonNull
getSecureStop(@onNull byte[] ssid)1022     public native byte[] getSecureStop(@NonNull byte[] ssid);
1023 
1024     /**
1025      * Process the secure stop server response message ssRelease.  After
1026      * authenticating the message, remove the secure stops identified in the
1027      * response.
1028      *
1029      * @param ssRelease the server response indicating which secure stops to release
1030      */
releaseSecureStops(@onNull byte[] ssRelease)1031     public native void releaseSecureStops(@NonNull byte[] ssRelease);
1032 
1033     /**
1034      * Remove a specific secure stop without requiring a secure stop release message
1035      * from the license server.
1036      * @param ssid the ID of the secure stop to remove
1037      */
removeSecureStop(@onNull byte[] ssid)1038     public native void removeSecureStop(@NonNull byte[] ssid);
1039 
1040     /**
1041      * Remove all secure stops without requiring a secure stop release message from
1042      * the license server.
1043      *
1044      * This method was added in API 28. In API versions 18 through 27,
1045      * {@link #releaseAllSecureStops} should be called instead. There is no need to
1046      * do anything for API versions prior to 18.
1047      */
removeAllSecureStops()1048     public native void removeAllSecureStops();
1049 
1050     /**
1051      * Remove all secure stops without requiring a secure stop release message from
1052      * the license server.
1053      *
1054      * @deprecated Remove all secure stops using {@link #removeAllSecureStops} instead.
1055      */
releaseAllSecureStops()1056     public void releaseAllSecureStops() {
1057         removeAllSecureStops();;
1058     }
1059 
1060     @Retention(RetentionPolicy.SOURCE)
1061     @IntDef({HDCP_LEVEL_UNKNOWN, HDCP_NONE, HDCP_V1, HDCP_V2,
1062                         HDCP_V2_1, HDCP_V2_2, HDCP_NO_DIGITAL_OUTPUT})
1063     public @interface HdcpLevel {}
1064 
1065 
1066     /**
1067      * The DRM plugin did not report an HDCP level, or an error
1068      * occurred accessing it
1069      */
1070     public static final int HDCP_LEVEL_UNKNOWN = 0;
1071 
1072     /**
1073      * HDCP is not supported on this device, content is unprotected
1074      */
1075     public static final int HDCP_NONE = 1;
1076 
1077     /**
1078      * HDCP version 1.0
1079      */
1080     public static final int HDCP_V1 = 2;
1081 
1082     /**
1083      * HDCP version 2.0 Type 1.
1084      */
1085     public static final int HDCP_V2 = 3;
1086 
1087     /**
1088      * HDCP version 2.1 Type 1.
1089      */
1090     public static final int HDCP_V2_1 = 4;
1091 
1092     /**
1093      *  HDCP version 2.2 Type 1.
1094      */
1095     public static final int HDCP_V2_2 = 5;
1096 
1097     /**
1098      * No digital output, implicitly secure
1099      */
1100     public static final int HDCP_NO_DIGITAL_OUTPUT = Integer.MAX_VALUE;
1101 
1102     /**
1103      * Return the HDCP level negotiated with downstream receivers the
1104      * device is connected to. If multiple HDCP-capable displays are
1105      * simultaneously connected to separate interfaces, this method
1106      * returns the lowest negotiated level of all interfaces.
1107      * <p>
1108      * This method should only be used for informational purposes, not for
1109      * enforcing compliance with HDCP requirements. Trusted enforcement of
1110      * HDCP policies must be handled by the DRM system.
1111      * <p>
1112      * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE},
1113      * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2}
1114      * or {@link #HDCP_NO_DIGITAL_OUTPUT}.
1115      */
1116     @HdcpLevel
getConnectedHdcpLevel()1117     public native int getConnectedHdcpLevel();
1118 
1119     /**
1120      * Return the maximum supported HDCP level. The maximum HDCP level is a
1121      * constant for a given device, it does not depend on downstream receivers
1122      * that may be connected. If multiple HDCP-capable interfaces are present,
1123      * it indicates the highest of the maximum HDCP levels of all interfaces.
1124      * <p>
1125      * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE},
1126      * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2}
1127      * or {@link #HDCP_NO_DIGITAL_OUTPUT}.
1128      */
1129     @HdcpLevel
getMaxHdcpLevel()1130     public native int getMaxHdcpLevel();
1131 
1132     /**
1133      * Return the number of MediaDrm sessions that are currently opened
1134      * simultaneously among all MediaDrm instances for the active DRM scheme.
1135      * @return the number of open sessions.
1136      */
getOpenSessionCount()1137     public native int getOpenSessionCount();
1138 
1139     /**
1140      * Return the maximum number of MediaDrm sessions that may be opened
1141      * simultaneosly among all MediaDrm instances for the active DRM
1142      * scheme. The maximum number of sessions is not affected by any
1143      * sessions that may have already been opened.
1144      * @return maximum sessions.
1145      */
getMaxSessionCount()1146     public native int getMaxSessionCount();
1147 
1148     /**
1149      * Security level indicates the robustness of the device's DRM
1150      * implementation.
1151      */
1152     @Retention(RetentionPolicy.SOURCE)
1153     @IntDef({SECURITY_LEVEL_UNKNOWN, SECURITY_LEVEL_SW_SECURE_CRYPTO,
1154             SECURITY_LEVEL_SW_SECURE_DECODE, SECURITY_LEVEL_HW_SECURE_CRYPTO,
1155             SECURITY_LEVEL_HW_SECURE_DECODE, SECURITY_LEVEL_HW_SECURE_ALL})
1156     public @interface SecurityLevel {}
1157 
1158     /**
1159      * The DRM plugin did not report a security level, or an error occurred
1160      * accessing it
1161      */
1162     public static final int SECURITY_LEVEL_UNKNOWN = 0;
1163 
1164     /**
1165      * DRM key management uses software-based whitebox crypto.
1166      */
1167     public static final int SECURITY_LEVEL_SW_SECURE_CRYPTO = 1;
1168 
1169     /**
1170      * DRM key management and decoding use software-based whitebox crypto.
1171      */
1172     public static final int SECURITY_LEVEL_SW_SECURE_DECODE = 2;
1173 
1174     /**
1175      * DRM key management and crypto operations are performed within a hardware
1176      * backed trusted execution environment.
1177      */
1178     public static final int SECURITY_LEVEL_HW_SECURE_CRYPTO = 3;
1179 
1180     /**
1181      * DRM key management, crypto operations and decoding of content are
1182      * performed within a hardware backed trusted execution environment.
1183      */
1184     public static final int SECURITY_LEVEL_HW_SECURE_DECODE = 4;
1185 
1186     /**
1187      * DRM key management, crypto operations, decoding of content and all
1188      * handling of the media (compressed and uncompressed) is handled within a
1189      * hardware backed trusted execution environment.
1190      */
1191     public static final int SECURITY_LEVEL_HW_SECURE_ALL = 5;
1192 
1193     /**
1194      * The maximum security level supported by the device. This is the default
1195      * security level when a session is opened.
1196      * @hide
1197      */
1198     public static final int SECURITY_LEVEL_MAX = 6;
1199 
1200     /**
1201      * The maximum security level supported by the device. This is the default
1202      * security level when a session is opened.
1203      */
1204     @SecurityLevel
getMaxSecurityLevel()1205     public static final int getMaxSecurityLevel() {
1206         return SECURITY_LEVEL_MAX;
1207     }
1208 
1209     /**
1210      * Return the current security level of a session. A session has an initial
1211      * security level determined by the robustness of the DRM system's
1212      * implementation on the device. The security level may be changed at the
1213      * time a session is opened using {@link #openSession}.
1214      * @param sessionId the session to query.
1215      * <p>
1216      * @return one of {@link #SECURITY_LEVEL_UNKNOWN},
1217      * {@link #SECURITY_LEVEL_SW_SECURE_CRYPTO}, {@link #SECURITY_LEVEL_SW_SECURE_DECODE},
1218      * {@link #SECURITY_LEVEL_HW_SECURE_CRYPTO}, {@link #SECURITY_LEVEL_HW_SECURE_DECODE} or
1219      * {@link #SECURITY_LEVEL_HW_SECURE_ALL}.
1220      */
1221     @SecurityLevel
getSecurityLevel(@onNull byte[] sessionId)1222     public native int getSecurityLevel(@NonNull byte[] sessionId);
1223 
1224     /**
1225      * String property name: identifies the maker of the DRM plugin
1226      */
1227     public static final String PROPERTY_VENDOR = "vendor";
1228 
1229     /**
1230      * String property name: identifies the version of the DRM plugin
1231      */
1232     public static final String PROPERTY_VERSION = "version";
1233 
1234     /**
1235      * String property name: describes the DRM plugin
1236      */
1237     public static final String PROPERTY_DESCRIPTION = "description";
1238 
1239     /**
1240      * String property name: a comma-separated list of cipher and mac algorithms
1241      * supported by CryptoSession.  The list may be empty if the DRM
1242      * plugin does not support CryptoSession operations.
1243      */
1244     public static final String PROPERTY_ALGORITHMS = "algorithms";
1245 
1246     /** @hide */
1247     @StringDef(prefix = { "PROPERTY_" }, value = {
1248         PROPERTY_VENDOR,
1249         PROPERTY_VERSION,
1250         PROPERTY_DESCRIPTION,
1251         PROPERTY_ALGORITHMS,
1252     })
1253     @Retention(RetentionPolicy.SOURCE)
1254     public @interface StringProperty {}
1255 
1256     /**
1257      * Read a MediaDrm String property value, given the property name string.
1258      * <p>
1259      * Standard fields names are:
1260      * {@link #PROPERTY_VENDOR}, {@link #PROPERTY_VERSION},
1261      * {@link #PROPERTY_DESCRIPTION}, {@link #PROPERTY_ALGORITHMS}
1262      */
1263     @NonNull
getPropertyString(@onNull @tringProperty String propertyName)1264     public native String getPropertyString(@NonNull @StringProperty String propertyName);
1265 
1266     /**
1267      * Set a MediaDrm String property value, given the property name string
1268      * and new value for the property.
1269      */
setPropertyString(@onNull @tringProperty String propertyName, @NonNull String value)1270     public native void setPropertyString(@NonNull @StringProperty String propertyName,
1271             @NonNull String value);
1272 
1273     /**
1274      * Byte array property name: the device unique identifier is established during
1275      * device provisioning and provides a means of uniquely identifying each device.
1276      */
1277     public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId";
1278 
1279     /** @hide */
1280     @StringDef(prefix = { "PROPERTY_" }, value = {
1281         PROPERTY_DEVICE_UNIQUE_ID,
1282     })
1283     @Retention(RetentionPolicy.SOURCE)
1284     public @interface ArrayProperty {}
1285 
1286     /**
1287      * Read a MediaDrm byte array property value, given the property name string.
1288      * <p>
1289      * Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID}
1290      */
1291     @NonNull
1292     public native byte[] getPropertyByteArray(@ArrayProperty String propertyName);
1293 
1294     /**
1295     * Set a MediaDrm byte array property value, given the property name string
1296     * and new value for the property.
1297     */
setPropertyByteArray(@onNull @rrayProperty String propertyName, @NonNull byte[] value)1298     public native void setPropertyByteArray(@NonNull @ArrayProperty
1299             String propertyName, @NonNull byte[] value);
1300 
setCipherAlgorithmNative( @onNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm)1301     private static final native void setCipherAlgorithmNative(
1302             @NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm);
1303 
setMacAlgorithmNative( @onNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm)1304     private static final native void setMacAlgorithmNative(
1305             @NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm);
1306 
1307     @NonNull
encryptNative( @onNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull byte[] keyId, @NonNull byte[] input, @NonNull byte[] iv)1308     private static final native byte[] encryptNative(
1309             @NonNull MediaDrm drm, @NonNull byte[] sessionId,
1310             @NonNull byte[] keyId, @NonNull byte[] input, @NonNull byte[] iv);
1311 
1312     @NonNull
decryptNative( @onNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull byte[] keyId, @NonNull byte[] input, @NonNull byte[] iv)1313     private static final native byte[] decryptNative(
1314             @NonNull MediaDrm drm, @NonNull byte[] sessionId,
1315             @NonNull byte[] keyId, @NonNull byte[] input, @NonNull byte[] iv);
1316 
1317     @NonNull
signNative( @onNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull byte[] keyId, @NonNull byte[] message)1318     private static final native byte[] signNative(
1319             @NonNull MediaDrm drm, @NonNull byte[] sessionId,
1320             @NonNull byte[] keyId, @NonNull byte[] message);
1321 
verifyNative( @onNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull byte[] keyId, @NonNull byte[] message, @NonNull byte[] signature)1322     private static final native boolean verifyNative(
1323             @NonNull MediaDrm drm, @NonNull byte[] sessionId,
1324             @NonNull byte[] keyId, @NonNull byte[] message, @NonNull byte[] signature);
1325 
1326     /**
1327      * Return Metrics data about the current MediaDrm instance.
1328      *
1329      * @return a {@link PersistableBundle} containing the set of attributes and values
1330      * available for this instance of MediaDrm.
1331      * The attributes are described in {@link MetricsConstants}.
1332      *
1333      * Additional vendor-specific fields may also be present in
1334      * the return value.
1335      */
getMetrics()1336     public PersistableBundle getMetrics() {
1337         PersistableBundle bundle = getMetricsNative();
1338         return bundle;
1339     }
1340 
getMetricsNative()1341     private native PersistableBundle getMetricsNative();
1342 
1343     /**
1344      * In addition to supporting decryption of DASH Common Encrypted Media, the
1345      * MediaDrm APIs provide the ability to securely deliver session keys from
1346      * an operator's session key server to a client device, based on the factory-installed
1347      * root of trust, and then perform encrypt, decrypt, sign and verify operations
1348      * with the session key on arbitrary user data.
1349      * <p>
1350      * The CryptoSession class implements generic encrypt/decrypt/sign/verify methods
1351      * based on the established session keys.  These keys are exchanged using the
1352      * getKeyRequest/provideKeyResponse methods.
1353      * <p>
1354      * Applications of this capability could include securing various types of
1355      * purchased or private content, such as applications, books and other media,
1356      * photos or media delivery protocols.
1357      * <p>
1358      * Operators can create session key servers that are functionally similar to a
1359      * license key server, except that instead of receiving license key requests and
1360      * providing encrypted content keys which are used specifically to decrypt A/V media
1361      * content, the session key server receives session key requests and provides
1362      * encrypted session keys which can be used for general purpose crypto operations.
1363      * <p>
1364      * A CryptoSession is obtained using {@link #getCryptoSession}
1365      */
1366     public final class CryptoSession {
1367         private byte[] mSessionId;
1368 
CryptoSession(@onNull byte[] sessionId, @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)1369         CryptoSession(@NonNull byte[] sessionId,
1370                       @NonNull String cipherAlgorithm,
1371                       @NonNull String macAlgorithm)
1372         {
1373             mSessionId = sessionId;
1374             setCipherAlgorithmNative(MediaDrm.this, sessionId, cipherAlgorithm);
1375             setMacAlgorithmNative(MediaDrm.this, sessionId, macAlgorithm);
1376         }
1377 
1378         /**
1379          * Encrypt data using the CryptoSession's cipher algorithm
1380          *
1381          * @param keyid specifies which key to use
1382          * @param input the data to encrypt
1383          * @param iv the initialization vector to use for the cipher
1384          */
1385         @NonNull
encrypt( @onNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv)1386         public byte[] encrypt(
1387                 @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) {
1388             return encryptNative(MediaDrm.this, mSessionId, keyid, input, iv);
1389         }
1390 
1391         /**
1392          * Decrypt data using the CryptoSessions's cipher algorithm
1393          *
1394          * @param keyid specifies which key to use
1395          * @param input the data to encrypt
1396          * @param iv the initialization vector to use for the cipher
1397          */
1398         @NonNull
decrypt( @onNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv)1399         public byte[] decrypt(
1400                 @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) {
1401             return decryptNative(MediaDrm.this, mSessionId, keyid, input, iv);
1402         }
1403 
1404         /**
1405          * Sign data using the CryptoSessions's mac algorithm.
1406          *
1407          * @param keyid specifies which key to use
1408          * @param message the data for which a signature is to be computed
1409          */
1410         @NonNull
sign(@onNull byte[] keyid, @NonNull byte[] message)1411         public byte[] sign(@NonNull byte[] keyid, @NonNull byte[] message) {
1412             return signNative(MediaDrm.this, mSessionId, keyid, message);
1413         }
1414 
1415         /**
1416          * Verify a signature using the CryptoSessions's mac algorithm. Return true
1417          * if the signatures match, false if they do no.
1418          *
1419          * @param keyid specifies which key to use
1420          * @param message the data to verify
1421          * @param signature the reference signature which will be compared with the
1422          *        computed signature
1423          */
verify( @onNull byte[] keyid, @NonNull byte[] message, @NonNull byte[] signature)1424         public boolean verify(
1425                 @NonNull byte[] keyid, @NonNull byte[] message, @NonNull byte[] signature) {
1426             return verifyNative(MediaDrm.this, mSessionId, keyid, message, signature);
1427         }
1428     };
1429 
1430     /**
1431      * Obtain a CryptoSession object which can be used to encrypt, decrypt,
1432      * sign and verify messages or data using the session keys established
1433      * for the session using methods {@link #getKeyRequest} and
1434      * {@link #provideKeyResponse} using a session key server.
1435      *
1436      * @param sessionId the session ID for the session containing keys
1437      * to be used for encrypt, decrypt, sign and/or verify
1438      * @param cipherAlgorithm the algorithm to use for encryption and
1439      * decryption ciphers. The algorithm string conforms to JCA Standard
1440      * Names for Cipher Transforms and is case insensitive.  For example
1441      * "AES/CBC/NoPadding".
1442      * @param macAlgorithm the algorithm to use for sign and verify
1443      * The algorithm string conforms to JCA Standard Names for Mac
1444      * Algorithms and is case insensitive.  For example "HmacSHA256".
1445      * <p>
1446      * The list of supported algorithms for a DRM plugin can be obtained
1447      * using the method {@link #getPropertyString} with the property name
1448      * "algorithms".
1449      */
getCryptoSession( @onNull byte[] sessionId, @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)1450     public CryptoSession getCryptoSession(
1451             @NonNull byte[] sessionId,
1452             @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)
1453     {
1454         return new CryptoSession(sessionId, cipherAlgorithm, macAlgorithm);
1455     }
1456 
1457     /**
1458      * Contains the opaque data an app uses to request a certificate from a provisioning
1459      * server
1460      *
1461      * @hide - not part of the public API at this time
1462      */
1463     public static final class CertificateRequest {
1464         private byte[] mData;
1465         private String mDefaultUrl;
1466 
CertificateRequest(@onNull byte[] data, @NonNull String defaultUrl)1467         CertificateRequest(@NonNull byte[] data, @NonNull String defaultUrl) {
1468             mData = data;
1469             mDefaultUrl = defaultUrl;
1470         }
1471 
1472         /**
1473          * Get the opaque message data
1474          */
1475         @NonNull
getData()1476         public byte[] getData() { return mData; }
1477 
1478         /**
1479          * Get the default URL to use when sending the certificate request
1480          * message to a server, if known. The app may prefer to use a different
1481          * certificate server URL obtained from other sources.
1482          */
1483         @NonNull
getDefaultUrl()1484         public String getDefaultUrl() { return mDefaultUrl; }
1485     }
1486 
1487     /**
1488      * Generate a certificate request, specifying the certificate type
1489      * and authority. The response received should be passed to
1490      * provideCertificateResponse.
1491      *
1492      * @param certType Specifies the certificate type.
1493      *
1494      * @param certAuthority is passed to the certificate server to specify
1495      * the chain of authority.
1496      *
1497      * @hide - not part of the public API at this time
1498      */
1499     @NonNull
getCertificateRequest( @ertificateType int certType, @NonNull String certAuthority)1500     public CertificateRequest getCertificateRequest(
1501             @CertificateType int certType, @NonNull String certAuthority)
1502     {
1503         ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority);
1504         return new CertificateRequest(provisionRequest.getData(),
1505                 provisionRequest.getDefaultUrl());
1506     }
1507 
1508     /**
1509      * Contains the wrapped private key and public certificate data associated
1510      * with a certificate.
1511      *
1512      * @hide - not part of the public API at this time
1513      */
1514     public static final class Certificate {
Certificate()1515         Certificate() {}
1516 
1517         /**
1518          * Get the wrapped private key data
1519          */
1520         @NonNull
getWrappedPrivateKey()1521         public byte[] getWrappedPrivateKey() {
1522             if (mWrappedKey == null) {
1523                 // this should never happen as mWrappedKey is initialized in
1524                 // JNI after construction of the KeyRequest object. The check
1525                 // is needed here to guarantee @NonNull annotation.
1526                 throw new RuntimeException("Cerfificate is not initialized");
1527             }
1528             return mWrappedKey;
1529         }
1530 
1531         /**
1532          * Get the PEM-encoded certificate chain
1533          */
1534         @NonNull
getContent()1535         public byte[] getContent() {
1536             if (mCertificateData == null) {
1537                 // this should never happen as mCertificateData is initialized in
1538                 // JNI after construction of the KeyRequest object. The check
1539                 // is needed here to guarantee @NonNull annotation.
1540                 throw new RuntimeException("Cerfificate is not initialized");
1541             }
1542             return mCertificateData;
1543         }
1544 
1545         private byte[] mWrappedKey;
1546         private byte[] mCertificateData;
1547     }
1548 
1549 
1550     /**
1551      * Process a response from the certificate server.  The response
1552      * is obtained from an HTTP Post to the url provided by getCertificateRequest.
1553      * <p>
1554      * The public X509 certificate chain and wrapped private key are returned
1555      * in the returned Certificate objec.  The certificate chain is in PEM format.
1556      * The wrapped private key should be stored in application private
1557      * storage, and used when invoking the signRSA method.
1558      *
1559      * @param response the opaque certificate response byte array to provide to the
1560      * MediaDrm instance.
1561      *
1562      * @throws DeniedByServerException if the response indicates that the
1563      * server rejected the request
1564      *
1565      * @hide - not part of the public API at this time
1566      */
1567     @NonNull
provideCertificateResponse(@onNull byte[] response)1568     public Certificate provideCertificateResponse(@NonNull byte[] response)
1569             throws DeniedByServerException {
1570         return provideProvisionResponseNative(response);
1571     }
1572 
1573     @NonNull
signRSANative( @onNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm, @NonNull byte[] wrappedKey, @NonNull byte[] message)1574     private static final native byte[] signRSANative(
1575             @NonNull MediaDrm drm, @NonNull byte[] sessionId,
1576             @NonNull String algorithm, @NonNull byte[] wrappedKey, @NonNull byte[] message);
1577 
1578     /**
1579      * Sign data using an RSA key
1580      *
1581      * @param sessionId a sessionId obtained from openSession on the MediaDrm object
1582      * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
1583      * @param wrappedKey - the wrapped (encrypted) RSA private key obtained
1584      * from provideCertificateResponse
1585      * @param message the data for which a signature is to be computed
1586      *
1587      * @hide - not part of the public API at this time
1588      */
1589     @NonNull
signRSA( @onNull byte[] sessionId, @NonNull String algorithm, @NonNull byte[] wrappedKey, @NonNull byte[] message)1590     public byte[] signRSA(
1591             @NonNull byte[] sessionId, @NonNull String algorithm,
1592             @NonNull byte[] wrappedKey, @NonNull byte[] message) {
1593         return signRSANative(this, sessionId, algorithm, wrappedKey, message);
1594     }
1595 
1596     @Override
finalize()1597     protected void finalize() throws Throwable {
1598         try {
1599             if (mCloseGuard != null) {
1600                 mCloseGuard.warnIfOpen();
1601             }
1602             release();
1603         } finally {
1604             super.finalize();
1605         }
1606     }
1607 
1608     /**
1609      * Releases resources associated with the current session of
1610      * MediaDrm. It is considered good practice to call this method when
1611      * the {@link MediaDrm} object is no longer needed in your
1612      * application. After this method is called, {@link MediaDrm} is no
1613      * longer usable since it has lost all of its required resource.
1614      *
1615      * This method was added in API 28. In API versions 18 through 27, release()
1616      * should be called instead. There is no need to do anything for API
1617      * versions prior to 18.
1618      */
1619     @Override
close()1620     public void close() {
1621         release();
1622     }
1623 
1624     /**
1625      * @deprecated replaced by {@link #close()}.
1626      */
1627     @Deprecated
release()1628     public void release() {
1629         mCloseGuard.close();
1630         if (mClosed.compareAndSet(false, true)) {
1631             native_release();
1632         }
1633     }
1634 
1635     /** @hide */
native_release()1636     public native final void native_release();
1637 
native_init()1638     private static native final void native_init();
1639 
native_setup(Object mediadrm_this, byte[] uuid, String appPackageName)1640     private native final void native_setup(Object mediadrm_this, byte[] uuid,
1641             String appPackageName);
1642 
1643     static {
1644         System.loadLibrary("media_jni");
native_init()1645         native_init();
1646     }
1647 
1648     /**
1649      * Definitions for the metrics that are reported via the
1650      * {@link #getMetrics} call.
1651      */
1652     public final static class MetricsConstants
1653     {
MetricsConstants()1654         private MetricsConstants() {}
1655 
1656         /**
1657          * Key to extract the number of successful {@link #openSession} calls
1658          * from the {@link PersistableBundle} returned by a
1659          * {@link #getMetrics} call.
1660          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1661          */
1662         public static final String OPEN_SESSION_OK_COUNT
1663             = "drm.mediadrm.open_session.ok.count";
1664 
1665         /**
1666          * Key to extract the number of failed {@link #openSession} calls
1667          * from the {@link PersistableBundle} returned by a
1668          * {@link #getMetrics} call.
1669          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1670          */
1671         public static final String OPEN_SESSION_ERROR_COUNT
1672             = "drm.mediadrm.open_session.error.count";
1673 
1674         /**
1675          * Key to extract the list of error codes that were returned from
1676          * {@link #openSession} calls. The key is used to lookup the list
1677          * in the {@link PersistableBundle} returned by a {@link #getMetrics}
1678          * call.
1679          * The list is an array of Long values
1680          * ({@link android.os.BaseBundle#getLongArray}).
1681          */
1682         public static final String OPEN_SESSION_ERROR_LIST
1683             = "drm.mediadrm.open_session.error.list";
1684 
1685         /**
1686          * Key to extract the number of successful {@link #closeSession} calls
1687          * from the {@link PersistableBundle} returned by a
1688          * {@link #getMetrics} call.
1689          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1690          */
1691         public static final String CLOSE_SESSION_OK_COUNT
1692             = "drm.mediadrm.close_session.ok.count";
1693 
1694         /**
1695          * Key to extract the number of failed {@link #closeSession} calls
1696          * from the {@link PersistableBundle} returned by a
1697          * {@link #getMetrics} call.
1698          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1699          */
1700         public static final String CLOSE_SESSION_ERROR_COUNT
1701             = "drm.mediadrm.close_session.error.count";
1702 
1703         /**
1704          * Key to extract the list of error codes that were returned from
1705          * {@link #closeSession} calls. The key is used to lookup the list
1706          * in the {@link PersistableBundle} returned by a {@link #getMetrics}
1707          * call.
1708          * The list is an array of Long values
1709          * ({@link android.os.BaseBundle#getLongArray}).
1710          */
1711         public static final String CLOSE_SESSION_ERROR_LIST
1712             = "drm.mediadrm.close_session.error.list";
1713 
1714         /**
1715          * Key to extract the start times of sessions. Times are
1716          * represented as milliseconds since epoch (1970-01-01T00:00:00Z).
1717          * The start times are returned from the {@link PersistableBundle}
1718          * from a {@link #getMetrics} call.
1719          * The start times are returned as another {@link PersistableBundle}
1720          * containing the session ids as keys and the start times as long
1721          * values. Use {@link android.os.BaseBundle#keySet} to get the list of
1722          * session ids, and then {@link android.os.BaseBundle#getLong} to get
1723          * the start time for each session.
1724          */
1725         public static final String SESSION_START_TIMES_MS
1726             = "drm.mediadrm.session_start_times_ms";
1727 
1728         /**
1729          * Key to extract the end times of sessions. Times are
1730          * represented as milliseconds since epoch (1970-01-01T00:00:00Z).
1731          * The end times are returned from the {@link PersistableBundle}
1732          * from a {@link #getMetrics} call.
1733          * The end times are returned as another {@link PersistableBundle}
1734          * containing the session ids as keys and the end times as long
1735          * values. Use {@link android.os.BaseBundle#keySet} to get the list of
1736          * session ids, and then {@link android.os.BaseBundle#getLong} to get
1737          * the end time for each session.
1738          */
1739         public static final String SESSION_END_TIMES_MS
1740             = "drm.mediadrm.session_end_times_ms";
1741 
1742         /**
1743          * Key to extract the number of successful {@link #getKeyRequest} calls
1744          * from the {@link PersistableBundle} returned by a
1745          * {@link #getMetrics} call.
1746          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1747          */
1748         public static final String GET_KEY_REQUEST_OK_COUNT
1749             = "drm.mediadrm.get_key_request.ok.count";
1750 
1751         /**
1752          * Key to extract the number of failed {@link #getKeyRequest}
1753          * calls from the {@link PersistableBundle} returned by a
1754          * {@link #getMetrics} call.
1755          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1756          */
1757         public static final String GET_KEY_REQUEST_ERROR_COUNT
1758             = "drm.mediadrm.get_key_request.error.count";
1759 
1760         /**
1761          * Key to extract the list of error codes that were returned from
1762          * {@link #getKeyRequest} calls. The key is used to lookup the list
1763          * in the {@link PersistableBundle} returned by a {@link #getMetrics}
1764          * call.
1765          * The list is an array of Long values
1766          * ({@link android.os.BaseBundle#getLongArray}).
1767          */
1768         public static final String GET_KEY_REQUEST_ERROR_LIST
1769             = "drm.mediadrm.get_key_request.error.list";
1770 
1771         /**
1772          * Key to extract the average time in microseconds of calls to
1773          * {@link #getKeyRequest}. The value is retrieved from the
1774          * {@link PersistableBundle} returned from {@link #getMetrics}.
1775          * The time is a Long value ({@link android.os.BaseBundle#getLong}).
1776          */
1777         public static final String GET_KEY_REQUEST_OK_TIME_MICROS
1778             = "drm.mediadrm.get_key_request.ok.average_time_micros";
1779 
1780         /**
1781          * Key to extract the number of successful {@link #provideKeyResponse}
1782          * calls from the {@link PersistableBundle} returned by a
1783          * {@link #getMetrics} call.
1784          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1785          */
1786         public static final String PROVIDE_KEY_RESPONSE_OK_COUNT
1787             = "drm.mediadrm.provide_key_response.ok.count";
1788 
1789         /**
1790          * Key to extract the number of failed {@link #provideKeyResponse}
1791          * calls from the {@link PersistableBundle} returned by a
1792          * {@link #getMetrics} call.
1793          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1794          */
1795         public static final String PROVIDE_KEY_RESPONSE_ERROR_COUNT
1796             = "drm.mediadrm.provide_key_response.error.count";
1797 
1798         /**
1799          * Key to extract the list of error codes that were returned from
1800          * {@link #provideKeyResponse} calls. The key is used to lookup the
1801          * list in the {@link PersistableBundle} returned by a
1802          * {@link #getMetrics} call.
1803          * The list is an array of Long values
1804          * ({@link android.os.BaseBundle#getLongArray}).
1805          */
1806         public static final String PROVIDE_KEY_RESPONSE_ERROR_LIST
1807             = "drm.mediadrm.provide_key_response.error.list";
1808 
1809         /**
1810          * Key to extract the average time in microseconds of calls to
1811          * {@link #provideKeyResponse}. The valus is retrieved from the
1812          * {@link PersistableBundle} returned from {@link #getMetrics}.
1813          * The time is a Long value ({@link android.os.BaseBundle#getLong}).
1814          */
1815         public static final String PROVIDE_KEY_RESPONSE_OK_TIME_MICROS
1816             = "drm.mediadrm.provide_key_response.ok.average_time_micros";
1817 
1818         /**
1819          * Key to extract the number of successful {@link #getProvisionRequest}
1820          * calls from the {@link PersistableBundle} returned by a
1821          * {@link #getMetrics} call.
1822          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1823          */
1824         public static final String GET_PROVISION_REQUEST_OK_COUNT
1825             = "drm.mediadrm.get_provision_request.ok.count";
1826 
1827         /**
1828          * Key to extract the number of failed {@link #getProvisionRequest}
1829          * calls from the {@link PersistableBundle} returned by a
1830          * {@link #getMetrics} call.
1831          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1832          */
1833         public static final String GET_PROVISION_REQUEST_ERROR_COUNT
1834             = "drm.mediadrm.get_provision_request.error.count";
1835 
1836         /**
1837          * Key to extract the list of error codes that were returned from
1838          * {@link #getProvisionRequest} calls. The key is used to lookup the
1839          * list in the {@link PersistableBundle} returned by a
1840          * {@link #getMetrics} call.
1841          * The list is an array of Long values
1842          * ({@link android.os.BaseBundle#getLongArray}).
1843          */
1844         public static final String GET_PROVISION_REQUEST_ERROR_LIST
1845             = "drm.mediadrm.get_provision_request.error.list";
1846 
1847         /**
1848          * Key to extract the number of successful
1849          * {@link #provideProvisionResponse} calls from the
1850          * {@link PersistableBundle} returned by a {@link #getMetrics} call.
1851          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1852          */
1853         public static final String PROVIDE_PROVISION_RESPONSE_OK_COUNT
1854             = "drm.mediadrm.provide_provision_response.ok.count";
1855 
1856         /**
1857          * Key to extract the number of failed
1858          * {@link #provideProvisionResponse} calls from the
1859          * {@link PersistableBundle} returned by a {@link #getMetrics} call.
1860          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1861          */
1862         public static final String PROVIDE_PROVISION_RESPONSE_ERROR_COUNT
1863             = "drm.mediadrm.provide_provision_response.error.count";
1864 
1865         /**
1866          * Key to extract the list of error codes that were returned from
1867          * {@link #provideProvisionResponse} calls. The key is used to lookup
1868          * the list in the {@link PersistableBundle} returned by a
1869          * {@link #getMetrics} call.
1870          * The list is an array of Long values
1871          * ({@link android.os.BaseBundle#getLongArray}).
1872          */
1873         public static final String PROVIDE_PROVISION_RESPONSE_ERROR_LIST
1874             = "drm.mediadrm.provide_provision_response.error.list";
1875 
1876         /**
1877          * Key to extract the number of successful
1878          * {@link #getPropertyByteArray} calls were made with the
1879          * {@link #PROPERTY_DEVICE_UNIQUE_ID} value. The key is used to lookup
1880          * the value in the {@link PersistableBundle} returned by a
1881          * {@link #getMetrics} call.
1882          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1883          */
1884         public static final String GET_DEVICE_UNIQUE_ID_OK_COUNT
1885             = "drm.mediadrm.get_device_unique_id.ok.count";
1886 
1887         /**
1888          * Key to extract the number of failed
1889          * {@link #getPropertyByteArray} calls were made with the
1890          * {@link #PROPERTY_DEVICE_UNIQUE_ID} value. The key is used to lookup
1891          * the value in the {@link PersistableBundle} returned by a
1892          * {@link #getMetrics} call.
1893          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1894          */
1895         public static final String GET_DEVICE_UNIQUE_ID_ERROR_COUNT
1896             = "drm.mediadrm.get_device_unique_id.error.count";
1897 
1898         /**
1899          * Key to extract the list of error codes that were returned from
1900          * {@link #getPropertyByteArray} calls with the
1901          * {@link #PROPERTY_DEVICE_UNIQUE_ID} value. The key is used to lookup
1902          * the list in the {@link PersistableBundle} returned by a
1903          * {@link #getMetrics} call.
1904          * The list is an array of Long values
1905          * ({@link android.os.BaseBundle#getLongArray}).
1906          */
1907         public static final String GET_DEVICE_UNIQUE_ID_ERROR_LIST
1908             = "drm.mediadrm.get_device_unique_id.error.list";
1909 
1910         /**
1911          * Key to extraact the count of {@link KeyStatus#STATUS_EXPIRED} events
1912          * that occured. The count is extracted from the
1913          * {@link PersistableBundle} returned from a {@link #getMetrics} call.
1914          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1915          */
1916         public static final String KEY_STATUS_EXPIRED_COUNT
1917             = "drm.mediadrm.key_status.EXPIRED.count";
1918 
1919         /**
1920          * Key to extract the count of {@link KeyStatus#STATUS_INTERNAL_ERROR}
1921          * events that occured. The count is extracted from the
1922          * {@link PersistableBundle} returned from a {@link #getMetrics} call.
1923          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1924          */
1925         public static final String KEY_STATUS_INTERNAL_ERROR_COUNT
1926             = "drm.mediadrm.key_status.INTERNAL_ERROR.count";
1927 
1928         /**
1929          * Key to extract the count of
1930          * {@link KeyStatus#STATUS_OUTPUT_NOT_ALLOWED} events that occured.
1931          * The count is extracted from the
1932          * {@link PersistableBundle} returned from a {@link #getMetrics} call.
1933          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1934          */
1935         public static final String KEY_STATUS_OUTPUT_NOT_ALLOWED_COUNT
1936             = "drm.mediadrm.key_status_change.OUTPUT_NOT_ALLOWED.count";
1937 
1938         /**
1939          * Key to extract the count of {@link KeyStatus#STATUS_PENDING}
1940          * events that occured. The count is extracted from the
1941          * {@link PersistableBundle} returned from a {@link #getMetrics} call.
1942          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1943          */
1944         public static final String KEY_STATUS_PENDING_COUNT
1945             = "drm.mediadrm.key_status_change.PENDING.count";
1946 
1947         /**
1948          * Key to extract the count of {@link KeyStatus#STATUS_USABLE}
1949          * events that occured. The count is extracted from the
1950          * {@link PersistableBundle} returned from a {@link #getMetrics} call.
1951          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1952          */
1953         public static final String KEY_STATUS_USABLE_COUNT
1954             = "drm.mediadrm.key_status_change.USABLE.count";
1955 
1956         /**
1957          * Key to extract the count of {@link OnEventListener#onEvent}
1958          * calls of type PROVISION_REQUIRED occured. The count is
1959          * extracted from the {@link PersistableBundle} returned from a
1960          * {@link #getMetrics} call.
1961          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1962          */
1963         public static final String EVENT_PROVISION_REQUIRED_COUNT
1964             = "drm.mediadrm.event.PROVISION_REQUIRED.count";
1965 
1966         /**
1967          * Key to extract the count of {@link OnEventListener#onEvent}
1968          * calls of type KEY_NEEDED occured. The count is
1969          * extracted from the {@link PersistableBundle} returned from a
1970          * {@link #getMetrics} call.
1971          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1972          */
1973         public static final String EVENT_KEY_NEEDED_COUNT
1974             = "drm.mediadrm.event.KEY_NEEDED.count";
1975 
1976         /**
1977          * Key to extract the count of {@link OnEventListener#onEvent}
1978          * calls of type KEY_EXPIRED occured. The count is
1979          * extracted from the {@link PersistableBundle} returned from a
1980          * {@link #getMetrics} call.
1981          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1982          */
1983         public static final String EVENT_KEY_EXPIRED_COUNT
1984             = "drm.mediadrm.event.KEY_EXPIRED.count";
1985 
1986         /**
1987          * Key to extract the count of {@link OnEventListener#onEvent}
1988          * calls of type VENDOR_DEFINED. The count is
1989          * extracted from the {@link PersistableBundle} returned from a
1990          * {@link #getMetrics} call.
1991          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
1992          */
1993         public static final String EVENT_VENDOR_DEFINED_COUNT
1994             = "drm.mediadrm.event.VENDOR_DEFINED.count";
1995 
1996         /**
1997          * Key to extract the count of {@link OnEventListener#onEvent}
1998          * calls of type SESSION_RECLAIMED. The count is
1999          * extracted from the {@link PersistableBundle} returned from a
2000          * {@link #getMetrics} call.
2001          * The count is a Long value ({@link android.os.BaseBundle#getLong}).
2002          */
2003         public static final String EVENT_SESSION_RECLAIMED_COUNT
2004             = "drm.mediadrm.event.SESSION_RECLAIMED.count";
2005     }
2006 }
2007