diff options
Diffstat (limited to 'media/libmedia')
-rw-r--r-- | media/libmedia/Android.mk | 1 | ||||
-rw-r--r-- | media/libmedia/ICrypto.cpp | 293 | ||||
-rw-r--r-- | media/libmedia/IMediaPlayerService.cpp | 15 |
3 files changed, 309 insertions, 0 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index c34e23b..a758850 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -17,6 +17,7 @@ LOCAL_SRC_FILES:= \ IAudioFlingerClient.cpp \ IAudioTrack.cpp \ IAudioRecord.cpp \ + ICrypto.cpp \ AudioRecord.cpp \ AudioSystem.cpp \ mediaplayer.cpp \ diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp new file mode 100644 index 0000000..827d7af --- /dev/null +++ b/media/libmedia/ICrypto.cpp @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2012 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_NDEBUG 0 +#define LOG_TAG "ICrypto" +#include <utils/Log.h> + +#include <binder/Parcel.h> +#include <media/ICrypto.h> +#include <media/stagefright/foundation/ADebug.h> + +namespace android { + +enum { + INITIALIZE = IBinder::FIRST_CALL_TRANSACTION, + TERMINATE, + SET_ENTITLEMENT_KEY, + SET_ECM, + DECRYPT_VIDEO, + DECRYPT_AUDIO, +}; + +struct BpCrypto : public BpInterface<ICrypto> { + BpCrypto(const sp<IBinder> &impl) + : BpInterface<ICrypto>(impl) { + } + + virtual status_t initialize() { + Parcel data, reply; + data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); + remote()->transact(INITIALIZE, data, &reply); + + return reply.readInt32(); + } + + virtual status_t terminate() { + Parcel data, reply; + data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); + remote()->transact(TERMINATE, data, &reply); + + return reply.readInt32(); + } + + virtual status_t setEntitlementKey( + const void *key, size_t keyLength) { + Parcel data, reply; + data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); + data.writeInt32(keyLength); + data.write(key, keyLength); + remote()->transact(SET_ENTITLEMENT_KEY, data, &reply); + + return reply.readInt32(); + } + + virtual status_t setEntitlementControlMessage( + const void *msg, size_t msgLength) { + Parcel data, reply; + data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); + data.writeInt32(msgLength); + data.write(msg, msgLength); + remote()->transact(SET_ECM, 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) { + 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.writeIntPtr((intptr_t)dstData); + data.writeInt32(dstDataOffset); + + remote()->transact(DECRYPT_VIDEO, data, &reply); + + return reply.readInt32(); + } + + virtual ssize_t decryptAudio( + const void *iv, size_t ivLength, + const void *srcData, size_t srcDataSize, + void *dstData, size_t dstDataSize) { + 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.writeInt32(dstDataSize); + + remote()->transact(DECRYPT_AUDIO, data, &reply); + + ssize_t res = reply.readInt32(); + + if (res <= 0) { + return res; + } + + reply.read(dstData, res); + + return res; + } + +private: + DISALLOW_EVIL_CONSTRUCTORS(BpCrypto); +}; + +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: + { + CHECK_INTERFACE(ICrypto, data, reply); + reply->writeInt32(initialize()); + + return OK; + } + + case TERMINATE: + { + CHECK_INTERFACE(ICrypto, data, reply); + reply->writeInt32(terminate()); + + return OK; + } + + case SET_ENTITLEMENT_KEY: + { + CHECK_INTERFACE(ICrypto, data, reply); + + size_t keyLength = data.readInt32(); + void *key = malloc(keyLength); + data.read(key, keyLength); + + reply->writeInt32(setEntitlementKey(key, keyLength)); + + free(key); + key = NULL; + + return OK; + } + + case SET_ECM: + { + 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; + + return OK; + } + + case DECRYPT_VIDEO: + { + CHECK_INTERFACE(ICrypto, data, reply); + + void *iv = NULL; + + int32_t ivLength = data.readInt32(); + if (ivLength >= 0) { + iv = malloc(ivLength); + data.read(iv, ivLength); + } + + size_t srcDataSize = data.readInt32(); + void *srcData = malloc(srcDataSize); + data.read(srcData, srcDataSize); + + void *dstData = (void *)data.readIntPtr(); + size_t dstDataOffset = data.readInt32(); + + reply->writeInt32( + decryptVideo( + iv, + ivLength < 0 ? 0 : ivLength, + srcData, + srcDataSize, + dstData, + dstDataOffset)); + + free(srcData); + srcData = NULL; + + if (iv != NULL) { + free(iv); + iv = NULL; + } + + return OK; + } + + case DECRYPT_AUDIO: + { + CHECK_INTERFACE(ICrypto, data, reply); + + void *iv = NULL; + + int32_t ivLength = data.readInt32(); + if (ivLength >= 0) { + iv = malloc(ivLength); + data.read(iv, ivLength); + } + + size_t srcDataSize = data.readInt32(); + void *srcData = malloc(srcDataSize); + data.read(srcData, srcDataSize); + + size_t dstDataSize = data.readInt32(); + void *dstData = malloc(dstDataSize); + + ssize_t res = + decryptAudio( + iv, + ivLength < 0 ? 0 : ivLength, + srcData, + srcDataSize, + dstData, + dstDataSize); + + reply->writeInt32(res); + + if (res > 0) { + reply->write(dstData, res); + } + + free(dstData); + dstData = NULL; + + free(srcData); + srcData = NULL; + + if (iv != NULL) { + free(iv); + iv = NULL; + } + + return OK; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +} // namespace android + diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index f5fccef..9120617 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -20,6 +20,7 @@ #include <binder/Parcel.h> #include <binder/IMemory.h> +#include <media/ICrypto.h> #include <media/IMediaPlayerService.h> #include <media/IMediaRecorder.h> #include <media/IOMX.h> @@ -36,6 +37,7 @@ enum { CREATE_MEDIA_RECORDER, CREATE_METADATA_RETRIEVER, GET_OMX, + MAKE_CRYPTO, ADD_BATTERY_DATA, PULL_BATTERY_DATA }; @@ -111,6 +113,13 @@ public: return interface_cast<IOMX>(reply.readStrongBinder()); } + virtual sp<ICrypto> makeCrypto() { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + remote()->transact(MAKE_CRYPTO, data, &reply); + return interface_cast<ICrypto>(reply.readStrongBinder()); + } + virtual void addBatteryData(uint32_t params) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); @@ -191,6 +200,12 @@ status_t BnMediaPlayerService::onTransact( reply->writeStrongBinder(omx->asBinder()); return NO_ERROR; } break; + case MAKE_CRYPTO: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + sp<ICrypto> crypto = makeCrypto(); + reply->writeStrongBinder(crypto->asBinder()); + return NO_ERROR; + } break; case ADD_BATTERY_DATA: { CHECK_INTERFACE(IMediaPlayerService, data, reply); uint32_t params = data.readInt32(); |