diff options
author | Andreas Huber <andih@google.com> | 2012-04-03 14:19:20 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2012-04-03 14:19:20 -0700 |
commit | 1bd139a2a68690e80398b70b27ca59550fea0e65 (patch) | |
tree | e3be78f22aa021c4e372409128775c2093d46dae | |
parent | d22da88fd555f1262357c7dcdeface8445e3a012 (diff) | |
download | frameworks_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.cpp | 5 | ||||
-rw-r--r-- | cmds/stagefright/codec.cpp | 69 | ||||
-rw-r--r-- | include/media/ICrypto.h | 33 | ||||
-rw-r--r-- | include/media/stagefright/MediaCodec.h | 2 | ||||
-rw-r--r-- | media/libmedia/ICrypto.cpp | 269 | ||||
-rw-r--r-- | media/libmediaplayerservice/Crypto.cpp | 133 | ||||
-rw-r--r-- | media/libmediaplayerservice/Crypto.h | 44 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 8 | ||||
-rw-r--r-- | media/libstagefright/MediaCodec.cpp | 159 |
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; } |