Widevine drm aidl: address API review

Interface update in change 16810770

Bug: 214410088
Test: atest VtsAidlHalDrmTargetTest
Change-Id: I19da51ef75952f5ff6c7c02e0393f574e69ee30b
This commit is contained in:
Edwin
2022-02-08 16:16:12 -08:00
parent 6112060529
commit 9654d29be6
15 changed files with 150 additions and 292 deletions

View File

@@ -468,7 +468,6 @@ cc_library_shared {
"src/WVUUID.cpp", "src/WVUUID.cpp",
"aidl_src/wv_metrics.cpp", "aidl_src/wv_metrics.cpp",
"aidl_src/WVCreatePluginFactories.cpp", "aidl_src/WVCreatePluginFactories.cpp",
"aidl_src/WVCryptoFactory.cpp",
"aidl_src/WVDrmFactory.cpp", "aidl_src/WVDrmFactory.cpp",
], ],

View File

@@ -36,12 +36,17 @@ inline ::aidl::android::hardware::drm::LogPriority toAidlLogPriority(
} }
inline ::ndk::ScopedAStatus toNdkScopedAStatus( inline ::ndk::ScopedAStatus toNdkScopedAStatus(
::aidl::android::hardware::drm::Status status) { ::aidl::android::hardware::drm::Status status, const char* msg = nullptr) {
if (::aidl::android::hardware::drm::Status::OK == status) if (::aidl::android::hardware::drm::Status::OK == status)
return ::ndk::ScopedAStatus::ok(); return ::ndk::ScopedAStatus::ok();
else { else {
return ::ndk::ScopedAStatus::fromServiceSpecificError( auto err = static_cast<int32_t>(status);
static_cast<int32_t>(status)); if (msg) {
return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(err,
msg);
} else {
return ::ndk::ScopedAStatus::fromServiceSpecificError(err);
}
} }
} }

View File

