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 */ 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 */ 181 public static final boolean isCryptoSchemeSupported( 182 @NonNull UUID uuid, @NonNull String mimeType) { 183 return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), mimeType); 184 } 185 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 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 */ 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 */ 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 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 */ 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 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 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 */ 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 757 KeyRequest() {} 758 759 /** 760 * Get the opaque message data 761 */ 762 @NonNull 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 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 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 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 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 */ 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 */ 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 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 { 906 ProvisionRequest() {} 907 908 /** 909 * Get the opaque message data 910 */ 911 @NonNull 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 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 953 public ProvisionRequest getProvisionRequest() { 954 return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, ""); 955 } 956 957 @NonNull 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 */ 971 public void provideProvisionResponse(@NonNull byte[] response) 972 throws DeniedByServerException { 973 provideProvisionResponseNative(response); 974 } 975 976 @NonNull 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 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 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 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 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 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 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 */ 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 */ 1298 public native void setPropertyByteArray(@NonNull @ArrayProperty 1299 String propertyName, @NonNull byte[] value); 1300 1301 private static final native void setCipherAlgorithmNative( 1302 @NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm); 1303 1304 private static final native void setMacAlgorithmNative( 1305 @NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm); 1306 1307 @NonNull 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 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 1318 private static final native byte[] signNative( 1319 @NonNull MediaDrm drm, @NonNull byte[] sessionId, 1320 @NonNull byte[] keyId, @NonNull byte[] message); 1321 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 */ 1336 public PersistableBundle getMetrics() { 1337 PersistableBundle bundle = getMetricsNative(); 1338 return bundle; 1339 } 1340 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 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 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 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 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 */ 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 */ 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 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 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 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 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 { 1515 Certificate() {} 1516 1517 /** 1518 * Get the wrapped private key data 1519 */ 1520 @NonNull 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 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 1568 public Certificate provideCertificateResponse(@NonNull byte[] response) 1569 throws DeniedByServerException { 1570 return provideProvisionResponseNative(response); 1571 } 1572 1573 @NonNull 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 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 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 1620 public void close() { 1621 release(); 1622 } 1623 1624 /** 1625 * @deprecated replaced by {@link #close()}. 1626 */ 1627 @Deprecated 1628 public void release() { 1629 mCloseGuard.close(); 1630 if (mClosed.compareAndSet(false, true)) { 1631 native_release(); 1632 } 1633 } 1634 1635 /** @hide */ 1636 public native final void native_release(); 1637 1638 private static native final void native_init(); 1639 1640 private native final void native_setup(Object mediadrm_this, byte[] uuid, 1641 String appPackageName); 1642 1643 static { 1644 System.loadLibrary("media_jni"); 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 { 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