Don't send a SHChangeNotify for creating an app icon when creating a shortcut.
[chromium-blink-merge.git] / media / base / android / media_drm_bridge.cc
blob5506ed8062fb80278ad9985d232bca6135fd8b30
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
3 // found in the LICENSE file.
5 #include "media/base/android/media_drm_bridge.h"
7 #include <algorithm>
9 #include "base/android/build_info.h"
10 #include "base/android/jni_array.h"
11 #include "base/android/jni_string.h"
12 #include "base/callback_helpers.h"
13 #include "base/containers/hash_tables.h"
14 #include "base/lazy_instance.h"
15 #include "base/location.h"
16 #include "base/logging.h"
17 #include "base/message_loop/message_loop_proxy.h"
18 #include "base/strings/string_util.h"
19 #include "base/sys_byteorder.h"
20 #include "base/sys_info.h"
21 #include "jni/MediaDrmBridge_jni.h"
22 #include "media/base/cdm_key_information.h"
24 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
26 using base::android::AttachCurrentThread;
27 using base::android::ConvertUTF8ToJavaString;
28 using base::android::ConvertJavaStringToUTF8;
29 using base::android::JavaByteArrayToByteVector;
30 using base::android::ScopedJavaLocalRef;
32 namespace media {
34 namespace {
36 // DrmBridge supports session expiration event but doesn't provide detailed
37 // status for each key ID, which is required by the EME spec. Use a dummy key ID
38 // here to report session expiration info.
39 const char kDummyKeyId[] = "Dummy Key Id";
41 uint32 ReadUint32(const uint8_t* data) {
42 uint32 value = 0;
43 for (int i = 0; i < 4; ++i)
44 value = (value << 8) | data[i];
45 return value;
48 uint64 ReadUint64(const uint8_t* data) {
49 uint64 value = 0;
50 for (int i = 0; i < 8; ++i)
51 value = (value << 8) | data[i];
52 return value;
55 // Returns string session ID from jbyteArray (byte[] in Java).
56 std::string GetSessionId(JNIEnv* env, jbyteArray j_session_id) {
57 std::vector<uint8> session_id_vector;
58 JavaByteArrayToByteVector(env, j_session_id, &session_id_vector);
59 return std::string(session_id_vector.begin(), session_id_vector.end());
62 // The structure of an ISO CENC Protection System Specific Header (PSSH) box is
63 // as follows. (See ISO/IEC FDIS 23001-7:2011(E).)
64 // Note: ISO boxes use big-endian values.
66 // PSSH {
67 // uint32 Size
68 // uint32 Type
69 // uint64 LargeSize # Field is only present if value(Size) == 1.
70 // uint32 VersionAndFlags
71 // uint8[16] SystemId
72 // uint32 DataSize
73 // uint8[DataSize] Data
74 // }
75 const int kBoxHeaderSize = 8; // Box's header contains Size and Type.
76 const int kBoxLargeSizeSize = 8;
77 const int kPsshVersionFlagSize = 4;
78 const int kPsshSystemIdSize = 16;
79 const int kPsshDataSizeSize = 4;
80 const uint32 kTencType = 0x74656e63;
81 const uint32 kPsshType = 0x70737368;
82 const uint8 kWidevineUuid[16] = {
83 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
84 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED };
86 typedef std::vector<uint8> UUID;
88 // Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the
89 // "Data" of the box and put it in |pssh_data|. Returns true if such a box is
90 // found and successfully parsed. Returns false otherwise.
91 // Notes:
92 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box
93 // will be set in |pssh_data|.
94 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped.
95 bool GetPsshData(const uint8* data,
96 int data_size,
97 const UUID& uuid,
98 std::vector<uint8>* pssh_data) {
99 const uint8* cur = data;
100 const uint8* data_end = data + data_size;
101 int bytes_left = data_size;
103 while (bytes_left > 0) {
104 const uint8* box_head = cur;
106 if (bytes_left < kBoxHeaderSize)
107 return false;
109 uint64_t box_size = ReadUint32(cur);
110 uint32 type = ReadUint32(cur + 4);
111 cur += kBoxHeaderSize;
112 bytes_left -= kBoxHeaderSize;
114 if (box_size == 1) { // LargeSize is present.
115 if (bytes_left < kBoxLargeSizeSize)
116 return false;
118 box_size = ReadUint64(cur);
119 cur += kBoxLargeSizeSize;
120 bytes_left -= kBoxLargeSizeSize;
121 } else if (box_size == 0) {
122 box_size = bytes_left + kBoxHeaderSize;
125 const uint8* box_end = box_head + box_size;
126 if (data_end < box_end)
127 return false;
129 if (type == kTencType) {
130 // Skip 'tenc' box.
131 cur = box_end;
132 bytes_left = data_end - cur;
133 continue;
134 } else if (type != kPsshType) {
135 return false;
138 const int kPsshBoxMinimumSize =
139 kPsshVersionFlagSize + kPsshSystemIdSize + kPsshDataSizeSize;
140 if (box_end < cur + kPsshBoxMinimumSize)
141 return false;
143 uint32 version_and_flags = ReadUint32(cur);
144 cur += kPsshVersionFlagSize;
145 bytes_left -= kPsshVersionFlagSize;
146 if (version_and_flags != 0)
147 return false;
149 DCHECK_GE(bytes_left, kPsshSystemIdSize);
150 if (!std::equal(uuid.begin(), uuid.end(), cur)) {
151 cur = box_end;
152 bytes_left = data_end - cur;
153 continue;
156 cur += kPsshSystemIdSize;
157 bytes_left -= kPsshSystemIdSize;
159 uint32 data_size = ReadUint32(cur);
160 cur += kPsshDataSizeSize;
161 bytes_left -= kPsshDataSizeSize;
163 if (box_end < cur + data_size)
164 return false;
166 pssh_data->assign(cur, cur + data_size);
167 return true;
170 return false;
173 class KeySystemUuidManager {
174 public:
175 KeySystemUuidManager();
176 UUID GetUUID(const std::string& key_system);
177 void AddMapping(const std::string& key_system, const UUID& uuid);
178 std::vector<std::string> GetPlatformKeySystemNames();
180 private:
181 typedef base::hash_map<std::string, UUID> KeySystemUuidMap;
183 KeySystemUuidMap key_system_uuid_map_;
185 DISALLOW_COPY_AND_ASSIGN(KeySystemUuidManager);
188 KeySystemUuidManager::KeySystemUuidManager() {
189 // Widevine is always supported in Android.
190 key_system_uuid_map_[kWidevineKeySystem] =
191 UUID(kWidevineUuid, kWidevineUuid + arraysize(kWidevineUuid));
194 UUID KeySystemUuidManager::GetUUID(const std::string& key_system) {
195 KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system);
196 if (it == key_system_uuid_map_.end())
197 return UUID();
198 return it->second;
201 void KeySystemUuidManager::AddMapping(const std::string& key_system,
202 const UUID& uuid) {
203 KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system);
204 DCHECK(it == key_system_uuid_map_.end())
205 << "Shouldn't overwrite an existing key system.";
206 if (it != key_system_uuid_map_.end())
207 return;
208 key_system_uuid_map_[key_system] = uuid;
211 std::vector<std::string> KeySystemUuidManager::GetPlatformKeySystemNames() {
212 std::vector<std::string> key_systems;
213 for (KeySystemUuidMap::iterator it = key_system_uuid_map_.begin();
214 it != key_system_uuid_map_.end(); ++it) {
215 // Rule out the key system handled by Chrome explicitly.
216 if (it->first != kWidevineKeySystem)
217 key_systems.push_back(it->first);
219 return key_systems;
222 base::LazyInstance<KeySystemUuidManager>::Leaky g_key_system_uuid_manager =
223 LAZY_INSTANCE_INITIALIZER;
225 // Checks whether |key_system| is supported with |container_mime_type|. Only
226 // checks |key_system| support if |container_mime_type| is empty.
227 // TODO(xhwang): The |container_mime_type| is not the same as contentType in
228 // the EME spec. Revisit this once the spec issue with initData type is
229 // resolved.
230 bool IsKeySystemSupportedWithTypeImpl(const std::string& key_system,
231 const std::string& container_mime_type) {
232 if (!MediaDrmBridge::IsAvailable())
233 return false;
235 UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system);
236 if (scheme_uuid.empty())
237 return false;
239 JNIEnv* env = AttachCurrentThread();
240 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid =
241 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size());
242 ScopedJavaLocalRef<jstring> j_container_mime_type =
243 ConvertUTF8ToJavaString(env, container_mime_type);
244 return Java_MediaDrmBridge_isCryptoSchemeSupported(
245 env, j_scheme_uuid.obj(), j_container_mime_type.obj());
248 MediaDrmBridge::SecurityLevel GetSecurityLevelFromString(
249 const std::string& security_level_str) {
250 if (0 == security_level_str.compare("L1"))
251 return MediaDrmBridge::SECURITY_LEVEL_1;
252 if (0 == security_level_str.compare("L3"))
253 return MediaDrmBridge::SECURITY_LEVEL_3;
254 DCHECK(security_level_str.empty());
255 return MediaDrmBridge::SECURITY_LEVEL_NONE;
258 std::string GetSecurityLevelString(
259 MediaDrmBridge::SecurityLevel security_level) {
260 switch (security_level) {
261 case MediaDrmBridge::SECURITY_LEVEL_NONE:
262 return "";
263 case MediaDrmBridge::SECURITY_LEVEL_1:
264 return "L1";
265 case MediaDrmBridge::SECURITY_LEVEL_3:
266 return "L3";
268 return "";
271 } // namespace
273 // Called by Java.
274 static void AddKeySystemUuidMapping(JNIEnv* env,
275 jclass clazz,
276 jstring j_key_system,
277 jobject j_buffer) {
278 std::string key_system = ConvertJavaStringToUTF8(env, j_key_system);
279 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer));
280 UUID uuid(buffer, buffer + 16);
281 g_key_system_uuid_manager.Get().AddMapping(key_system, uuid);
284 // static
285 bool MediaDrmBridge::IsAvailable() {
286 if (base::android::BuildInfo::GetInstance()->sdk_int() < 19)
287 return false;
289 int32 os_major_version = 0;
290 int32 os_minor_version = 0;
291 int32 os_bugfix_version = 0;
292 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
293 &os_minor_version,
294 &os_bugfix_version);
295 if (os_major_version == 4 && os_minor_version == 4 && os_bugfix_version == 0)
296 return false;
298 return true;
301 // TODO(ddorwin): This is specific to Widevine. http://crbug.com/459400
302 // static
303 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) {
304 DCHECK(IsAvailable());
305 return SECURITY_LEVEL_1 == security_level;
308 // static
309 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() {
310 return g_key_system_uuid_manager.Get().GetPlatformKeySystemNames();
313 // static
314 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) {
315 DCHECK(!key_system.empty());
316 return IsKeySystemSupportedWithTypeImpl(key_system, "");
319 // static
320 bool MediaDrmBridge::IsKeySystemSupportedWithType(
321 const std::string& key_system,
322 const std::string& container_mime_type) {
323 DCHECK(!key_system.empty() && !container_mime_type.empty());
324 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type);
327 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) {
328 return RegisterNativesImpl(env);
331 MediaDrmBridge::MediaDrmBridge(
332 const std::vector<uint8>& scheme_uuid,
333 const SessionMessageCB& session_message_cb,
334 const SessionClosedCB& session_closed_cb,
335 const SessionErrorCB& session_error_cb,
336 const SessionKeysChangeCB& session_keys_change_cb)
337 : scheme_uuid_(scheme_uuid),
338 session_message_cb_(session_message_cb),
339 session_closed_cb_(session_closed_cb),
340 session_error_cb_(session_error_cb),
341 session_keys_change_cb_(session_keys_change_cb) {
342 JNIEnv* env = AttachCurrentThread();
343 CHECK(env);
345 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid =
346 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size());
347 j_media_drm_.Reset(Java_MediaDrmBridge_create(
348 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this)));
351 MediaDrmBridge::~MediaDrmBridge() {
352 JNIEnv* env = AttachCurrentThread();
353 player_tracker_.NotifyCdmUnset();
354 if (!j_media_drm_.is_null())
355 Java_MediaDrmBridge_destroy(env, j_media_drm_.obj());
358 // static
359 // TODO(xhwang): Enable SessionExpirationUpdateCB when it is supported.
360 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(
361 const std::string& key_system,
362 const SessionMessageCB& session_message_cb,
363 const SessionClosedCB& session_closed_cb,
364 const SessionErrorCB& session_error_cb,
365 const SessionKeysChangeCB& session_keys_change_cb,
366 const SessionExpirationUpdateCB& /* session_expiration_update_cb */) {
367 scoped_ptr<MediaDrmBridge> media_drm_bridge;
368 if (!IsAvailable())
369 return media_drm_bridge.Pass();
371 UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system);
372 if (scheme_uuid.empty())
373 return media_drm_bridge.Pass();
375 media_drm_bridge.reset(new MediaDrmBridge(scheme_uuid, session_message_cb,
376 session_closed_cb, session_error_cb,
377 session_keys_change_cb));
379 if (media_drm_bridge->j_media_drm_.is_null())
380 media_drm_bridge.reset();
382 return media_drm_bridge.Pass();
385 // static
386 scoped_ptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport(
387 const std::string& key_system) {
388 return MediaDrmBridge::Create(
389 key_system, SessionMessageCB(), SessionClosedCB(), SessionErrorCB(),
390 SessionKeysChangeCB(), SessionExpirationUpdateCB());
393 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) {
394 if (security_level != SECURITY_LEVEL_NONE &&
395 !std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid)) {
396 NOTREACHED() << "Widevine security level " << security_level
397 << "used with another key system";
398 return false;
401 JNIEnv* env = AttachCurrentThread();
403 std::string security_level_str = GetSecurityLevelString(security_level);
404 if (security_level_str.empty())
405 return false;
407 ScopedJavaLocalRef<jstring> j_security_level =
408 ConvertUTF8ToJavaString(env, security_level_str);
409 return Java_MediaDrmBridge_setSecurityLevel(
410 env, j_media_drm_.obj(), j_security_level.obj());
413 void MediaDrmBridge::SetServerCertificate(
414 const uint8* certificate_data,
415 int certificate_data_length,
416 scoped_ptr<media::SimpleCdmPromise> promise) {
417 promise->reject(NOT_SUPPORTED_ERROR, 0,
418 "SetServerCertificate() is not supported.");
421 void MediaDrmBridge::CreateSessionAndGenerateRequest(
422 SessionType session_type,
423 const std::string& init_data_type,
424 const uint8* init_data,
425 int init_data_length,
426 scoped_ptr<media::NewSessionCdmPromise> promise) {
427 DVLOG(1) << __FUNCTION__;
429 if (session_type != media::MediaKeys::TEMPORARY_SESSION) {
430 promise->reject(NOT_SUPPORTED_ERROR, 0,
431 "Only the temporary session type is supported.");
432 return;
435 JNIEnv* env = AttachCurrentThread();
436 ScopedJavaLocalRef<jbyteArray> j_init_data;
437 // Caller should always use "video/*" content types.
438 DCHECK_EQ(0u, init_data_type.find("video/"));
440 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as
441 // the init data when using MP4 container.
442 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) &&
443 init_data_type == "video/mp4") {
444 std::vector<uint8> pssh_data;
445 if (!GetPsshData(init_data, init_data_length, scheme_uuid_, &pssh_data)) {
446 promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid PSSH data.");
447 return;
449 j_init_data =
450 base::android::ToJavaByteArray(env, &pssh_data[0], pssh_data.size());
451 } else {
452 j_init_data =
453 base::android::ToJavaByteArray(env, init_data, init_data_length);
456 ScopedJavaLocalRef<jstring> j_mime =
457 ConvertUTF8ToJavaString(env, init_data_type);
458 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass());
459 Java_MediaDrmBridge_createSession(env, j_media_drm_.obj(), j_init_data.obj(),
460 j_mime.obj(), promise_id);
463 void MediaDrmBridge::LoadSession(
464 SessionType session_type,
465 const std::string& session_id,
466 scoped_ptr<media::NewSessionCdmPromise> promise) {
467 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported.");
470 void MediaDrmBridge::UpdateSession(
471 const std::string& session_id,
472 const uint8* response,
473 int response_length,
474 scoped_ptr<media::SimpleCdmPromise> promise) {
475 DVLOG(1) << __FUNCTION__;
477 JNIEnv* env = AttachCurrentThread();
478 ScopedJavaLocalRef<jbyteArray> j_response =
479 base::android::ToJavaByteArray(env, response, response_length);
480 ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray(
481 env, reinterpret_cast<const uint8_t*>(session_id.data()),
482 session_id.size());
483 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass());
484 Java_MediaDrmBridge_updateSession(env, j_media_drm_.obj(), j_session_id.obj(),
485 j_response.obj(), promise_id);
488 void MediaDrmBridge::CloseSession(const std::string& session_id,
489 scoped_ptr<media::SimpleCdmPromise> promise) {
490 DVLOG(1) << __FUNCTION__;
491 JNIEnv* env = AttachCurrentThread();
492 ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray(
493 env, reinterpret_cast<const uint8_t*>(session_id.data()),
494 session_id.size());
495 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass());
496 Java_MediaDrmBridge_closeSession(env, j_media_drm_.obj(), j_session_id.obj(),
497 promise_id);
500 void MediaDrmBridge::RemoveSession(
501 const std::string& session_id,
502 scoped_ptr<media::SimpleCdmPromise> promise) {
503 promise->reject(NOT_SUPPORTED_ERROR, 0, "RemoveSession() is not supported.");
506 CdmContext* MediaDrmBridge::GetCdmContext() {
507 NOTREACHED();
508 return nullptr;
511 int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb,
512 const base::Closure& cdm_unset_cb) {
513 return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb);
516 void MediaDrmBridge::UnregisterPlayer(int registration_id) {
517 player_tracker_.UnregisterPlayer(registration_id);
520 void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) {
521 if (closure.is_null()) {
522 media_crypto_ready_cb_.Reset();
523 return;
526 DCHECK(media_crypto_ready_cb_.is_null());
528 if (!GetMediaCrypto().is_null()) {
529 base::MessageLoopProxy::current()->PostTask(FROM_HERE, closure);
530 return;
533 media_crypto_ready_cb_ = closure;
536 void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject) {
537 DCHECK(!GetMediaCrypto().is_null());
538 if (!media_crypto_ready_cb_.is_null())
539 base::ResetAndReturn(&media_crypto_ready_cb_).Run();
542 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env,
543 jobject j_media_drm,
544 jint j_promise_id) {
545 cdm_promise_adapter_.ResolvePromise(j_promise_id);
548 void MediaDrmBridge::OnPromiseResolvedWithSession(JNIEnv* env,
549 jobject j_media_drm,
550 jint j_promise_id,
551 jbyteArray j_session_id) {
552 cdm_promise_adapter_.ResolvePromise(j_promise_id,
553 GetSessionId(env, j_session_id));
556 void MediaDrmBridge::OnPromiseRejected(JNIEnv* env,
557 jobject j_media_drm,
558 jint j_promise_id,
559 jstring j_error_message) {
560 std::string error_message = ConvertJavaStringToUTF8(env, j_error_message);
561 cdm_promise_adapter_.RejectPromise(j_promise_id, MediaKeys::UNKNOWN_ERROR, 0,
562 error_message);
565 void MediaDrmBridge::OnSessionMessage(JNIEnv* env,
566 jobject j_media_drm,
567 jbyteArray j_session_id,
568 jbyteArray j_message,
569 jstring j_legacy_destination_url) {
570 std::vector<uint8> message;
571 JavaByteArrayToByteVector(env, j_message, &message);
572 GURL legacy_destination_url =
573 GURL(ConvertJavaStringToUTF8(env, j_legacy_destination_url));
574 // Note: Message type is not supported in MediaDrm. Do our best guess here.
575 media::MediaKeys::MessageType message_type =
576 legacy_destination_url.is_empty() ? media::MediaKeys::LICENSE_REQUEST
577 : media::MediaKeys::LICENSE_RENEWAL;
579 session_message_cb_.Run(GetSessionId(env, j_session_id), message_type,
580 message, legacy_destination_url);
583 void MediaDrmBridge::OnSessionClosed(JNIEnv* env,
584 jobject j_media_drm,
585 jbyteArray j_session_id) {
586 session_closed_cb_.Run(GetSessionId(env, j_session_id));
589 void MediaDrmBridge::OnSessionKeysChange(JNIEnv* env,
590 jobject j_media_drm,
591 jbyteArray j_session_id,
592 bool has_additional_usable_key,
593 jint j_key_status) {
594 if (has_additional_usable_key)
595 player_tracker_.NotifyNewKey();
597 scoped_ptr<CdmKeyInformation> cdm_key_information(new CdmKeyInformation());
598 cdm_key_information->key_id.assign(kDummyKeyId,
599 kDummyKeyId + sizeof(kDummyKeyId));
600 cdm_key_information->status =
601 static_cast<CdmKeyInformation::KeyStatus>(j_key_status);
602 CdmKeysInfo cdm_keys_info;
603 cdm_keys_info.push_back(cdm_key_information.release());
605 session_keys_change_cb_.Run(GetSessionId(env, j_session_id),
606 has_additional_usable_key, cdm_keys_info.Pass());
609 void MediaDrmBridge::OnLegacySessionError(JNIEnv* env,
610 jobject j_media_drm,
611 jbyteArray j_session_id,
612 jstring j_error_message) {
613 std::string error_message = ConvertJavaStringToUTF8(env, j_error_message);
614 session_error_cb_.Run(GetSessionId(env, j_session_id),
615 MediaKeys::UNKNOWN_ERROR, 0, error_message);
618 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() {
619 JNIEnv* env = AttachCurrentThread();
620 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj());
623 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() {
624 JNIEnv* env = AttachCurrentThread();
625 ScopedJavaLocalRef<jstring> j_security_level =
626 Java_MediaDrmBridge_getSecurityLevel(env, j_media_drm_.obj());
627 std::string security_level_str =
628 ConvertJavaStringToUTF8(env, j_security_level.obj());
629 return GetSecurityLevelFromString(security_level_str);
632 bool MediaDrmBridge::IsProtectedSurfaceRequired() {
633 // For Widevine, this depends on the security level.
634 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid))
635 return IsSecureDecoderRequired(GetSecurityLevel());
637 // For other key systems, assume true.
638 return true;
641 void MediaDrmBridge::ResetDeviceCredentials(
642 const ResetCredentialsCB& callback) {
643 DCHECK(reset_credentials_cb_.is_null());
644 reset_credentials_cb_ = callback;
645 JNIEnv* env = AttachCurrentThread();
646 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj());
649 void MediaDrmBridge::OnResetDeviceCredentialsCompleted(
650 JNIEnv* env, jobject, bool success) {
651 base::ResetAndReturn(&reset_credentials_cb_).Run(success);
654 } // namespace media