@@ -7,7 +7,6 @@
#ifndef WV_CREATE_PLUGIN_FACTORIES_H_ #ifndef WV_CREATE_PLUGIN_FACTORIES_H_
#define WV_CREATE_PLUGIN_FACTORIES_H_ #define WV_CREATE_PLUGIN_FACTORIES_H_
#include "WVCryptoFactory.h"
#include "WVDrmFactory.h" #include "WVDrmFactory.h"
namespace wvdrm { namespace wvdrm {
@@ -16,7 +15,6 @@ namespace drm {
namespace widevine { namespace widevine {
std::shared_ptr<WVDrmFactory> createDrmFactory(); std::shared_ptr<WVDrmFactory> createDrmFactory();
std::shared_ptr<WVCryptoFactory> createCryptoFactory();
} // namespace widevine } // namespace widevine
} // namespace drm } // namespace drm

View File

@@ -1,45 +0,0 @@
//
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
//
#ifndef WV_CRYPTO_FACTORY_H_
#define WV_CRYPTO_FACTORY_H_
#include <aidl/android/hardware/drm/BnCryptoFactory.h>
#include <aidl/android/hardware/drm/ICryptoFactory.h>
#include <aidl/android/hardware/drm/ICryptoPlugin.h>
#include "WVTypes.h"
namespace wvdrm {
namespace hardware {
namespace drm {
namespace widevine {
struct WVCryptoFactory : public ::aidl::android::hardware::drm::BnCryptoFactory {
public:
WVCryptoFactory() {}
virtual ~WVCryptoFactory() {}
::ndk::ScopedAStatus createPlugin(
const ::aidl::android::hardware::drm::Uuid& in_uuid,
const std::vector<uint8_t>& in_initData,
std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>*
_aidl_return) override;
::ndk::ScopedAStatus isCryptoSchemeSupported(
const ::aidl::android::hardware::drm::Uuid& in_uuid,
bool* _aidl_return) override;
private:
WVDRM_DISALLOW_COPY_AND_ASSIGN(WVCryptoFactory);
};
} // namespace widevine
} // namespace drm
} // namespace hardware
} // namespace wvdrm
#endif // WV_CRYPTO_FACTORY_H_

View File

@@ -23,29 +23,26 @@ struct WVDrmFactory : public ::aidl::android::hardware::drm::BnDrmFactory {
WVDrmFactory() {} WVDrmFactory() {}
virtual ~WVDrmFactory() {} virtual ~WVDrmFactory() {}
::ndk::ScopedAStatus createPlugin( ::ndk::ScopedAStatus createDrmPlugin(
const ::aidl::android::hardware::drm::Uuid& in_uuid, const ::aidl::android::hardware::drm::Uuid& in_uuid,
const std::string& in_appPackageName, const std::string& in_appPackageName,
std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return)
override; override;
::ndk::ScopedAStatus createCryptoPlugin(
const ::aidl::android::hardware::drm::Uuid& in_uuid,
const std::vector<uint8_t>& in_initData,
std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>*
_aidl_return) override;
::ndk::ScopedAStatus getSupportedCryptoSchemes( ::ndk::ScopedAStatus getSupportedCryptoSchemes(
std::vector<::aidl::android::hardware::drm::Uuid>* _aidl_return) override; ::aidl::android::hardware::drm::CryptoSchemes* _aidl_return) override;
::ndk::ScopedAStatus isContentTypeSupported(const std::string& in_mimeType, // This method is not part of the AIDL interface, it is provided
bool* _aidl_return) override;
// This overloaded method is not part of the AIDL interface, it is provided
// for Widevine CDM. // for Widevine CDM.
bool isCryptoSchemeSupported( bool isCryptoSchemeSupported(
const ::aidl::android::hardware::drm::Uuid& in_uuid); const ::aidl::android::hardware::drm::Uuid& in_uuid);
::ndk::ScopedAStatus isCryptoSchemeSupported(
const ::aidl::android::hardware::drm::Uuid& in_uuid,
const std::string& in_mimeType,
::aidl::android::hardware::drm::SecurityLevel in_securityLevel,
bool* _aidl_return) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
private: private:

View File

@@ -15,10 +15,6 @@ std::shared_ptr<WVDrmFactory> createDrmFactory() {
return std::make_shared<WVDrmFactory>(); return std::make_shared<WVDrmFactory>();
} }
std::shared_ptr<WVCryptoFactory> createCryptoFactory() {
return std::make_shared<WVCryptoFactory>();
}
} // namespace widevine } // namespace widevine
} // namespace drm } // namespace drm
} // namespace hardware } // namespace hardware

View File

@@ -1,65 +0,0 @@
//
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
//
//#define LOG_NDEBUG 0
#define LOG_TAG "WVCdm"
#include "WVCryptoFactory.h"
#include <android/binder_ibinder_platform.h>
#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include "Utils.h"
#include "WVCDMSingleton.h"
#include "WVCryptoPlugin.h"
#include "WVUUID.h"
namespace wvdrm {
namespace hardware {
namespace drm {
namespace widevine {
using ::aidl::android::hardware::drm::Status;
using ::aidl::android::hardware::drm::Uuid;
::ndk::ScopedAStatus WVCryptoFactory::isCryptoSchemeSupported(
const Uuid& in_uuid, bool* _aidl_return) {
*_aidl_return = isWidevineUUID(in_uuid.uuid.data());
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus WVCryptoFactory::createPlugin(
const ::aidl::android::hardware::drm::Uuid& in_uuid,
const std::vector<uint8_t>& in_initData,
std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>*
_aidl_return) {
const auto& self = android::IPCThreadState::self();
const char* sid = self->getCallingSid();
sid = sid ? (std::strstr(sid, "mediadrmserver") ? sid : "app") : "nullptr";
ALOGI("[%s] calling %s", sid, __PRETTY_FUNCTION__);
bool isSupported = false;
isCryptoSchemeSupported(in_uuid, &isSupported);
if (!isSupported) {
ALOGE(
"Widevine Drm HAL: failed to create crypto plugin, "
"invalid crypto scheme");
*_aidl_return = nullptr;
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
}
std::shared_ptr<WVCryptoPlugin> plugin =
::ndk::SharedRefBase::make<WVCryptoPlugin>(in_initData.data(),
in_initData.size(), getCDM());
AIBinder_setRequestingSid(plugin->asBinder().get(), true);
*_aidl_return = std::move(plugin);
return toNdkScopedAStatus(Status::OK);
}
} // namespace widevine
} // namespace drm
} // namespace hardware
} // namespace wvdrm

View File

@@ -15,6 +15,7 @@
#include "Utils.h" #include "Utils.h"
#include "WVCDMSingleton.h" #include "WVCDMSingleton.h"
#include "WVCryptoPlugin.h"
#include "WVDrmPlugin.h" #include "WVDrmPlugin.h"
#include "WVUUID.h" #include "WVUUID.h"
#include "android-base/properties.h" #include "android-base/properties.h"
@@ -31,6 +32,7 @@ namespace widevine {
using std::string; using std::string;
using std::vector; using std::vector;
using ::aidl::android::hardware::drm::CryptoSchemes;
using ::aidl::android::hardware::drm::SecurityLevel; using ::aidl::android::hardware::drm::SecurityLevel;
using ::aidl::android::hardware::drm::Status; using ::aidl::android::hardware::drm::Status;
using ::aidl::android::hardware::drm::Uuid; using ::aidl::android::hardware::drm::Uuid;
@@ -41,40 +43,33 @@ bool WVDrmFactory::isCryptoSchemeSupported(const Uuid& in_uuid) {
return isWidevineUUID(in_uuid.uuid.data()); return isWidevineUUID(in_uuid.uuid.data());
} }
::ndk::ScopedAStatus WVDrmFactory::isCryptoSchemeSupported( ::ndk::ScopedAStatus WVDrmFactory::createCryptoPlugin(
const Uuid& in_uuid, const string& in_mimeType, const ::aidl::android::hardware::drm::Uuid& in_uuid,
SecurityLevel in_securityLevel, bool* _aidl_return) { const std::vector<uint8_t>& in_initData,
bool isMimeTypeSupported = false; std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>*
isContentTypeSupported(in_mimeType, &isMimeTypeSupported); _aidl_return) {
if (!isWidevineUUID(in_uuid.uuid.data()) || !isMimeTypeSupported) { const auto& self = android::IPCThreadState::self();
*_aidl_return = false; const char* sid = self->getCallingSid();
return ::ndk::ScopedAStatus::ok(); sid = sid ? (std::strstr(sid, "mediadrmserver") ? sid : "app") : "nullptr";
ALOGI("[%s] calling %s", sid, __PRETTY_FUNCTION__);
if (!isCryptoSchemeSupported(in_uuid)) {
ALOGE(
"Widevine Drm HAL: failed to create crypto plugin, "
"invalid crypto scheme");
*_aidl_return = nullptr;
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
} }
if (wvcdm::WvContentDecryptionModule::IsSecurityLevelSupported( std::shared_ptr<WVCryptoPlugin> plugin =
wvcdm::kSecurityLevelL1)) { ::ndk::SharedRefBase::make<WVCryptoPlugin>(in_initData.data(),
if (wvcdm::WvContentDecryptionModule::IsAudio(in_mimeType)) { in_initData.size(), getCDM());
if (in_securityLevel < SecurityLevel::HW_SECURE_ALL) { AIBinder_setRequestingSid(plugin->asBinder().get(), true);
*_aidl_return = true; *_aidl_return = std::move(plugin);
return ::ndk::ScopedAStatus::ok(); return toNdkScopedAStatus(Status::OK);
}
} else {
*_aidl_return = true;
return ::ndk::ScopedAStatus::ok();
}
}
*_aidl_return = in_securityLevel <= SecurityLevel::SW_SECURE_DECODE;
return ::ndk::ScopedAStatus::ok();
} }
::ndk::ScopedAStatus WVDrmFactory::isContentTypeSupported( ::ndk::ScopedAStatus WVDrmFactory::createDrmPlugin(
const string& in_mimeType, bool* _aidl_return) {
*_aidl_return =
wvcdm::WvContentDecryptionModule::IsSupported(in_mimeType.c_str());
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus WVDrmFactory::createPlugin(
const Uuid& in_uuid, const string& in_appPackageName, const Uuid& in_uuid, const string& in_appPackageName,
std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) { std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) {
const auto& self = ::android::IPCThreadState::self(); const auto& self = ::android::IPCThreadState::self();
@@ -130,13 +125,22 @@ int32_t WVDrmFactory::firstApiLevel() {
} }
::ndk::ScopedAStatus WVDrmFactory::getSupportedCryptoSchemes( ::ndk::ScopedAStatus WVDrmFactory::getSupportedCryptoSchemes(
vector<Uuid>* _aidl_return) { CryptoSchemes* _aidl_return) {
vector<Uuid> schemes; CryptoSchemes schemes{};
Uuid scheme;
for (const auto& uuid : wvdrm::getSupportedCryptoSchemes()) { for (const auto& uuid : wvdrm::getSupportedCryptoSchemes()) {
scheme.uuid.assign(uuid.begin(), uuid.end()); schemes.uuids.push_back({uuid});
schemes.push_back(scheme);
} }
schemes.minLevel = schemes.maxLevel = SecurityLevel::SW_SECURE_CRYPTO;
if (wvcdm::WvContentDecryptionModule::IsSecurityLevelSupported(
wvcdm::kSecurityLevelL1)) {
schemes.maxLevel = SecurityLevel::HW_SECURE_ALL;
}
schemes.mimeTypes = {
wvcdm::ISO_BMFF_VIDEO_MIME_TYPE, wvcdm::ISO_BMFF_AUDIO_MIME_TYPE,
wvcdm::WEBM_VIDEO_MIME_TYPE, wvcdm::WEBM_AUDIO_MIME_TYPE,
wvcdm::CENC_INIT_DATA_FORMAT, wvcdm::HLS_INIT_DATA_FORMAT,
wvcdm::WEBM_INIT_DATA_FORMAT};
*_aidl_return = schemes; *_aidl_return = schemes;
return ::ndk::ScopedAStatus::ok(); return ::ndk::ScopedAStatus::ok();
} }

View File

@@ -2,7 +2,6 @@ on property:init.svc.mediadrm=running
mkdir /data/vendor/mediadrm 0770 media mediadrm mkdir /data/vendor/mediadrm 0770 media mediadrm
service vendor.drm-widevine-hal /vendor/bin/hw/android.hardware.drm-service.widevine service vendor.drm-widevine-hal /vendor/bin/hw/android.hardware.drm-service.widevine
interface aidl android.hardware.drm::ICryptoFactory/widevine
interface aidl android.hardware.drm::IDrmFactory/widevine interface aidl android.hardware.drm::IDrmFactory/widevine
class hal class hal
user media user media

View File

@@ -22,12 +22,9 @@
#include <binder/ProcessState.h> #include <binder/ProcessState.h>
#include "WVCreatePluginFactories.h" #include "WVCreatePluginFactories.h"
#include "WVCryptoFactory.h"
#include "WVDrmFactory.h" #include "WVDrmFactory.h"
using ::wvdrm::hardware::drm::widevine::createCryptoFactory;
using ::wvdrm::hardware::drm::widevine::createDrmFactory; using ::wvdrm::hardware::drm::widevine::createDrmFactory;
using ::wvdrm::hardware::drm::widevine::WVCryptoFactory;
using ::wvdrm::hardware::drm::widevine::WVDrmFactory; using ::wvdrm::hardware::drm::widevine::WVDrmFactory;
int main(int /* argc */, char** /* argv */) { int main(int /* argc */, char** /* argv */) {
@@ -41,13 +38,5 @@ int main(int /* argc */, char** /* argv */) {
CHECK(status == STATUS_OK) CHECK(status == STATUS_OK)
<< "Failed to add Widevine Factory HAL, status=" << status; << "Failed to add Widevine Factory HAL, status=" << status;
std::shared_ptr<WVCryptoFactory> cryptoFactory = createCryptoFactory();
const std::string cryptoInstance =
std::string(WVCryptoFactory::descriptor) + "/widevine";
status = AServiceManager_addService(cryptoFactory->asBinder().get(),
cryptoInstance.c_str());
CHECK(status == STATUS_OK)
<< "Failed to add Widevine Crypto HAL, status=" << status;
ABinderProcess_joinThreadPool(); ABinderProcess_joinThreadPool();
} }

View File

@@ -17,7 +17,6 @@
<hal format="aidl"> <hal format="aidl">
<name>android.hardware.drm</name> <name>android.hardware.drm</name>
<version>1</version> <version>1</version>
<fqname>ICryptoFactory/widevine</fqname>
<fqname>IDrmFactory/widevine</fqname> <fqname>IDrmFactory/widevine</fqname>
</hal> </hal>
</manifest> </manifest>

View File

@@ -26,7 +26,7 @@ namespace widevine {
struct SharedBufferBase { struct SharedBufferBase {
uint8_t* mBase; uint8_t* mBase;
int64_t mSize; int64_t mSize;
SharedBufferBase(const ::aidl::android::hardware::common::Ashmem& mem); SharedBufferBase(const ::aidl::android::hardware::drm::SharedBuffer& mem);
~SharedBufferBase(); ~SharedBufferBase();
}; };
@@ -45,20 +45,11 @@ struct WVCryptoPlugin : public ::aidl::android::hardware::drm::BnCryptoPlugin {
const std::vector<uint8_t>& in_sessionId) override; const std::vector<uint8_t>& in_sessionId) override;
::ndk::ScopedAStatus setSharedBufferBase( ::ndk::ScopedAStatus setSharedBufferBase(
const ::aidl::android::hardware::common::Ashmem& in_base, const ::aidl::android::hardware::drm::SharedBuffer& in_base) override;
int32_t in_bufferId) override;
::ndk::ScopedAStatus decrypt( ::ndk::ScopedAStatus decrypt(
bool in_secure, const std::vector<uint8_t>& in_keyId, const ::aidl::android::hardware::drm::DecryptArgs& in_args,
const std::vector<uint8_t>& in_iv, int32_t* _aidl_return) override;
::aidl::android::hardware::drm::Mode in_mode,
const ::aidl::android::hardware::drm::Pattern& in_pattern,
const std::vector<::aidl::android::hardware::drm::SubSample>&
in_subSamples,
const ::aidl::android::hardware::drm::SharedBuffer& in_source,
int64_t in_offset,
const ::aidl::android::hardware::drm::DestinationBuffer& in_destination,
::aidl::android::hardware::drm::DecryptResult* _aidl_return) override;
::ndk::ScopedAStatus getLogMessages( ::ndk::ScopedAStatus getLogMessages(
std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return)
@@ -90,4 +81,4 @@ struct WVCryptoPlugin : public ::aidl::android::hardware::drm::BnCryptoPlugin {
} // namespace hardware } // namespace hardware
} // namespace wvdrm } // namespace wvdrm
#endif // WV_CRYPTO_PLUGIN_H_ #endif // WV_CRYPTO_PLUGIN_H_

View File

@@ -28,7 +28,7 @@ namespace hardware {
namespace drm { namespace drm {
namespace widevine { namespace widevine {
using ::aidl::android::hardware::drm::BufferType; using ::aidl::android::hardware::drm::DestinationBuffer;
using ::aidl::android::hardware::drm::Mode; using ::aidl::android::hardware::drm::Mode;
using ::aidl::android::hardware::drm::SharedBuffer; using ::aidl::android::hardware::drm::SharedBuffer;
using ::aidl::android::hardware::drm::Status; using ::aidl::android::hardware::drm::Status;
@@ -64,15 +64,16 @@ WVCryptoPlugin::~WVCryptoPlugin() {
} }
SharedBufferBase::SharedBufferBase( SharedBufferBase::SharedBufferBase(
const ::aidl::android::hardware::common::Ashmem& mem) const ::aidl::android::hardware::drm::SharedBuffer& mem)
: mBase(nullptr), mSize(mem.size) { : mBase(nullptr), mSize(mem.size) {
if (mem.fd.get() < 0) { if (mem.handle.fds.empty()) {
return; return;
} }
auto addr = mmap(nullptr, mem.size, PROT_READ | PROT_WRITE, MAP_SHARED, auto fd = mem.handle.fds[0].get();
mem.fd.get(), 0); auto addr =
mmap(nullptr, mem.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) { if (addr == MAP_FAILED) {
ALOGE("mmap err: fd %d; errno %s", mem.fd.get(), strerror(errno)); ALOGE("mmap err: fd %d; errno %s", fd, strerror(errno));
} else { } else {
mBase = static_cast<uint8_t*>(addr); mBase = static_cast<uint8_t*>(addr);
} }
@@ -129,97 +130,99 @@ SharedBufferBase::~SharedBufferBase() {
} }
::ndk::ScopedAStatus WVCryptoPlugin::setSharedBufferBase( ::ndk::ScopedAStatus WVCryptoPlugin::setSharedBufferBase(
const ::aidl::android::hardware::common::Ashmem& in_base, const ::aidl::android::hardware::drm::SharedBuffer& in_base) {
int32_t in_bufferId) {
std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock); std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
mSharedBufferMap[in_bufferId] = std::make_shared<SharedBufferBase>(in_base); mSharedBufferMap[in_base.bufferId] =
std::make_shared<SharedBufferBase>(in_base);
return ::ndk::ScopedAStatus::ok(); return ::ndk::ScopedAStatus::ok();
} }
::ndk::ScopedAStatus WVCryptoPlugin::decrypt( ::ndk::ScopedAStatus WVCryptoPlugin::decrypt(
bool in_secure, const std::vector<uint8_t>& in_keyId, const ::aidl::android::hardware::drm::DecryptArgs& in_args,
const std::vector<uint8_t>& in_iv, int32_t* _aidl_return) {
::aidl::android::hardware::drm::Mode in_mode, const char* detailedError = "";
const ::aidl::android::hardware::drm::Pattern& in_pattern, *_aidl_return = 0; // bytes decrypted
const std::vector<SubSample>& in_subSamples,
const ::aidl::android::hardware::drm::SharedBuffer& in_source,
int64_t in_offset,
const ::aidl::android::hardware::drm::DestinationBuffer& in_destination,
::aidl::android::hardware::drm::DecryptResult* _aidl_return) {
_aidl_return->bytesWritten = 0;
uint8_t* srcPtr = nullptr; uint8_t* srcPtr = nullptr;
void* destPtr = nullptr; void* destPtr = nullptr;
// Convert parameters to the form the CDM wishes to consume them in. // Convert parameters to the form the CDM wishes to consume them in.
const KeyId cryptoKey(reinterpret_cast<const char*>(in_keyId.data()), const KeyId cryptoKey(reinterpret_cast<const char*>(in_args.keyId.data()),
wvcdm::KEY_ID_SIZE); wvcdm::KEY_ID_SIZE);
// start scope for lock_guard // start scope for lock_guard
{ {
std::lock_guard<std::mutex> lock(mSharedBufferLock); std::lock_guard<std::mutex> lock(mSharedBufferLock);
if (mSharedBufferMap.find(in_source.bufferId) == mSharedBufferMap.end()) { if (mSharedBufferMap.find(in_args.source.bufferId) ==
_aidl_return->detailedError = "source decrypt buffer base not set"; mSharedBufferMap.end()) {
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); detailedError = "source decrypt buffer base not set";
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
} }
if (in_destination.type == BufferType::SHARED_MEMORY) { const auto NON_SECURE = DestinationBuffer::Tag::nonsecureMemory;
const SharedBuffer& dest = in_destination.nonsecureMemory; if (in_args.destination.getTag() == NON_SECURE) {
const SharedBuffer& dest = in_args.destination.get<NON_SECURE>();
if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) { if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
_aidl_return->detailedError = "destination decrypt buffer base not set"; detailedError = "destination decrypt buffer base not set";
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE,
detailedError);
} }
} }
if (in_mode != Mode::UNENCRYPTED && in_mode != Mode::AES_CTR && if (in_args.mode != Mode::UNENCRYPTED && in_args.mode != Mode::AES_CTR &&
in_mode != Mode::AES_CBC) { in_args.mode != Mode::AES_CBC) {
_aidl_return->detailedError = detailedError =
"The requested encryption mode is not supported by Widevine CDM."; "The requested encryption mode is not supported by Widevine CDM.";
return toNdkScopedAStatus(Status::BAD_VALUE); return toNdkScopedAStatus(Status::BAD_VALUE, detailedError);
} else if (in_mode == Mode::AES_CTR && } else if (in_args.mode == Mode::AES_CTR &&
(in_pattern.encryptBlocks != 0 || in_pattern.skipBlocks != 0)) { (in_args.pattern.encryptBlocks != 0 ||
_aidl_return->detailedError = in_args.pattern.skipBlocks != 0)) {
"The 'cens' schema is not supported by Widevine CDM."; detailedError = "The 'cens' schema is not supported by Widevine CDM.";
return toNdkScopedAStatus(Status::BAD_VALUE); return toNdkScopedAStatus(Status::BAD_VALUE, detailedError);
} }
auto src = mSharedBufferMap[in_source.bufferId]; auto src = mSharedBufferMap[in_args.source.bufferId];
if (src->mBase == nullptr) { if (src->mBase == nullptr) {
_aidl_return->detailedError = "source is a nullptr"; detailedError = "source is a nullptr";
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
} }
size_t totalSrcSize = 0; size_t totalSrcSize = 0;
if (__builtin_add_overflow(in_source.offset, in_offset, &totalSrcSize) || if (__builtin_add_overflow(in_args.source.offset, in_args.offset,
__builtin_add_overflow(totalSrcSize, in_source.size, &totalSrcSize) || &totalSrcSize) ||
__builtin_add_overflow(totalSrcSize, in_args.source.size,
&totalSrcSize) ||
totalSrcSize > src->mSize) { totalSrcSize > src->mSize) {
android_errorWriteLog(0x534e4554, "176496160"); android_errorWriteLog(0x534e4554, "176496160");
_aidl_return->detailedError = "invalid source buffer size"; detailedError = "invalid source buffer size";
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
} }
srcPtr = src->mBase + in_source.offset + in_offset; srcPtr = src->mBase + in_args.source.offset + in_args.offset;
if (in_destination.type == BufferType::SHARED_MEMORY) { if (in_args.destination.getTag() == NON_SECURE) {
const SharedBuffer& destBuffer = in_destination.nonsecureMemory; const SharedBuffer& destBuffer = in_args.destination.get<NON_SECURE>();
auto dest = mSharedBufferMap[destBuffer.bufferId]; auto dest = mSharedBufferMap[destBuffer.bufferId];
if (dest->mBase == nullptr) { if (dest->mBase == nullptr) {
_aidl_return->detailedError = "destination is a nullptr"; detailedError = "destination is a nullptr";
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE,
detailedError);
} }
size_t totalDstSize = 0; size_t totalDstSize = 0;
if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, if (__builtin_add_overflow(destBuffer.offset, destBuffer.size,
&totalDstSize) || &totalDstSize) ||
totalDstSize > dest->mSize) { totalDstSize > dest->mSize) {
android_errorWriteLog(0x534e4554, "176444622"); android_errorWriteLog(0x534e4554, "176444622");
_aidl_return->detailedError = "invalid buffer size"; detailedError = "invalid buffer size";
return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE); return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE,
detailedError);
} }
destPtr = static_cast<void*>(dest->mBase + destPtr = static_cast<void*>(
in_destination.nonsecureMemory.offset); dest->mBase + in_args.destination.get<NON_SECURE>().offset);
} else if (in_destination.type == BufferType::NATIVE_HANDLE) { } else if (in_args.destination.getTag() ==
native_handle_t* handle = DestinationBuffer::Tag::secureMemory) {
android::makeFromAidl(in_destination.secureMemory); native_handle_t* handle = android::makeFromAidl(
in_args.destination.get<DestinationBuffer::Tag::secureMemory>());
destPtr = static_cast<void*>(handle); destPtr = static_cast<void*>(handle);
} }
} // lock_guard scope } // lock_guard scope
@@ -227,14 +230,14 @@ SharedBufferBase::~SharedBufferBase() {
// Set up the decrypt params // Set up the decrypt params
CdmDecryptionParametersV16 params; CdmDecryptionParametersV16 params;
params.key_id = cryptoKey; params.key_id = cryptoKey;
params.is_secure = in_secure; params.is_secure = in_args.secure;
if (in_mode == Mode::AES_CTR) { if (in_args.mode == Mode::AES_CTR) {
params.cipher_mode = wvcdm::kCipherModeCtr; params.cipher_mode = wvcdm::kCipherModeCtr;
} else if (in_mode == Mode::AES_CBC) { } else if (in_args.mode == Mode::AES_CBC) {
params.cipher_mode = wvcdm::kCipherModeCbc; params.cipher_mode = wvcdm::kCipherModeCbc;
} }
params.pattern.encrypt_blocks = in_pattern.encryptBlocks; params.pattern.encrypt_blocks = in_args.pattern.encryptBlocks;
params.pattern.skip_blocks = in_pattern.skipBlocks; params.pattern.skip_blocks = in_args.pattern.skipBlocks;
// Set up the sample // Set up the sample
// Android's API only supports one at a time // Android's API only supports one at a time
@@ -243,16 +246,17 @@ SharedBufferBase::~SharedBufferBase() {
sample.encrypt_buffer = srcPtr; sample.encrypt_buffer = srcPtr;
sample.decrypt_buffer = destPtr; sample.decrypt_buffer = destPtr;
sample.decrypt_buffer_offset = 0; sample.decrypt_buffer_offset = 0;
sample.iv = in_iv; sample.iv = in_args.iv;
// Set up the subsamples // Set up the subsamples
// We abuse std::transform() here to also do some side-effects: Tallying the // We abuse std::transform() here to also do some side-effects: Tallying the
// total size of the sample and checking if any of the data is protected. // total size of the sample and checking if any of the data is protected.
size_t totalSize = 0; size_t totalSize = 0;
bool hasProtectedData = false; bool hasProtectedData = false;
sample.subsamples.reserve(in_subSamples.size()); sample.subsamples.reserve(in_args.subSamples.size());
std::transform( std::transform(
in_subSamples.data(), in_subSamples.data() + in_subSamples.size(), in_args.subSamples.data(),
in_args.subSamples.data() + in_args.subSamples.size(),
std::back_inserter(sample.subsamples), std::back_inserter(sample.subsamples),
[&](const SubSample& subSample) -> CdmDecryptionSubsample { [&](const SubSample& subSample) -> CdmDecryptionSubsample {
totalSize += totalSize +=
@@ -265,23 +269,22 @@ SharedBufferBase::~SharedBufferBase() {
sample.encrypt_buffer_length = totalSize; sample.encrypt_buffer_length = totalSize;
sample.decrypt_buffer_size = totalSize; sample.decrypt_buffer_size = totalSize;
if (in_mode == Mode::UNENCRYPTED && hasProtectedData) { if (in_args.mode == Mode::UNENCRYPTED && hasProtectedData) {
_aidl_return->detailedError = detailedError = "Protected ranges found in allegedly clear data.";
"Protected ranges found in allegedly clear data."; return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
} }
// Decrypt // Decrypt
std::string errorDetailMsg; std::string errorDetailMsg;
Status res = attemptDecrypt(params, hasProtectedData, &errorDetailMsg); Status res = attemptDecrypt(params, hasProtectedData, &errorDetailMsg);
if (res != Status::OK) { if (res != Status::OK) {
_aidl_return->detailedError = errorDetailMsg; detailedError = errorDetailMsg.data();
return toNdkScopedAStatus(res); return toNdkScopedAStatus(res, detailedError);
} }
_aidl_return->bytesWritten = totalSize; *_aidl_return = totalSize; // return bytes decrypted
_aidl_return->detailedError = errorDetailMsg; detailedError = errorDetailMsg.data();
return toNdkScopedAStatus(Status::OK); return toNdkScopedAStatus(Status::OK, detailedError);
} }
Status WVCryptoPlugin::attemptDecrypt(const CdmDecryptionParametersV16& params, Status WVCryptoPlugin::attemptDecrypt(const CdmDecryptionParametersV16& params,

View File

@@ -140,8 +140,6 @@ struct WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin,
const std::string& in_mime, const std::string& in_mime,
::aidl::android::hardware::drm::SecurityLevel in_level, ::aidl::android::hardware::drm::SecurityLevel in_level,
bool* _aidl_return) override; bool* _aidl_return) override;
::ndk::ScopedAStatus requiresSecureDecoderDefault(
const std::string& in_mime, bool* _aidl_return) override;
::ndk::ScopedAStatus restoreKeys( ::ndk::ScopedAStatus restoreKeys(
const std::vector<uint8_t>& in_sessionId, const std::vector<uint8_t>& in_sessionId,
const ::aidl::android::hardware::drm::KeySetId& in_keySetId) override; const ::aidl::android::hardware::drm::KeySetId& in_keySetId) override;

View File

@@ -118,13 +118,13 @@ KeyStatusType ConvertFromCdmKeyStatus(CdmKeyStatus keyStatus) {
case wvcdm::kKeyStatusExpired: case wvcdm::kKeyStatusExpired:
return KeyStatusType::EXPIRED; return KeyStatusType::EXPIRED;
case wvcdm::kKeyStatusOutputNotAllowed: case wvcdm::kKeyStatusOutputNotAllowed:
return KeyStatusType::OUTPUTNOTALLOWED; return KeyStatusType::OUTPUT_NOT_ALLOWED;
case wvcdm::kKeyStatusPending: case wvcdm::kKeyStatusPending:
case wvcdm::kKeyStatusUsableInFuture: case wvcdm::kKeyStatusUsableInFuture:
return KeyStatusType::USABLEINFUTURE; return KeyStatusType::USABLE_IN_FUTURE;
case wvcdm::kKeyStatusInternalError: case wvcdm::kKeyStatusInternalError:
default: default:
return KeyStatusType::INTERNALERROR; return KeyStatusType::INTERNAL_ERROR;
} }
} }
@@ -1762,28 +1762,18 @@ void WVDrmPlugin::sendSessionLostState(const vector<uint8_t>& in_sessionId) {
::ndk::ScopedAStatus WVDrmPlugin::requiresSecureDecoder( ::ndk::ScopedAStatus WVDrmPlugin::requiresSecureDecoder(
const std::string& in_mime, SecurityLevel in_level, bool* _aidl_return) { const std::string& in_mime, SecurityLevel in_level, bool* _aidl_return) {
if (!strncasecmp(in_mime.c_str(), "video/", 6)) { if (!strncasecmp(in_mime.c_str(), "video/", 6)) {
// Type is video, so check level to see if we require a secure decoder. if (in_level == SecurityLevel::DEFAULT) {
*_aidl_return = in_level == SecurityLevel::HW_SECURE_ALL || std::string level(mPropertySet.security_level());
in_level == SecurityLevel::HW_SECURE_DECODE; if (level == kResetSecurityLevel) {
} else { mCDM->QueryStatus(wvcdm::kLevelDefault, wvcdm::QUERY_KEY_SECURITY_LEVEL,
// Type is not video, so never require a secure decoder. &level);
*_aidl_return = false; }
} *_aidl_return = level == wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1;
return ::ndk::ScopedAStatus::ok(); } else {
} // Type is video, so check level to see if we require a secure decoder.
*_aidl_return = in_level == SecurityLevel::HW_SECURE_ALL ||
::ndk::ScopedAStatus WVDrmPlugin::requiresSecureDecoderDefault( in_level == SecurityLevel::HW_SECURE_DECODE;
const std::string& in_mime, bool* _aidl_return) {
if (!strncasecmp(in_mime.c_str(), "video/", 6)) {
// Type is video, so check level to see if we require a secure decoder.
std::string level(mPropertySet.security_level());
if (level == kResetSecurityLevel) {
mCDM->QueryStatus(wvcdm::kLevelDefault, wvcdm::QUERY_KEY_SECURITY_LEVEL,
&level);
} }
*_aidl_return = level == wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1;
} else { } else {
// Type is not video, so never require a secure decoder. // Type is not video, so never require a secure decoder.
*_aidl_return = false; *_aidl_return = false;