Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1241)

Side by Side Diff: media/base/android/media_drm_bridge.cc

Issue 2790783002: [Clank] Add JNI interface for media persistent license storage (Closed)
Patch Set: Fix lint Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/base/android/media_drm_bridge.h ('k') | media/base/android/media_drm_storage_bridge.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/base/android/media_drm_bridge.h" 5 #include "media/base/android/media_drm_bridge.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/android/build_info.h" 11 #include "base/android/build_info.h"
12 #include "base/android/jni_array.h" 12 #include "base/android/jni_array.h"
13 #include "base/android/jni_string.h" 13 #include "base/android/jni_string.h"
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/callback_helpers.h" 15 #include "base/callback_helpers.h"
16 #include "base/containers/hash_tables.h" 16 #include "base/containers/hash_tables.h"
17 #include "base/feature_list.h" 17 #include "base/feature_list.h"
18 #include "base/location.h" 18 #include "base/location.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/macros.h" 20 #include "base/macros.h"
21 #include "base/single_thread_task_runner.h" 21 #include "base/single_thread_task_runner.h"
22 #include "base/strings/string_number_conversions.h" 22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
24 #include "base/sys_byteorder.h" 24 #include "base/sys_byteorder.h"
25 #include "base/sys_info.h" 25 #include "base/sys_info.h"
26 #include "base/threading/thread_task_runner_handle.h" 26 #include "base/threading/thread_task_runner_handle.h"
27 #include "jni/MediaDrmBridge_jni.h" 27 #include "jni/MediaDrmBridge_jni.h"
28 #include "media/base/android/android_util.h"
28 #include "media/base/android/media_codec_util.h" 29 #include "media/base/android/media_codec_util.h"
29 #include "media/base/android/media_drm_bridge_client.h" 30 #include "media/base/android/media_drm_bridge_client.h"
30 #include "media/base/android/media_drm_bridge_delegate.h" 31 #include "media/base/android/media_drm_bridge_delegate.h"
31 #include "media/base/cdm_key_information.h" 32 #include "media/base/cdm_key_information.h"
32 #include "media/base/media_switches.h" 33 #include "media/base/media_switches.h"
33 #include "media/base/provision_fetcher.h" 34 #include "media/base/provision_fetcher.h"
34 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. 35 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
35 36
36 using base::android::AttachCurrentThread; 37 using base::android::AttachCurrentThread;
37 using base::android::ConvertUTF8ToJavaString; 38 using base::android::ConvertUTF8ToJavaString;
(...skipping 26 matching lines...) Expand all
64 }; 65 };
65 66
66 // These must be in sync with Android MediaDrm KEY_TYPE_XXX constants: 67 // These must be in sync with Android MediaDrm KEY_TYPE_XXX constants:
67 // https://developer.android.com/reference/android/media/MediaDrm.html#KEY_TYPE_ OFFLINE 68 // https://developer.android.com/reference/android/media/MediaDrm.html#KEY_TYPE_ OFFLINE
68 // KEY_TYPE_RELEASE is handled internally in Java. 69 // KEY_TYPE_RELEASE is handled internally in Java.
69 enum class KeyType : uint32_t { 70 enum class KeyType : uint32_t {
70 KEY_TYPE_STREAMING = 1, 71 KEY_TYPE_STREAMING = 1,
71 KEY_TYPE_OFFLINE = 2, 72 KEY_TYPE_OFFLINE = 2,
72 }; 73 };
73 74
74 // Converts jbyteArray (byte[] in Java) into std::string.
75 std::string AsString(JNIEnv* env, jbyteArray j_byte_array) {
76 std::vector<uint8_t> byte_vector;
77 JavaByteArrayToByteVector(env, j_byte_array, &byte_vector);
78 return std::string(byte_vector.begin(), byte_vector.end());
79 }
80
81 const uint8_t kWidevineUuid[16] = { 75 const uint8_t kWidevineUuid[16] = {
82 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, // 76 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, //
83 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED}; 77 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED};
84 78
85 // Convert |init_data_type| to a string supported by MediaDRM. 79 // Convert |init_data_type| to a string supported by MediaDRM.
86 // "audio"/"video" does not matter, so use "video". 80 // "audio"/"video" does not matter, so use "video".
87 std::string ConvertInitDataType(media::EmeInitDataType init_data_type) { 81 std::string ConvertInitDataType(media::EmeInitDataType init_data_type) {
88 // TODO(jrummell/xhwang): EME init data types like "webm" and "cenc" are 82 // TODO(jrummell/xhwang): EME init data types like "webm" and "cenc" are
89 // supported in API level >=21 for Widevine key system. Switch to use those 83 // supported in API level >=21 for Widevine key system. Switch to use those
90 // strings when they are officially supported in Android for all key systems. 84 // strings when they are officially supported in Android for all key systems.
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 JNIEnv* env, 623 JNIEnv* env,
630 const JavaParamRef<jobject>& j_media_drm, 624 const JavaParamRef<jobject>& j_media_drm,
631 const JavaParamRef<jstring>& j_default_url, 625 const JavaParamRef<jstring>& j_default_url,
632 const JavaParamRef<jbyteArray>& j_request_data) { 626 const JavaParamRef<jbyteArray>& j_request_data) {
633 DVLOG(1) << __func__; 627 DVLOG(1) << __func__;
634 628
635 task_runner_->PostTask(FROM_HERE, 629 task_runner_->PostTask(FROM_HERE,
636 base::Bind(&MediaDrmBridge::SendProvisioningRequest, 630 base::Bind(&MediaDrmBridge::SendProvisioningRequest,
637 weak_factory_.GetWeakPtr(), 631 weak_factory_.GetWeakPtr(),
638 ConvertJavaStringToUTF8(env, j_default_url), 632 ConvertJavaStringToUTF8(env, j_default_url),
639 AsString(env, j_request_data))); 633 JavaBytesToString(env, j_request_data)));
640 } 634 }
641 635
642 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env, 636 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env,
643 const JavaParamRef<jobject>& j_media_drm, 637 const JavaParamRef<jobject>& j_media_drm,
644 jint j_promise_id) { 638 jint j_promise_id) {
645 task_runner_->PostTask(FROM_HERE, 639 task_runner_->PostTask(FROM_HERE,
646 base::Bind(&MediaDrmBridge::ResolvePromise, 640 base::Bind(&MediaDrmBridge::ResolvePromise,
647 weak_factory_.GetWeakPtr(), j_promise_id)); 641 weak_factory_.GetWeakPtr(), j_promise_id));
648 } 642 }
649 643
650 void MediaDrmBridge::OnPromiseResolvedWithSession( 644 void MediaDrmBridge::OnPromiseResolvedWithSession(
651 JNIEnv* env, 645 JNIEnv* env,
652 const JavaParamRef<jobject>& j_media_drm, 646 const JavaParamRef<jobject>& j_media_drm,
653 jint j_promise_id, 647 jint j_promise_id,
654 const JavaParamRef<jbyteArray>& j_session_id) { 648 const JavaParamRef<jbyteArray>& j_session_id) {
655 task_runner_->PostTask(FROM_HERE, 649 task_runner_->PostTask(FROM_HERE,
656 base::Bind(&MediaDrmBridge::ResolvePromiseWithSession, 650 base::Bind(&MediaDrmBridge::ResolvePromiseWithSession,
657 weak_factory_.GetWeakPtr(), j_promise_id, 651 weak_factory_.GetWeakPtr(), j_promise_id,
658 AsString(env, j_session_id))); 652 JavaBytesToString(env, j_session_id)));
659 } 653 }
660 654
661 void MediaDrmBridge::OnPromiseRejected( 655 void MediaDrmBridge::OnPromiseRejected(
662 JNIEnv* env, 656 JNIEnv* env,
663 const JavaParamRef<jobject>& j_media_drm, 657 const JavaParamRef<jobject>& j_media_drm,
664 jint j_promise_id, 658 jint j_promise_id,
665 const JavaParamRef<jstring>& j_error_message) { 659 const JavaParamRef<jstring>& j_error_message) {
666 task_runner_->PostTask( 660 task_runner_->PostTask(
667 FROM_HERE, 661 FROM_HERE,
668 base::Bind(&MediaDrmBridge::RejectPromise, weak_factory_.GetWeakPtr(), 662 base::Bind(&MediaDrmBridge::RejectPromise, weak_factory_.GetWeakPtr(),
669 j_promise_id, ConvertJavaStringToUTF8(env, j_error_message))); 663 j_promise_id, ConvertJavaStringToUTF8(env, j_error_message)));
670 } 664 }
671 665
672 void MediaDrmBridge::OnSessionMessage( 666 void MediaDrmBridge::OnSessionMessage(
673 JNIEnv* env, 667 JNIEnv* env,
674 const JavaParamRef<jobject>& j_media_drm, 668 const JavaParamRef<jobject>& j_media_drm,
675 const JavaParamRef<jbyteArray>& j_session_id, 669 const JavaParamRef<jbyteArray>& j_session_id,
676 jint j_message_type, 670 jint j_message_type,
677 const JavaParamRef<jbyteArray>& j_message) { 671 const JavaParamRef<jbyteArray>& j_message) {
678 DVLOG(2) << __func__; 672 DVLOG(2) << __func__;
679 673
680 std::vector<uint8_t> message; 674 std::vector<uint8_t> message;
681 JavaByteArrayToByteVector(env, j_message, &message); 675 JavaByteArrayToByteVector(env, j_message, &message);
682 ContentDecryptionModule::MessageType message_type = 676 ContentDecryptionModule::MessageType message_type =
683 GetMessageType(static_cast<RequestType>(j_message_type)); 677 GetMessageType(static_cast<RequestType>(j_message_type));
684 678
685 task_runner_->PostTask( 679 task_runner_->PostTask(
686 FROM_HERE, base::Bind(session_message_cb_, AsString(env, j_session_id), 680 FROM_HERE,
687 message_type, message)); 681 base::Bind(session_message_cb_, JavaBytesToString(env, j_session_id),
682 message_type, message));
688 } 683 }
689 684
690 void MediaDrmBridge::OnSessionClosed( 685 void MediaDrmBridge::OnSessionClosed(
691 JNIEnv* env, 686 JNIEnv* env,
692 const JavaParamRef<jobject>& j_media_drm, 687 const JavaParamRef<jobject>& j_media_drm,
693 const JavaParamRef<jbyteArray>& j_session_id) { 688 const JavaParamRef<jbyteArray>& j_session_id) {
694 DVLOG(2) << __func__; 689 DVLOG(2) << __func__;
695 std::string session_id = AsString(env, j_session_id); 690 std::string session_id = JavaBytesToString(env, j_session_id);
696 task_runner_->PostTask(FROM_HERE, base::Bind(session_closed_cb_, session_id)); 691 task_runner_->PostTask(FROM_HERE, base::Bind(session_closed_cb_, session_id));
697 } 692 }
698 693
699 void MediaDrmBridge::OnSessionKeysChange( 694 void MediaDrmBridge::OnSessionKeysChange(
700 JNIEnv* env, 695 JNIEnv* env,
701 const JavaParamRef<jobject>& j_media_drm, 696 const JavaParamRef<jobject>& j_media_drm,
702 const JavaParamRef<jbyteArray>& j_session_id, 697 const JavaParamRef<jbyteArray>& j_session_id,
703 const JavaParamRef<jobjectArray>& j_keys_info, 698 const JavaParamRef<jobjectArray>& j_keys_info,
704 bool has_additional_usable_key) { 699 bool has_additional_usable_key) {
705 DVLOG(2) << __func__; 700 DVLOG(2) << __func__;
(...skipping 19 matching lines...) Expand all
725 720
726 DVLOG(2) << __func__ << "Key status change: " 721 DVLOG(2) << __func__ << "Key status change: "
727 << base::HexEncode(&key_id[0], key_id.size()) << ", " 722 << base::HexEncode(&key_id[0], key_id.size()) << ", "
728 << key_status; 723 << key_status;
729 724
730 cdm_keys_info.push_back(new CdmKeyInformation(key_id, key_status, 0)); 725 cdm_keys_info.push_back(new CdmKeyInformation(key_id, key_status, 0));
731 } 726 }
732 727
733 task_runner_->PostTask( 728 task_runner_->PostTask(
734 FROM_HERE, 729 FROM_HERE,
735 base::Bind(session_keys_change_cb_, AsString(env, j_session_id), 730 base::Bind(session_keys_change_cb_, JavaBytesToString(env, j_session_id),
736 has_additional_usable_key, base::Passed(&cdm_keys_info))); 731 has_additional_usable_key, base::Passed(&cdm_keys_info)));
737 732
738 if (has_additional_usable_key) { 733 if (has_additional_usable_key) {
739 task_runner_->PostTask(FROM_HERE, 734 task_runner_->PostTask(FROM_HERE,
740 base::Bind(&MediaDrmBridge::OnHasAdditionalUsableKey, 735 base::Bind(&MediaDrmBridge::OnHasAdditionalUsableKey,
741 weak_factory_.GetWeakPtr())); 736 weak_factory_.GetWeakPtr()));
742 } 737 }
743 } 738 }
744 739
745 // According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys 740 // According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys
746 // will never expire. This will be translated into a NULL base::Time() [2], 741 // will never expire. This will be translated into a NULL base::Time() [2],
747 // which will then be mapped to a zero Java time [3]. The zero Java time is 742 // which will then be mapped to a zero Java time [3]. The zero Java time is
748 // passed to Blink which will then be translated to NaN [4], which is what the 743 // passed to Blink which will then be translated to NaN [4], which is what the
749 // spec uses to indicate that the license will never expire [5]. 744 // spec uses to indicate that the license will never expire [5].
750 // [1] 745 // [1]
751 // http://developer.android.com/reference/android/media/MediaDrm.OnExpirationUpd ateListener.html 746 // http://developer.android.com/reference/android/media/MediaDrm.OnExpirationUpd ateListener.html
752 // [2] See base::Time::FromDoubleT() 747 // [2] See base::Time::FromDoubleT()
753 // [3] See base::Time::ToJavaTime() 748 // [3] See base::Time::ToJavaTime()
754 // [4] See MediaKeySession::expirationChanged() 749 // [4] See MediaKeySession::expirationChanged()
755 // [5] https://github.com/w3c/encrypted-media/issues/58 750 // [5] https://github.com/w3c/encrypted-media/issues/58
756 void MediaDrmBridge::OnSessionExpirationUpdate( 751 void MediaDrmBridge::OnSessionExpirationUpdate(
757 JNIEnv* env, 752 JNIEnv* env,
758 const JavaParamRef<jobject>& j_media_drm, 753 const JavaParamRef<jobject>& j_media_drm,
759 const JavaParamRef<jbyteArray>& j_session_id, 754 const JavaParamRef<jbyteArray>& j_session_id,
760 jlong expiry_time_ms) { 755 jlong expiry_time_ms) {
761 DVLOG(2) << __func__ << ": " << expiry_time_ms << " ms"; 756 DVLOG(2) << __func__ << ": " << expiry_time_ms << " ms";
762 task_runner_->PostTask( 757 task_runner_->PostTask(
763 FROM_HERE, 758 FROM_HERE, base::Bind(session_expiration_update_cb_,
764 base::Bind(session_expiration_update_cb_, AsString(env, j_session_id), 759 JavaBytesToString(env, j_session_id),
765 base::Time::FromDoubleT(expiry_time_ms / 1000.0))); 760 base::Time::FromDoubleT(expiry_time_ms / 1000.0)));
766 } 761 }
767 762
768 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( 763 void MediaDrmBridge::OnResetDeviceCredentialsCompleted(
769 JNIEnv* env, 764 JNIEnv* env,
770 const JavaParamRef<jobject>&, 765 const JavaParamRef<jobject>&,
771 bool success) { 766 bool success) {
772 DVLOG(2) << __func__ << ": success:" << success; 767 DVLOG(2) << __func__ << ": success:" << success;
773 DCHECK(!reset_credentials_cb_.is_null()); 768 DCHECK(!reset_credentials_cb_.is_null());
774 task_runner_->PostTask( 769 task_runner_->PostTask(
775 FROM_HERE, 770 FROM_HERE,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 815
821 // TODO(yucliu): Per EME spec on individualization, implementation should not 816 // TODO(yucliu): Per EME spec on individualization, implementation should not
822 // expose application-specific information. Considering encode origin before 817 // expose application-specific information. Considering encode origin before
823 // passing to MediaDrm. 818 // passing to MediaDrm.
824 ScopedJavaLocalRef<jstring> j_security_origin = ConvertUTF8ToJavaString( 819 ScopedJavaLocalRef<jstring> j_security_origin = ConvertUTF8ToJavaString(
825 env, use_origin_isolated_storage ? security_origin.spec() : ""); 820 env, use_origin_isolated_storage ? security_origin.spec() : "");
826 821
827 // Note: OnMediaCryptoReady() could be called in this call. 822 // Note: OnMediaCryptoReady() could be called in this call.
828 j_media_drm_.Reset(Java_MediaDrmBridge_create( 823 j_media_drm_.Reset(Java_MediaDrmBridge_create(
829 env, j_scheme_uuid, j_security_origin, j_security_level, 824 env, j_scheme_uuid, j_security_origin, j_security_level,
830 reinterpret_cast<intptr_t>(this))); 825 reinterpret_cast<intptr_t>(this), reinterpret_cast<intptr_t>(&storage_)));
831 } 826 }
832 827
833 MediaDrmBridge::~MediaDrmBridge() { 828 MediaDrmBridge::~MediaDrmBridge() {
834 DCHECK(task_runner_->BelongsToCurrentThread()); 829 DCHECK(task_runner_->BelongsToCurrentThread());
835 DVLOG(1) << __func__; 830 DVLOG(1) << __func__;
836 831
837 JNIEnv* env = AttachCurrentThread(); 832 JNIEnv* env = AttachCurrentThread();
838 833
839 // After the call to Java_MediaDrmBridge_destroy() Java won't call native 834 // After the call to Java_MediaDrmBridge_destroy() Java won't call native
840 // methods anymore, this is ensured by MediaDrmBridge.java. 835 // methods anymore, this is ensured by MediaDrmBridge.java.
(...skipping 20 matching lines...) Expand all
861 856
862 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { 857 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() {
863 JNIEnv* env = AttachCurrentThread(); 858 JNIEnv* env = AttachCurrentThread();
864 ScopedJavaLocalRef<jstring> j_security_level = 859 ScopedJavaLocalRef<jstring> j_security_level =
865 Java_MediaDrmBridge_getSecurityLevel(env, j_media_drm_); 860 Java_MediaDrmBridge_getSecurityLevel(env, j_media_drm_);
866 std::string security_level_str = 861 std::string security_level_str =
867 ConvertJavaStringToUTF8(env, j_security_level.obj()); 862 ConvertJavaStringToUTF8(env, j_security_level.obj());
868 return GetSecurityLevelFromString(security_level_str); 863 return GetSecurityLevelFromString(security_level_str);
869 } 864 }
870 865
871 // We have to use scoped_ptr to pass ScopedJavaGlobalRef with a callback.
872 // TODO(timav): Check whether we can simply pass j_media_crypto_->obj() in the
873 // callback.
874 MediaDrmBridge::JavaObjectPtr MediaDrmBridge::CreateJavaObjectPtr(
875 jobject object) {
876 JavaObjectPtr j_object_ptr(new ScopedJavaGlobalRef<jobject>());
877 j_object_ptr->Reset(AttachCurrentThread(), object);
878 return j_object_ptr;
879 }
880
881 void MediaDrmBridge::NotifyMediaCryptoReady(JavaObjectPtr j_media_crypto) { 866 void MediaDrmBridge::NotifyMediaCryptoReady(JavaObjectPtr j_media_crypto) {
882 DCHECK(task_runner_->BelongsToCurrentThread()); 867 DCHECK(task_runner_->BelongsToCurrentThread());
883 DCHECK(j_media_crypto); 868 DCHECK(j_media_crypto);
884 DCHECK(!j_media_crypto_); 869 DCHECK(!j_media_crypto_);
885 870
886 j_media_crypto_ = std::move(j_media_crypto); 871 j_media_crypto_ = std::move(j_media_crypto);
887 872
888 if (media_crypto_ready_cb_.is_null()) 873 if (media_crypto_ready_cb_.is_null())
889 return; 874 return;
890 875
876 // We have to use scoped_ptr to pass ScopedJavaGlobalRef with a callback.
877 // TODO(yucliu): Check whether we can simply pass j_media_crypto_->obj() in th e
878 // callback.
891 base::ResetAndReturn(&media_crypto_ready_cb_) 879 base::ResetAndReturn(&media_crypto_ready_cb_)
892 .Run(CreateJavaObjectPtr(j_media_crypto_->obj()), 880 .Run(CreateJavaObjectPtr(j_media_crypto_->obj()),
893 IsProtectedSurfaceRequired()); 881 IsProtectedSurfaceRequired());
894 } 882 }
895 883
896 void MediaDrmBridge::SendProvisioningRequest(const std::string& default_url, 884 void MediaDrmBridge::SendProvisioningRequest(const std::string& default_url,
897 const std::string& request_data) { 885 const std::string& request_data) {
898 DCHECK(task_runner_->BelongsToCurrentThread()); 886 DCHECK(task_runner_->BelongsToCurrentThread());
899 DVLOG(1) << __func__; 887 DVLOG(1) << __func__;
900 888
(...skipping 27 matching lines...) Expand all
928 } 916 }
929 917
930 void MediaDrmBridge::OnHasAdditionalUsableKey() { 918 void MediaDrmBridge::OnHasAdditionalUsableKey() {
931 DCHECK(task_runner_->BelongsToCurrentThread()); 919 DCHECK(task_runner_->BelongsToCurrentThread());
932 DVLOG(1) << __func__; 920 DVLOG(1) << __func__;
933 921
934 player_tracker_.NotifyNewKey(); 922 player_tracker_.NotifyNewKey();
935 } 923 }
936 924
937 } // namespace media 925 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_drm_bridge.h ('k') | media/base/android/media_drm_storage_bridge.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698