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 17package android.media; 18 19import android.media.MediaDrmException; 20import java.lang.ref.WeakReference; 21import java.util.UUID; 22import java.util.HashMap; 23import java.util.List; 24import android.os.Handler; 25import android.os.Looper; 26import android.os.Message; 27import android.os.Bundle; 28import android.os.Parcel; 29import android.util.Log; 30 31/** 32 * MediaDrm can be used to obtain keys for decrypting protected media streams, in 33 * conjunction with {@link android.media.MediaCrypto}. The MediaDrm APIs 34 * are designed to support the ISO/IEC 23001-7: Common Encryption standard, but 35 * may also be used to implement other encryption schemes. 36 * <p> 37 * Encrypted content is prepared using an encryption server and stored in a content 38 * library. The encrypted content is streamed or downloaded from the content library to 39 * client devices via content servers. Licenses to view the content are obtained from 40 * a License Server. 41 * <p> 42 * <p><img src="../../../images/mediadrm_overview.png" 43 * alt="MediaDrm Overview diagram" 44 * border="0" /></p> 45 * <p> 46 * Keys are requested from the license server using a key request. The key 47 * response is delivered to the client app, which provides the response to the 48 * MediaDrm API. 49 * <p> 50 * A Provisioning server may be required to distribute device-unique credentials to 51 * the devices. 52 * <p> 53 * Enforcing requirements related to the number of devices that may play content 54 * simultaneously can be performed either through key renewal or using the secure 55 * stop methods. 56 * <p> 57 * The following sequence diagram shows the interactions between the objects 58 * involved while playing back encrypted content: 59 * <p> 60 * <p><img src="../../../images/mediadrm_decryption_sequence.png" 61 * alt="MediaDrm Overview diagram" 62 * border="0" /></p> 63 * <p> 64 * The app first constructs {@link android.media.MediaExtractor} and 65 * {@link android.media.MediaCodec} objects. It accesses the DRM-scheme-identifying UUID, 66 * typically from metadata in the content, and uses this UUID to construct an instance 67 * of a MediaDrm object that is able to support the DRM scheme required by the content. 68 * Crypto schemes are assigned 16 byte UUIDs. The method {@link #isCryptoSchemeSupported} 69 * can be used to query if a given scheme is supported on the device. 70 * <p> 71 * The app calls {@link #openSession} to generate a sessionId that will uniquely identify 72 * the session in subsequent interactions. The app next uses the MediaDrm object to 73 * obtain a key request message and send it to the license server, then provide 74 * the server's response to the MediaDrm object. 75 * <p> 76 * Once the app has a sessionId, it can construct a MediaCrypto object from the UUID and 77 * sessionId. The MediaCrypto object is registered with the MediaCodec in the 78 * {@link MediaCodec.#configure} method to enable the codec to decrypt content. 79 * <p> 80 * When the app has constructed {@link android.media.MediaExtractor}, 81 * {@link android.media.MediaCodec} and {@link android.media.MediaCrypto} objects, 82 * it proceeds to pull samples from the extractor and queue them into the decoder. For 83 * encrypted content, the samples returned from the extractor remain encrypted, they 84 * are only decrypted when the samples are delivered to the decoder. 85 * <p> 86 * <a name="Callbacks"></a> 87 * <h3>Callbacks</h3> 88 * <p>Applications should register for informational events in order 89 * to be informed of key state updates during playback or streaming. 90 * Registration for these events is done via a call to 91 * {@link #setOnEventListener}. In order to receive the respective 92 * callback associated with this listener, applications are required to create 93 * MediaDrm objects on a thread with its own Looper running (main UI 94 * thread by default has a Looper running). 95 */ 96public final class MediaDrm { 97 98 private final static String TAG = "MediaDrm"; 99 100 private EventHandler mEventHandler; 101 private OnEventListener mOnEventListener; 102 103 private int mNativeContext; 104 105 /** 106 * Query if the given scheme identified by its UUID is supported on 107 * this device. 108 * @param uuid The UUID of the crypto scheme. 109 */ 110 public static final boolean isCryptoSchemeSupported(UUID uuid) { 111 return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), null); 112 } 113 114 /** 115 * Query if the given scheme identified by its UUID is supported on 116 * this device, and whether the drm plugin is able to handle the 117 * media container format specified by mimeType. 118 * @param uuid The UUID of the crypto scheme. 119 * @param mimeType The MIME type of the media container, e.g. "video/mp4" 120 * or "video/webm" 121 */ 122 public static final boolean isCryptoSchemeSupported(UUID uuid, String mimeType) { 123 return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), mimeType); 124 } 125 126 private static final byte[] getByteArrayFromUUID(UUID uuid) { 127 long msb = uuid.getMostSignificantBits(); 128 long lsb = uuid.getLeastSignificantBits(); 129 130 byte[] uuidBytes = new byte[16]; 131 for (int i = 0; i < 8; ++i) { 132 uuidBytes[i] = (byte)(msb >>> (8 * (7 - i))); 133 uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i))); 134 } 135 136 return uuidBytes; 137 } 138 139 private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid, 140 String mimeType); 141 142 /** 143 * Instantiate a MediaDrm object 144 * 145 * @param uuid The UUID of the crypto scheme. 146 * 147 * @throws UnsupportedSchemeException if the device does not support the 148 * specified scheme UUID 149 */ 150 public MediaDrm(UUID uuid) throws UnsupportedSchemeException { 151 Looper looper; 152 if ((looper = Looper.myLooper()) != null) { 153 mEventHandler = new EventHandler(this, looper); 154 } else if ((looper = Looper.getMainLooper()) != null) { 155 mEventHandler = new EventHandler(this, looper); 156 } else { 157 mEventHandler = null; 158 } 159 160 /* Native setup requires a weak reference to our object. 161 * It's easier to create it here than in C++. 162 */ 163 native_setup(new WeakReference<MediaDrm>(this), 164 getByteArrayFromUUID(uuid)); 165 } 166 167 /** 168 * Register a callback to be invoked when an event occurs 169 * 170 * @param listener the callback that will be run 171 */ 172 public void setOnEventListener(OnEventListener listener) 173 { 174 mOnEventListener = listener; 175 } 176 177 /** 178 * Interface definition for a callback to be invoked when a drm event 179 * occurs 180 */ 181 public interface OnEventListener 182 { 183 /** 184 * Called when an event occurs that requires the app to be notified 185 * 186 * @param md the MediaDrm object on which the event occurred 187 * @param sessionId the DRM session ID on which the event occurred 188 * @param event indicates the event type 189 * @param extra an secondary error code 190 * @param data optional byte array of data that may be associated with the event 191 */ 192 void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data); 193 } 194 195 /** 196 * This event type indicates that the app needs to request a certificate from 197 * the provisioning server. The request message data is obtained using 198 * {@link #getProvisionRequest} 199 */ 200 public static final int EVENT_PROVISION_REQUIRED = 1; 201 202 /** 203 * This event type indicates that the app needs to request keys from a license 204 * server. The request message data is obtained using {@link #getKeyRequest}. 205 */ 206 public static final int EVENT_KEY_REQUIRED = 2; 207 208 /** 209 * This event type indicates that the licensed usage duration for keys in a session 210 * has expired. The keys are no longer valid. 211 */ 212 public static final int EVENT_KEY_EXPIRED = 3; 213 214 /** 215 * This event may indicate some specific vendor-defined condition, see your 216 * DRM provider documentation for details 217 */ 218 public static final int EVENT_VENDOR_DEFINED = 4; 219 220 private static final int DRM_EVENT = 200; 221 222 private class EventHandler extends Handler 223 { 224 private MediaDrm mMediaDrm; 225 226 public EventHandler(MediaDrm md, Looper looper) { 227 super(looper); 228 mMediaDrm = md; 229 } 230 231 @Override 232 public void handleMessage(Message msg) { 233 if (mMediaDrm.mNativeContext == 0) { 234 Log.w(TAG, "MediaDrm went away with unhandled events"); 235 return; 236 } 237 switch(msg.what) { 238 239 case DRM_EVENT: 240 Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")"); 241 242 if (mOnEventListener != null) { 243 if (msg.obj != null && msg.obj instanceof Parcel) { 244 Parcel parcel = (Parcel)msg.obj; 245 byte[] sessionId = parcel.createByteArray(); 246 if (sessionId.length == 0) { 247 sessionId = null; 248 } 249 byte[] data = parcel.createByteArray(); 250 if (data.length == 0) { 251 data = null; 252 } 253 mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data); 254 } 255 } 256 return; 257 258 default: 259 Log.e(TAG, "Unknown message type " + msg.what); 260 return; 261 } 262 } 263 } 264 265 /* 266 * This method is called from native code when an event occurs. This method 267 * just uses the EventHandler system to post the event back to the main app thread. 268 * We use a weak reference to the original MediaPlayer object so that the native 269 * code is safe from the object disappearing from underneath it. (This is 270 * the cookie passed to native_setup().) 271 */ 272 private static void postEventFromNative(Object mediadrm_ref, 273 int eventType, int extra, Object obj) 274 { 275 MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get(); 276 if (md == null) { 277 return; 278 } 279 if (md.mEventHandler != null) { 280 Message m = md.mEventHandler.obtainMessage(DRM_EVENT, eventType, extra, obj); 281 md.mEventHandler.sendMessage(m); 282 } 283 } 284 285 /** 286 * Open a new session with the MediaDrm object. A session ID is returned. 287 * 288 * @throws NotProvisionedException if provisioning is needed 289 * @throws ResourceBusyException if required resources are in use 290 */ 291 public native byte[] openSession() throws NotProvisionedException; 292 293 /** 294 * Close a session on the MediaDrm object that was previously opened 295 * with {@link #openSession}. 296 */ 297 public native void closeSession(byte[] sessionId); 298 299 /** 300 * This key request type species that the keys will be for online use, they will 301 * not be saved to the device for subsequent use when the device is not connected 302 * to a network. 303 */ 304 public static final int KEY_TYPE_STREAMING = 1; 305 306 /** 307 * This key request type specifies that the keys will be for offline use, they 308 * will be saved to the device for use when the device is not connected to a network. 309 */ 310 public static final int KEY_TYPE_OFFLINE = 2; 311 312 /** 313 * This key request type specifies that previously saved offline keys should be released. 314 */ 315 public static final int KEY_TYPE_RELEASE = 3; 316 317 /** 318 * Contains the opaque data an app uses to request keys from a license server 319 */ 320 public final static class KeyRequest { 321 KeyRequest() {} 322 323 /** 324 * Get the opaque message data 325 */ 326 public byte[] getData() { return mData; } 327 328 /** 329 * Get the default URL to use when sending the key request message to a 330 * server, if known. The app may prefer to use a different license 331 * server URL from other sources. 332 */ 333 public String getDefaultUrl() { return mDefaultUrl; } 334 335 private byte[] mData; 336 private String mDefaultUrl; 337 }; 338 339 /** 340 * A key request/response exchange occurs between the app and a license server 341 * to obtain or release keys used to decrypt encrypted content. 342 * <p> 343 * getKeyRequest() is used to obtain an opaque key request byte array that is 344 * delivered to the license server. The opaque key request byte array is returned 345 * in KeyRequest.data. The recommended URL to deliver the key request to is 346 * returned in KeyRequest.defaultUrl. 347 * <p> 348 * After the app has received the key request response from the server, 349 * it should deliver to the response to the DRM engine plugin using the method 350 * {@link #provideKeyResponse}. 351 * 352 * @param scope may be a sessionId or a keySetId, depending on the specified keyType. 353 * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, 354 * scope should be set to the sessionId the keys will be provided to. When the keyType 355 * is KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys 356 * being released. Releasing keys from a device invalidates them for all sessions. 357 * @param init container-specific data, its meaning is interpreted based on the 358 * mime type provided in the mimeType parameter. It could contain, for example, 359 * the content ID, key ID or other data obtained from the content metadata that is 360 * required in generating the key request. init may be null when keyType is 361 * KEY_TYPE_RELEASE. 362 * @param mimeType identifies the mime type of the content 363 * @param keyType specifes the type of the request. The request may be to acquire 364 * keys for streaming or offline content, or to release previously acquired 365 * keys, which are identified by a keySetId. 366 * @param optionalParameters are included in the key request message to 367 * allow a client application to provide additional message parameters to the server. 368 * 369 * @throws NotProvisionedException if reprovisioning is needed, due to a 370 * problem with the certifcate 371 */ 372 public native KeyRequest getKeyRequest(byte[] scope, byte[] init, 373 String mimeType, int keyType, 374 HashMap<String, String> optionalParameters) 375 throws NotProvisionedException; 376 377 378 /** 379 * A key response is received from the license server by the app, then it is 380 * provided to the DRM engine plugin using provideKeyResponse. When the 381 * response is for an offline key request, a keySetId is returned that can be 382 * used to later restore the keys to a new session with the method 383 * {@link #restoreKeys}. 384 * When the response is for a streaming or release request, null is returned. 385 * 386 * @param scope may be a sessionId or keySetId depending on the type of the 387 * response. Scope should be set to the sessionId when the response is for either 388 * streaming or offline key requests. Scope should be set to the keySetId when 389 * the response is for a release request. 390 * @param response the byte array response from the server 391 * 392 * @throws NotProvisionedException if the response indicates that 393 * reprovisioning is required 394 * @throws DeniedByServerException if the response indicates that the 395 * server rejected the request 396 * @throws ResourceBusyException if required resources are in use 397 */ 398 public native byte[] provideKeyResponse(byte[] scope, byte[] response) 399 throws NotProvisionedException, DeniedByServerException; 400 401 402 /** 403 * Restore persisted offline keys into a new session. keySetId identifies the 404 * keys to load, obtained from a prior call to {@link #provideKeyResponse}. 405 * 406 * @param sessionId the session ID for the DRM session 407 * @param keySetId identifies the saved key set to restore 408 */ 409 public native void restoreKeys(byte[] sessionId, byte[] keySetId); 410 411 /** 412 * Remove the current keys from a session. 413 * 414 * @param sessionId the session ID for the DRM session 415 */ 416 public native void removeKeys(byte[] sessionId); 417 418 /** 419 * Request an informative description of the key status for the session. The status is 420 * in the form of {name, value} pairs. Since DRM license policies vary by vendor, 421 * the specific status field names are determined by each DRM vendor. Refer to your 422 * DRM provider documentation for definitions of the field names for a particular 423 * DRM engine plugin. 424 * 425 * @param sessionId the session ID for the DRM session 426 */ 427 public native HashMap<String, String> queryKeyStatus(byte[] sessionId); 428 429 /** 430 * Contains the opaque data an app uses to request a certificate from a provisioning 431 * server 432 */ 433 public final static class ProvisionRequest { 434 ProvisionRequest() {} 435 436 /** 437 * Get the opaque message data 438 */ 439 public byte[] getData() { return mData; } 440 441 /** 442 * Get the default URL to use when sending the provision request 443 * message to a server, if known. The app may prefer to use a different 444 * provisioning server URL obtained from other sources. 445 */ 446 public String getDefaultUrl() { return mDefaultUrl; } 447 448 private byte[] mData; 449 private String mDefaultUrl; 450 } 451 452 /** 453 * A provision request/response exchange occurs between the app and a provisioning 454 * server to retrieve a device certificate. If provisionining is required, the 455 * EVENT_PROVISION_REQUIRED event will be sent to the event handler. 456 * getProvisionRequest is used to obtain the opaque provision request byte array that 457 * should be delivered to the provisioning server. The provision request byte array 458 * is returned in ProvisionRequest.data. The recommended URL to deliver the provision 459 * request to is returned in ProvisionRequest.defaultUrl. 460 */ 461 public native ProvisionRequest getProvisionRequest(); 462 463 /** 464 * After a provision response is received by the app, it is provided to the DRM 465 * engine plugin using this method. 466 * 467 * @param response the opaque provisioning response byte array to provide to the 468 * DRM engine plugin. 469 * 470 * @throws DeniedByServerException if the response indicates that the 471 * server rejected the request 472 */ 473 public native void provideProvisionResponse(byte[] response) 474 throws DeniedByServerException; 475 476 /** 477 * A means of enforcing limits on the number of concurrent streams per subscriber 478 * across devices is provided via SecureStop. This is achieved by securely 479 * monitoring the lifetime of sessions. 480 * <p> 481 * Information from the server related to the current playback session is written 482 * to persistent storage on the device when each MediaCrypto object is created. 483 * <p> 484 * In the normal case, playback will be completed, the session destroyed and the 485 * Secure Stops will be queried. The app queries secure stops and forwards the 486 * secure stop message to the server which verifies the signature and notifies the 487 * server side database that the session destruction has been confirmed. The persisted 488 * record on the client is only removed after positive confirmation that the server 489 * received the message using releaseSecureStops(). 490 */ 491 public native List<byte[]> getSecureStops(); 492 493 494 /** 495 * Process the SecureStop server response message ssRelease. After authenticating 496 * the message, remove the SecureStops identified in the response. 497 * 498 * @param ssRelease the server response indicating which secure stops to release 499 */ 500 public native void releaseSecureStops(byte[] ssRelease); 501 502 503 /** 504 * String property name: identifies the maker of the DRM engine plugin 505 */ 506 public static final String PROPERTY_VENDOR = "vendor"; 507 508 /** 509 * String property name: identifies the version of the DRM engine plugin 510 */ 511 public static final String PROPERTY_VERSION = "version"; 512 513 /** 514 * String property name: describes the DRM engine plugin 515 */ 516 public static final String PROPERTY_DESCRIPTION = "description"; 517 518 /** 519 * String property name: a comma-separated list of cipher and mac algorithms 520 * supported by CryptoSession. The list may be empty if the DRM engine 521 * plugin does not support CryptoSession operations. 522 */ 523 public static final String PROPERTY_ALGORITHMS = "algorithms"; 524 525 /** 526 * Read a DRM engine plugin String property value, given the property name string. 527 * <p> 528 * Standard fields names are: 529 * {@link #PROPERTY_VENDOR}, {@link #PROPERTY_VERSION}, 530 * {@link #PROPERTY_DESCRIPTION}, {@link #PROPERTY_ALGORITHMS} 531 */ 532 public native String getPropertyString(String propertyName); 533 534 535 /** 536 * Byte array property name: the device unique identifier is established during 537 * device provisioning and provides a means of uniquely identifying each device. 538 */ 539 public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId"; 540 541 /** 542 * Read a DRM engine plugin byte array property value, given the property name string. 543 * <p> 544 * Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID} 545 */ 546 public native byte[] getPropertyByteArray(String propertyName); 547 548 549 /** 550 * Set a DRM engine plugin String property value. 551 */ 552 public native void setPropertyString(String propertyName, String value); 553 554 /** 555 * Set a DRM engine plugin byte array property value. 556 */ 557 public native void setPropertyByteArray(String propertyName, byte[] value); 558 559 560 private static final native void setCipherAlgorithmNative(MediaDrm drm, byte[] sessionId, 561 String algorithm); 562 563 private static final native void setMacAlgorithmNative(MediaDrm drm, byte[] sessionId, 564 String algorithm); 565 566 private static final native byte[] encryptNative(MediaDrm drm, byte[] sessionId, 567 byte[] keyId, byte[] input, byte[] iv); 568 569 private static final native byte[] decryptNative(MediaDrm drm, byte[] sessionId, 570 byte[] keyId, byte[] input, byte[] iv); 571 572 private static final native byte[] signNative(MediaDrm drm, byte[] sessionId, 573 byte[] keyId, byte[] message); 574 575 private static final native boolean verifyNative(MediaDrm drm, byte[] sessionId, 576 byte[] keyId, byte[] message, 577 byte[] signature); 578 579 /** 580 * In addition to supporting decryption of DASH Common Encrypted Media, the 581 * MediaDrm APIs provide the ability to securely deliver session keys from 582 * an operator's session key server to a client device, based on the factory-installed 583 * root of trust, and then perform encrypt, decrypt, sign and verify operations 584 * with the session key on arbitrary user data. 585 * <p> 586 * The CryptoSession class implements generic encrypt/decrypt/sign/verify methods 587 * based on the established session keys. These keys are exchanged using the 588 * getKeyRequest/provideKeyResponse methods. 589 * <p> 590 * Applications of this capability could include securing various types of 591 * purchased or private content, such as applications, books and other media, 592 * photos or media delivery protocols. 593 * <p> 594 * Operators can create session key servers that are functionally similar to a 595 * license key server, except that instead of receiving license key requests and 596 * providing encrypted content keys which are used specifically to decrypt A/V media 597 * content, the session key server receives session key requests and provides 598 * encrypted session keys which can be used for general purpose crypto operations. 599 * <p> 600 * A CryptoSession is obtained using {@link #getCryptoSession} 601 */ 602 public final class CryptoSession { 603 private MediaDrm mDrm; 604 private byte[] mSessionId; 605 606 CryptoSession(MediaDrm drm, byte[] sessionId, 607 String cipherAlgorithm, String macAlgorithm) 608 { 609 mSessionId = sessionId; 610 mDrm = drm; 611 setCipherAlgorithmNative(drm, sessionId, cipherAlgorithm); 612 setMacAlgorithmNative(drm, sessionId, macAlgorithm); 613 } 614 615 /** 616 * Encrypt data using the CryptoSession's cipher algorithm 617 * 618 * @param keyid specifies which key to use 619 * @param input the data to encrypt 620 * @param iv the initialization vector to use for the cipher 621 */ 622 public byte[] encrypt(byte[] keyid, byte[] input, byte[] iv) { 623 return encryptNative(mDrm, mSessionId, keyid, input, iv); 624 } 625 626 /** 627 * Decrypt data using the CryptoSessions's cipher algorithm 628 * 629 * @param keyid specifies which key to use 630 * @param input the data to encrypt 631 * @param iv the initialization vector to use for the cipher 632 */ 633 public byte[] decrypt(byte[] keyid, byte[] input, byte[] iv) { 634 return decryptNative(mDrm, mSessionId, keyid, input, iv); 635 } 636 637 /** 638 * Sign data using the CryptoSessions's mac algorithm. 639 * 640 * @param keyid specifies which key to use 641 * @param message the data for which a signature is to be computed 642 */ 643 public byte[] sign(byte[] keyid, byte[] message) { 644 return signNative(mDrm, mSessionId, keyid, message); 645 } 646 647 /** 648 * Verify a signature using the CryptoSessions's mac algorithm. Return true 649 * if the signatures match, false if they do no. 650 * 651 * @param keyid specifies which key to use 652 * @param message the data to verify 653 * @param signature the reference signature which will be compared with the 654 * computed signature 655 */ 656 public boolean verify(byte[] keyid, byte[] message, byte[] signature) { 657 return verifyNative(mDrm, mSessionId, keyid, message, signature); 658 } 659 }; 660 661 /** 662 * Obtain a CryptoSession object which can be used to encrypt, decrypt, 663 * sign and verify messages or data using the session keys established 664 * for the session using methods {@link #getKeyRequest} and 665 * {@link #provideKeyResponse} using a session key server. 666 * 667 * @param sessionId the session ID for the session containing keys 668 * to be used for encrypt, decrypt, sign and/or verify 669 * @param cipherAlgorithm the algorithm to use for encryption and 670 * decryption ciphers. The algorithm string conforms to JCA Standard 671 * Names for Cipher Transforms and is case insensitive. For example 672 * "AES/CBC/NoPadding". 673 * @param macAlgorithm the algorithm to use for sign and verify 674 * The algorithm string conforms to JCA Standard Names for Mac 675 * Algorithms and is case insensitive. For example "HmacSHA256". 676 * <p> 677 * The list of supported algorithms for a DRM engine plugin can be obtained 678 * using the method {@link #getPropertyString} with the property name 679 * "algorithms". 680 */ 681 public CryptoSession getCryptoSession(byte[] sessionId, 682 String cipherAlgorithm, 683 String macAlgorithm) 684 { 685 return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm); 686 } 687 688 @Override 689 protected void finalize() { 690 native_finalize(); 691 } 692 693 public native final void release(); 694 private static native final void native_init(); 695 696 private native final void native_setup(Object mediadrm_this, byte[] uuid); 697 698 private native final void native_finalize(); 699 700 static { 701 System.loadLibrary("media_jni"); 702 native_init(); 703 } 704} 705