summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2012-04-03 14:19:20 -0700
committerAndreas Huber <andih@google.com>2012-04-03 14:19:20 -0700
commit1bd139a2a68690e80398b70b27ca59550fea0e65 (patch)
treee3be78f22aa021c4e372409128775c2093d46dae
parentd22da88fd555f1262357c7dcdeface8445e3a012 (diff)
downloadframeworks_av-1bd139a2a68690e80398b70b27ca59550fea0e65.zip
frameworks_av-1bd139a2a68690e80398b70b27ca59550fea0e65.tar.gz
frameworks_av-1bd139a2a68690e80398b70b27ca59550fea0e65.tar.bz2
New Crypto services talking to the new crypto "HAL".
Change-Id: I69ed31e7a8b4d69d1209d2d516f94d258f072566 related-to-bug: 6275919
-rw-r--r--cmds/stagefright/SimplePlayer.cpp5
-rw-r--r--cmds/stagefright/codec.cpp69
-rw-r--r--include/media/ICrypto.h33
-rw-r--r--include/media/stagefright/MediaCodec.h2
-rw-r--r--media/libmedia/ICrypto.cpp269
-rw-r--r--media/libmediaplayerservice/Crypto.cpp133
-rw-r--r--media/libmediaplayerservice/Crypto.h44
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp8
-rw-r--r--media/libstagefright/MediaCodec.cpp159
9 files changed, 412 insertions, 310 deletions
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index 0cfeb3e..7636906 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -22,6 +22,7 @@
#include <gui/SurfaceTextureClient.h>
#include <media/AudioTrack.h>
+#include <media/ICrypto.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -318,7 +319,9 @@ status_t SimplePlayer::onPrepare() {
CHECK(state->mCodec != NULL);
err = state->mCodec->configure(
- format, mNativeWindow->getSurfaceTextureClient(),
+ format,
+ mNativeWindow->getSurfaceTextureClient(),
+ NULL /* crypto */,
0 /* flags */);
CHECK_EQ(err, (status_t)OK);
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index cf2909e..5cbfbfe 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -20,8 +20,10 @@
#include "SimplePlayer.h"
+#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
-
+#include <media/ICrypto.h>
+#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -59,6 +61,33 @@ struct CodecState {
bool mIsAudio;
};
+static sp<ICrypto> makeCrypto(
+ const uint8_t uuid[16], const void *data, size_t size) {
+ sp<IServiceManager> sm = defaultServiceManager();
+
+ sp<IBinder> binder =
+ sm->getService(String16("media.player"));
+
+ sp<IMediaPlayerService> service =
+ interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service != NULL);
+
+ sp<ICrypto> crypto = service->makeCrypto();
+
+ if (crypto == NULL || crypto->initCheck() != OK) {
+ return NULL;
+ }
+
+ status_t err = crypto->createPlugin(uuid, data, size);
+
+ if (err != OK) {
+ return NULL;
+ }
+
+ return crypto;
+}
+
} // namespace android
static int decode(
@@ -78,6 +107,8 @@ static int decode(
return 1;
}
+ sp<ICrypto> crypto;
+
KeyedVector<size_t, CodecState> stateByTrack;
bool haveAudio = false;
@@ -113,7 +144,38 @@ static int decode(
state->mNumBuffersDecoded = 0;
state->mIsAudio = isAudio;
- if (decryptInputBuffers && !isAudio) {
+ if (decryptInputBuffers && crypto == NULL) {
+ sp<ABuffer> emm;
+ CHECK(format->findBuffer("emm", &emm));
+
+ sp<ABuffer> ecm;
+ CHECK(format->findBuffer("ecm", &ecm));
+
+ struct WVOpaqueInitData {
+ uint8_t mEMM[16];
+ uint8_t mECM[32];
+
+ } opaque;
+
+ CHECK_EQ(emm->size(), sizeof(opaque.mEMM));
+ memcpy(opaque.mEMM, emm->data(), emm->size());
+
+ CHECK_EQ(ecm->size(), 80u);
+ // bytes 16..47 of the original ecm stream data.
+ memcpy(opaque.mECM, ecm->data() + 16, 32);
+
+ static const uint8_t kUUIDWidevine[16] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+ };
+
+ crypto = makeCrypto(kUUIDWidevine, &opaque, sizeof(opaque));
+ CHECK(crypto != NULL);
+ CHECK_EQ(crypto->initCheck(), (status_t)OK);
+ }
+
+ if (decryptInputBuffers
+ && crypto->requiresSecureDecoderComponent(mime.c_str())) {
static const MediaCodecList *list = MediaCodecList::getInstance();
ssize_t index =
@@ -137,7 +199,8 @@ static int decode(
err = state->mCodec->configure(
format, isVideo ? surface : NULL,
- decryptInputBuffers ? MediaCodec::CONFIGURE_FLAG_SECURE : 0);
+ crypto,
+ 0 /* flags */);
CHECK_EQ(err, (status_t)OK);
diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h
index 916abe0..376c326 100644
--- a/include/media/ICrypto.h
+++ b/include/media/ICrypto.h
@@ -16,6 +16,7 @@
#include <binder/IInterface.h>
#include <media/stagefright/foundation/ABase.h>
+#include <media/hardware/CryptoAPI.h>
#ifndef ANDROID_ICRYPTO_H_
@@ -26,26 +27,26 @@ namespace android {
struct ICrypto : public IInterface {
DECLARE_META_INTERFACE(Crypto);
- virtual status_t initialize() = 0;
- virtual status_t terminate() = 0;
+ virtual status_t initCheck() const = 0;
- virtual status_t setEntitlementKey(
- const void *key, size_t keyLength) = 0;
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const = 0;
- virtual status_t setEntitlementControlMessage(
- const void *msg, size_t msgLength) = 0;
+ virtual status_t createPlugin(
+ const uint8_t uuid[16], const void *data, size_t size) = 0;
- // "dstData" is in media_server's address space (but inaccessible).
- virtual ssize_t decryptVideo(
- const void *iv, size_t ivLength,
- const void *srcData, size_t srcDataSize,
- void *dstData, size_t dstDataOffset) = 0;
+ virtual status_t destroyPlugin() = 0;
- // "dstData" is in the calling process' address space.
- virtual ssize_t decryptAudio(
- const void *iv, size_t ivLength,
- const void *srcData, size_t srcDataSize,
- void *dstData, size_t dstDataSize) = 0;
+ virtual bool requiresSecureDecoderComponent(
+ const char *mime) const = 0;
+
+ virtual status_t decrypt(
+ bool secure,
+ const uint8_t key[16],
+ const uint8_t iv[16],
+ CryptoPlugin::Mode mode,
+ const void *srcPtr,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+ void *dstPtr) = 0;
private:
DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 0fc88e1..0b0d511 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -34,7 +34,6 @@ struct SurfaceTextureClient;
struct MediaCodec : public AHandler {
enum ConfigureFlags {
CONFIGURE_FLAG_ENCODE = 1,
- CONFIGURE_FLAG_SECURE = 2,
};
enum BufferFlags {
@@ -53,6 +52,7 @@ struct MediaCodec : public AHandler {
status_t configure(
const sp<AMessage> &format,
const sp<SurfaceTextureClient> &nativeWindow,
+ const sp<ICrypto> &crypto,
uint32_t flags);
status_t start();
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index 827d7af..1fe6bed 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -25,12 +25,12 @@
namespace android {
enum {
- INITIALIZE = IBinder::FIRST_CALL_TRANSACTION,
- TERMINATE,
- SET_ENTITLEMENT_KEY,
- SET_ECM,
- DECRYPT_VIDEO,
- DECRYPT_AUDIO,
+ INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
+ IS_CRYPTO_SUPPORTED,
+ CREATE_PLUGIN,
+ DESTROY_PLUGIN,
+ REQUIRES_SECURE_COMPONENT,
+ DECRYPT,
};
struct BpCrypto : public BpInterface<ICrypto> {
@@ -38,104 +38,97 @@ struct BpCrypto : public BpInterface<ICrypto> {
: BpInterface<ICrypto>(impl) {
}
- virtual status_t initialize() {
+ virtual status_t initCheck() const {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- remote()->transact(INITIALIZE, data, &reply);
+ remote()->transact(INIT_CHECK, data, &reply);
return reply.readInt32();
}
- virtual status_t terminate() {
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- remote()->transact(TERMINATE, data, &reply);
+ data.write(uuid, 16);
+ remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
- return reply.readInt32();
+ return reply.readInt32() != 0;
}
- virtual status_t setEntitlementKey(
- const void *key, size_t keyLength) {
+ virtual status_t createPlugin(
+ const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeInt32(keyLength);
- data.write(key, keyLength);
- remote()->transact(SET_ENTITLEMENT_KEY, data, &reply);
+ data.write(uuid, 16);
+ data.writeInt32(opaqueSize);
+ data.write(opaqueData, opaqueSize);
+ remote()->transact(CREATE_PLUGIN, data, &reply);
return reply.readInt32();
}
- virtual status_t setEntitlementControlMessage(
- const void *msg, size_t msgLength) {
+ virtual status_t destroyPlugin() {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeInt32(msgLength);
- data.write(msg, msgLength);
- remote()->transact(SET_ECM, data, &reply);
+ remote()->transact(DESTROY_PLUGIN, data, &reply);
return reply.readInt32();
}
- virtual ssize_t decryptVideo(
- const void *iv, size_t ivLength,
- const void *srcData, size_t srcDataSize,
- void *dstData, size_t dstDataOffset) {
+ virtual bool requiresSecureDecoderComponent(
+ const char *mime) const {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- if (iv == NULL) {
- if (ivLength > 0) {
- return -EINVAL;
- }
-
- data.writeInt32(-1);
- } else {
- data.writeInt32(ivLength);
- data.write(iv, ivLength);
- }
-
- data.writeInt32(srcDataSize);
- data.write(srcData, srcDataSize);
+ data.writeCString(mime);
+ remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
- data.writeIntPtr((intptr_t)dstData);
- data.writeInt32(dstDataOffset);
-
- remote()->transact(DECRYPT_VIDEO, data, &reply);
-
- return reply.readInt32();
+ return reply.readInt32() != 0;
}
- virtual ssize_t decryptAudio(
- const void *iv, size_t ivLength,
- const void *srcData, size_t srcDataSize,
- void *dstData, size_t dstDataSize) {
+ virtual status_t decrypt(
+ bool secure,
+ const uint8_t key[16],
+ const uint8_t iv[16],
+ CryptoPlugin::Mode mode,
+ const void *srcPtr,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+ void *dstPtr) {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- if (iv == NULL) {
- if (ivLength > 0) {
- return -EINVAL;
- }
-
- data.writeInt32(-1);
- } else {
- data.writeInt32(ivLength);
- data.write(iv, ivLength);
+ data.writeInt32(secure);
+ data.writeInt32(mode);
+ data.write(key, 16);
+ data.write(iv, 16);
+
+ size_t totalSize = 0;
+ for (size_t i = 0; i < numSubSamples; ++i) {
+ totalSize += subSamples[i].mNumBytesOfEncryptedData;
+ totalSize += subSamples[i].mNumBytesOfClearData;
}
- data.writeInt32(srcDataSize);
- data.write(srcData, srcDataSize);
- data.writeInt32(dstDataSize);
+ data.writeInt32(totalSize);
+ data.write(srcPtr, totalSize);
+
+ data.writeInt32(numSubSamples);
+ data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
+
+ if (secure) {
+ data.writeIntPtr((intptr_t)dstPtr);
+ }
- remote()->transact(DECRYPT_AUDIO, data, &reply);
+ remote()->transact(DECRYPT, data, &reply);
- ssize_t res = reply.readInt32();
+ status_t result = reply.readInt32();
- if (res <= 0) {
- return res;
+ if (result != OK) {
+ return result;
}
- reply.read(dstData, res);
+ if (!secure) {
+ reply.read(dstPtr, totalSize);
+ }
- return res;
+ return OK;
}
private:
@@ -149,138 +142,120 @@ IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
status_t BnCrypto::onTransact(
uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
switch (code) {
- case INITIALIZE:
+ case INIT_CHECK:
{
CHECK_INTERFACE(ICrypto, data, reply);
- reply->writeInt32(initialize());
+ reply->writeInt32(initCheck());
return OK;
}
- case TERMINATE:
+ case IS_CRYPTO_SUPPORTED:
{
CHECK_INTERFACE(ICrypto, data, reply);
- reply->writeInt32(terminate());
+ uint8_t uuid[16];
+ data.read(uuid, sizeof(uuid));
+ reply->writeInt32(isCryptoSchemeSupported(uuid));
return OK;
}
- case SET_ENTITLEMENT_KEY:
+ case CREATE_PLUGIN:
{
CHECK_INTERFACE(ICrypto, data, reply);
- size_t keyLength = data.readInt32();
- void *key = malloc(keyLength);
- data.read(key, keyLength);
+ uint8_t uuid[16];
+ data.read(uuid, sizeof(uuid));
+
+ size_t opaqueSize = data.readInt32();
+ void *opaqueData = malloc(opaqueSize);
+ data.read(opaqueData, opaqueSize);
- reply->writeInt32(setEntitlementKey(key, keyLength));
+ reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
- free(key);
- key = NULL;
+ free(opaqueData);
+ opaqueData = NULL;
return OK;
}
- case SET_ECM:
+ case DESTROY_PLUGIN:
{
CHECK_INTERFACE(ICrypto, data, reply);
-
- size_t msgLength = data.readInt32();
- void *msg = malloc(msgLength);
- data.read(msg, msgLength);
-
- reply->writeInt32(setEntitlementControlMessage(msg, msgLength));
-
- free(msg);
- msg = NULL;
+ reply->writeInt32(destroyPlugin());
return OK;
}
- case DECRYPT_VIDEO:
+ case REQUIRES_SECURE_COMPONENT:
{
CHECK_INTERFACE(ICrypto, data, reply);
- void *iv = NULL;
+ const char *mime = data.readCString();
+ reply->writeInt32(requiresSecureDecoderComponent(mime));
- int32_t ivLength = data.readInt32();
- if (ivLength >= 0) {
- iv = malloc(ivLength);
- data.read(iv, ivLength);
- }
+ return OK;
+ }
- size_t srcDataSize = data.readInt32();
- void *srcData = malloc(srcDataSize);
- data.read(srcData, srcDataSize);
+ case DECRYPT:
+ {
+ CHECK_INTERFACE(ICrypto, data, reply);
- void *dstData = (void *)data.readIntPtr();
- size_t dstDataOffset = data.readInt32();
+ bool secure = data.readInt32() != 0;
+ CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
- reply->writeInt32(
- decryptVideo(
- iv,
- ivLength < 0 ? 0 : ivLength,
- srcData,
- srcDataSize,
- dstData,
- dstDataOffset));
+ uint8_t key[16];
+ data.read(key, sizeof(key));
- free(srcData);
- srcData = NULL;
+ uint8_t iv[16];
+ data.read(iv, sizeof(iv));
- if (iv != NULL) {
- free(iv);
- iv = NULL;
- }
+ size_t totalSize = data.readInt32();
+ void *srcData = malloc(totalSize);
+ data.read(srcData, totalSize);
- return OK;
- }
+ int32_t numSubSamples = data.readInt32();
- case DECRYPT_AUDIO:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
+ CryptoPlugin::SubSample *subSamples =
+ new CryptoPlugin::SubSample[numSubSamples];
- void *iv = NULL;
+ data.read(
+ subSamples,
+ sizeof(CryptoPlugin::SubSample) * numSubSamples);
- int32_t ivLength = data.readInt32();
- if (ivLength >= 0) {
- iv = malloc(ivLength);
- data.read(iv, ivLength);
+ void *dstPtr;
+ if (secure) {
+ dstPtr = (void *)data.readIntPtr();
+ } else {
+ dstPtr = malloc(totalSize);
}
- size_t srcDataSize = data.readInt32();
- void *srcData = malloc(srcDataSize);
- data.read(srcData, srcDataSize);
-
- size_t dstDataSize = data.readInt32();
- void *dstData = malloc(dstDataSize);
+ status_t err = decrypt(
+ secure,
+ key,
+ iv,
+ mode,
+ srcData,
+ subSamples, numSubSamples,
+ dstPtr);
- ssize_t res =
- decryptAudio(
- iv,
- ivLength < 0 ? 0 : ivLength,
- srcData,
- srcDataSize,
- dstData,
- dstDataSize);
+ reply->writeInt32(err);
- reply->writeInt32(res);
+ if (!secure) {
+ if (err == OK) {
+ reply->write(dstPtr, totalSize);
+ }
- if (res > 0) {
- reply->write(dstData, res);
+ free(dstPtr);
+ dstPtr = NULL;
}
- free(dstData);
- dstData = NULL;
+ delete[] subSamples;
+ subSamples = NULL;
free(srcData);
srcData = NULL;
- if (iv != NULL) {
- free(iv);
- iv = NULL;
- }
-
return OK;
}
diff --git a/media/libmediaplayerservice/Crypto.cpp b/media/libmediaplayerservice/Crypto.cpp
index e02035f..4491f2b 100644
--- a/media/libmediaplayerservice/Crypto.cpp
+++ b/media/libmediaplayerservice/Crypto.cpp
@@ -20,46 +20,137 @@
#include "Crypto.h"
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaErrors.h>
+#include <dlfcn.h>
+
namespace android {
-Crypto::Crypto() {
+Crypto::Crypto()
+ : mInitCheck(NO_INIT),
+ mLibHandle(NULL),
+ mPlugin(NULL) {
+ mInitCheck = init();
}
Crypto::~Crypto() {
+ delete mPlugin;
+ mPlugin = NULL;
+
+ delete mFactory;
+ mFactory = NULL;
+
+ if (mLibHandle != NULL) {
+ dlclose(mLibHandle);
+ mLibHandle = NULL;
+ }
}
-status_t Crypto::initialize() {
- return ERROR_UNSUPPORTED;
+status_t Crypto::initCheck() const {
+ return mInitCheck;
}
-status_t Crypto::terminate() {
- return ERROR_UNSUPPORTED;
+status_t Crypto::init() {
+ mLibHandle = dlopen("libdrmdecrypt.so", RTLD_NOW);
+
+ if (mLibHandle == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ typedef CryptoFactory *(*CreateCryptoFactoryFunc)();
+ CreateCryptoFactoryFunc createCryptoFactory =
+ (CreateCryptoFactoryFunc)dlsym(mLibHandle, "createCryptoFactory");
+
+ if (createCryptoFactory == NULL
+ || ((mFactory = createCryptoFactory()) == NULL)) {
+ dlclose(mLibHandle);
+ mLibHandle = NULL;
+
+ return ERROR_UNSUPPORTED;
+ }
+
+ return OK;
}
-status_t Crypto::setEntitlementKey(
- const void *key, size_t keyLength) {
- return ERROR_UNSUPPORTED;
+bool Crypto::isCryptoSchemeSupported(const uint8_t uuid[16]) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return false;
+ }
+
+ return mFactory->isCryptoSchemeSupported(uuid);
}
-status_t Crypto::setEntitlementControlMessage(
- const void *msg, size_t msgLength) {
- return ERROR_UNSUPPORTED;
+status_t Crypto::createPlugin(
+ const uint8_t uuid[16], const void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin != NULL) {
+ return -EINVAL;
+ }
+
+ return mFactory->createPlugin(uuid, data, size, &mPlugin);
}
-ssize_t Crypto::decryptVideo(
- const void *iv, size_t ivLength,
- const void *srcData, size_t srcDataSize,
- void *dstData, size_t dstDataOffset) {
- return ERROR_UNSUPPORTED;
+status_t Crypto::destroyPlugin() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ delete mPlugin;
+ mPlugin = NULL;
+
+ return OK;
+}
+
+bool Crypto::requiresSecureDecoderComponent(const char *mime) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->requiresSecureDecoderComponent(mime);
}
-ssize_t Crypto::decryptAudio(
- const void *iv, size_t ivLength,
- const void *srcData, size_t srcDataSize,
- void *dstData, size_t dstDataSize) {
- return ERROR_UNSUPPORTED;
+status_t Crypto::decrypt(
+ bool secure,
+ const uint8_t key[16],
+ const uint8_t iv[16],
+ CryptoPlugin::Mode mode,
+ const void *srcPtr,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+ void *dstPtr) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->decrypt(
+ secure, key, iv, mode, srcPtr, subSamples, numSubSamples, dstPtr);
}
} // namespace android
diff --git a/media/libmediaplayerservice/Crypto.h b/media/libmediaplayerservice/Crypto.h
index 9855496..74de2b5 100644
--- a/media/libmediaplayerservice/Crypto.h
+++ b/media/libmediaplayerservice/Crypto.h
@@ -23,32 +23,44 @@
namespace android {
+struct CryptoFactory;
+struct CryptoPlugin;
+
struct Crypto : public BnCrypto {
Crypto();
+ virtual ~Crypto();
- virtual status_t initialize();
- virtual status_t terminate();
+ virtual status_t initCheck() const;
- virtual status_t setEntitlementKey(
- const void *key, size_t keyLength);
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const;
- virtual status_t setEntitlementControlMessage(
- const void *msg, size_t msgLength);
+ virtual status_t createPlugin(
+ const uint8_t uuid[16], const void *data, size_t size);
- virtual ssize_t decryptVideo(
- const void *iv, size_t ivLength,
- const void *srcData, size_t srcDataSize,
- void *dstData, size_t dstDataOffset);
+ virtual status_t destroyPlugin();
- virtual ssize_t decryptAudio(
- const void *iv, size_t ivLength,
- const void *srcData, size_t srcDataSize,
- void *dstData, size_t dstDataSize);
+ virtual bool requiresSecureDecoderComponent(
+ const char *mime) const;
-protected:
- virtual ~Crypto();
+ virtual status_t decrypt(
+ bool secure,
+ const uint8_t key[16],
+ const uint8_t iv[16],
+ CryptoPlugin::Mode mode,
+ const void *srcPtr,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+ void *dstPtr);
private:
+ mutable Mutex mLock;
+
+ status_t mInitCheck;
+ void *mLibHandle;
+ CryptoFactory *mFactory;
+ CryptoPlugin *mPlugin;
+
+ status_t init();
+
DISALLOW_EVIL_CONSTRUCTORS(Crypto);
};
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index a977337..7c3fb0d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -294,13 +294,7 @@ sp<IOMX> MediaPlayerService::getOMX() {
}
sp<ICrypto> MediaPlayerService::makeCrypto() {
- Mutex::Autolock autoLock(mLock);
-
- if (mCrypto == NULL) {
- mCrypto = new Crypto;
- }
-
- return mCrypto;
+ return new Crypto;
}
status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 42b5c7e..ced8368 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -22,10 +22,8 @@
#include "include/SoftwareRenderer.h"
-#include <binder/IServiceManager.h>
#include <gui/SurfaceTextureClient.h>
#include <media/ICrypto.h>
-#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -134,6 +132,7 @@ status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
status_t MediaCodec::configure(
const sp<AMessage> &format,
const sp<SurfaceTextureClient> &nativeWindow,
+ const sp<ICrypto> &crypto,
uint32_t flags) {
sp<AMessage> msg = new AMessage(kWhatConfigure, id());
@@ -141,13 +140,13 @@ status_t MediaCodec::configure(
msg->setInt32("flags", flags);
if (nativeWindow != NULL) {
- if (!(mFlags & kFlagIsSoftwareCodec)) {
- msg->setObject(
- "native-window",
- new NativeWindowWrapper(nativeWindow));
- } else {
- mNativeWindow = nativeWindow;
- }
+ msg->setObject(
+ "native-window",
+ new NativeWindowWrapper(nativeWindow));
+ }
+
+ if (crypto != NULL) {
+ msg->setPointer("crypto", crypto.get());
}
sp<AMessage> response;
@@ -490,6 +489,12 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
mFlags &= ~kFlagIsSoftwareCodec;
}
+ if (componentName.endsWith(".secure")) {
+ mFlags |= kFlagIsSecure;
+ } else {
+ mFlags &= ~kFlagIsSecure;
+ }
+
(new AMessage)->postReply(mReplyID);
break;
}
@@ -532,8 +537,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
info.mOwnedByClient = false;
CHECK(msg->findBuffer(name.c_str(), &info.mData));
- if (portIndex == kPortIndexInput
- && (mFlags & kFlagIsSecure)) {
+ if (portIndex == kPortIndexInput && mCrypto != NULL) {
info.mEncryptedData =
new ABuffer(info.mData->capacity());
}
@@ -743,8 +747,23 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
if (obj != NULL) {
format->setObject("native-window", obj);
+
+ if (mFlags & kFlagIsSoftwareCodec) {
+ mNativeWindow =
+ static_cast<NativeWindowWrapper *>(obj.get())
+ ->getSurfaceTextureClient();
+ }
+ } else {
+ mNativeWindow.clear();
+ }
+
+ void *crypto;
+ if (!msg->findPointer("crypto", &crypto)) {
+ crypto = NULL;
}
+ mCrypto = static_cast<ICrypto *>(crypto);
+
uint32_t flags;
CHECK(msg->findInt32("flags", (int32_t *)&flags));
@@ -752,59 +771,6 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
format->setInt32("encoder", true);
}
- if (flags & CONFIGURE_FLAG_SECURE) {
- mFlags |= kFlagIsSecure;
-
- sp<IServiceManager> sm = defaultServiceManager();
-
- sp<IBinder> binder =
- sm->getService(String16("media.player"));
-
- sp<IMediaPlayerService> service =
- interface_cast<IMediaPlayerService>(binder);
-
- CHECK(service != NULL);
-
- mCrypto = service->makeCrypto();
-
- status_t err = mCrypto->initialize();
-
- if (err == OK) {
- sp<ABuffer> emm;
- if (format->findBuffer("emm", &emm)) {
- err = mCrypto->setEntitlementKey(
- emm->data(), emm->size());
- }
- }
-
- if (err == OK) {
- sp<ABuffer> ecm;
- if (format->findBuffer("ecm", &ecm)) {
- CHECK_EQ(ecm->size(), 80u);
-
- // bytes 16..47 of the original ecm stream data.
- err = mCrypto->setEntitlementControlMessage(
- ecm->data() + 16, 32);
- }
- }
-
- if (err != OK) {
- ALOGE("failed to instantiate crypto service.");
-
- mCrypto.clear();
-
- setState(INITIALIZED);
-
- sp<AMessage> response = new AMessage;
- response->setInt32("err", UNKNOWN_ERROR);
-
- response->postReply(mReplyID);
- break;
- }
- } else {
- mFlags &= ~kFlagIsSecure;
- }
-
mCodec->initiateConfigureComponent(format);
break;
}
@@ -1047,8 +1013,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
const BufferInfo &info = srcBuffers.itemAt(i);
dstBuffers->push_back(
- (portIndex == kPortIndexInput
- && (mFlags & kFlagIsSecure))
+ (portIndex == kPortIndexInput && mCrypto != NULL)
? info.mEncryptedData : info.mData);
}
@@ -1107,11 +1072,7 @@ void MediaCodec::setState(State newState) {
delete mSoftRenderer;
mSoftRenderer = NULL;
- if (mCrypto != NULL) {
- mCrypto->terminate();
- mCrypto.clear();
- }
-
+ mCrypto.clear();
mNativeWindow.clear();
mOutputFormat.clear();
@@ -1221,39 +1182,41 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
info->mData->meta()->setInt32("csd", true);
}
- if (mFlags & kFlagIsSecure) {
- uint8_t iv[16];
- memset(iv, 0, sizeof(iv));
-
- ssize_t outLength;
-
- if (mFlags & kFlagIsSoftwareCodec) {
- outLength = mCrypto->decryptAudio(
- (flags & BUFFER_FLAG_ENCRYPTED) ? iv : NULL,
- (flags & BUFFER_FLAG_ENCRYPTED) ? sizeof(iv) : 0,
- info->mEncryptedData->base() + offset,
- size,
- info->mData->base(),
- info->mData->capacity());
- } else {
- outLength = mCrypto->decryptVideo(
- (flags & BUFFER_FLAG_ENCRYPTED) ? iv : NULL,
- (flags & BUFFER_FLAG_ENCRYPTED) ? sizeof(iv) : 0,
- info->mEncryptedData->base() + offset,
- size,
- info->mData->base(),
- 0 /* offset */);
+ if (mCrypto != NULL) {
+ if (size > info->mEncryptedData->capacity()) {
+ return -ERANGE;
}
- if (outLength < 0) {
- return outLength;
+ uint8_t key[16];
+ uint8_t iv[16];
+
+ CryptoPlugin::Mode mode;
+ CryptoPlugin::SubSample ss;
+ if (flags & BUFFER_FLAG_ENCRYPTED) {
+ mode = CryptoPlugin::kMode_AES_WV;
+ ss.mNumBytesOfClearData = 0;
+ ss.mNumBytesOfEncryptedData = size;
+ } else {
+ mode = CryptoPlugin::kMode_Unencrypted;
+ ss.mNumBytesOfClearData = size;
+ ss.mNumBytesOfEncryptedData = 0;
}
- if ((size_t)outLength > info->mEncryptedData->capacity()) {
- return -ERANGE;
+ status_t err = mCrypto->decrypt(
+ (mFlags & kFlagIsSecure) != 0,
+ key,
+ iv,
+ mode,
+ info->mEncryptedData->base() + offset,
+ &ss,
+ 1 /* numSubSamples */,
+ info->mData->base());
+
+ if (err != OK) {
+ return err;
}
- info->mData->setRange(0, outLength);
+ info->mData->setRange(0, size);
} else if (flags & BUFFER_FLAG_ENCRYPTED) {
return -EINVAL;
}