Files
hardware_interfaces/drm/1.0/default/CryptoPlugin.cpp
Rahul Frias abd4e11c9d Correct reporting of errors in MediaCrypto
Legacy error codes need to be converted into new Status values before
being reported. Decryption errors (that were negative) were changed to
absolute values. This caused their translation to new Status values to
fail.

b/35634335

Test: Verified with GtsExoPlayerTestCases. Some failures, but those
      are unrelated to this CL and will be addressed separately.

Change-Id: I995cac33cb2725d02b0f1a3922e522ce07a9d1be
2017-02-28 20:56:13 +00:00

160 lines
5.8 KiB
C++

/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "android.hardware.drm@1.0-impl"
#include "CryptoPlugin.h"
#include "TypeConvert.h"
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidlmemory/mapping.h>
#include <media/stagefright/foundation/AString.h>
#include <utils/Log.h>
using android::hardware::hidl_memory;
using android::hidl::memory::V1_0::IMemory;
namespace android {
namespace hardware {
namespace drm {
namespace V1_0 {
namespace implementation {
// Methods from ::android::hardware::drm::V1_0::ICryptoPlugin follow
Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
const hidl_string& mime) {
return mLegacyPlugin->requiresSecureDecoderComponent(mime);
}
Return<void> CryptoPlugin::notifyResolution(uint32_t width,
uint32_t height) {
mLegacyPlugin->notifyResolution(width, height);
return Void();
}
Return<Status> CryptoPlugin::setMediaDrmSession(
const hidl_vec<uint8_t>& sessionId) {
return toStatus(mLegacyPlugin->setMediaDrmSession(toVector(sessionId)));
}
Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base,
uint32_t bufferId) {
mSharedBufferMap[bufferId] = mapMemory(base);
return Void();
}
Return<void> CryptoPlugin::decrypt(bool secure,
const hidl_array<uint8_t, 16>& keyId,
const hidl_array<uint8_t, 16>& iv, Mode mode,
const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
const SharedBuffer& source, uint64_t offset,
const DestinationBuffer& destination,
decrypt_cb _hidl_cb) {
if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set");
return Void();
}
if (destination.type == BufferType::SHARED_MEMORY) {
const SharedBuffer& dest = destination.nonsecureMemory;
if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination decrypt buffer base not set");
return Void();
}
}
android::CryptoPlugin::Mode legacyMode;
switch(mode) {
case Mode::UNENCRYPTED:
legacyMode = android::CryptoPlugin::kMode_Unencrypted;
break;
case Mode::AES_CTR:
legacyMode = android::CryptoPlugin::kMode_AES_CTR;
break;
case Mode::AES_CBC_CTS:
legacyMode = android::CryptoPlugin::kMode_AES_WV;
break;
case Mode::AES_CBC:
legacyMode = android::CryptoPlugin::kMode_AES_CBC;
break;
}
android::CryptoPlugin::Pattern legacyPattern;
legacyPattern.mEncryptBlocks = pattern.encryptBlocks;
legacyPattern.mSkipBlocks = pattern.skipBlocks;
android::CryptoPlugin::SubSample *legacySubSamples =
new android::CryptoPlugin::SubSample[subSamples.size()];
for (size_t i = 0; i < subSamples.size(); i++) {
legacySubSamples[i].mNumBytesOfClearData
= subSamples[i].numBytesOfClearData;
legacySubSamples[i].mNumBytesOfEncryptedData
= subSamples[i].numBytesOfEncryptedData;
}
AString detailMessage;
sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
if (source.offset + offset + source.size > sourceBase->getSize()) {
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
return Void();
}
uint8_t *base = static_cast<uint8_t *>
(static_cast<void *>(sourceBase->getPointer()));
void *srcPtr = static_cast<void *>(base + source.offset + offset);
void *destPtr = NULL;
if (destination.type == BufferType::SHARED_MEMORY) {
const SharedBuffer& destBuffer = destination.nonsecureMemory;
sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
return Void();
}
destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
} else if (destination.type == BufferType::NATIVE_HANDLE) {
native_handle_t *handle = const_cast<native_handle_t *>(
destination.secureMemory.getNativeHandle());
destPtr = static_cast<void *>(handle);
}
ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
legacyMode, legacyPattern, srcPtr, legacySubSamples,
subSamples.size(), destPtr, &detailMessage);
delete[] legacySubSamples;
uint32_t status;
uint32_t bytesWritten;
if (result >= 0) {
status = android::OK;
bytesWritten = result;
} else {
status = result;
bytesWritten = 0;
}
_hidl_cb(toStatus(status), bytesWritten, detailMessage.c_str());
return Void();
}
} // namespace implementation
} // namespace V1_0
} // namespace drm
} // namespace hardware
} // namespace android