android::status_t DrmFactory::createDrmPlugin( const uint8_t uuid[16], android::DrmPlugin** plugin) { if (!isCryptoSchemeSupported(uuid)) { *plugin = NULL; return android::BAD_VALUE; } *plugin = new DrmPlugin(SessionLibrary::get()); return android::OK; }
android::status_t CryptoFactory::createPlugin( const uint8_t uuid[16], const void* data, size_t size, android::CryptoPlugin** plugin) { if (!isCryptoSchemeSupported(uuid)) { *plugin = NULL; return android::BAD_VALUE; } android::sp<Session> session = SessionLibrary::get()->findSession( data, size); *plugin = new CryptoPlugin(session); return android::OK; }
status_t BnCrypto::onTransact( uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { switch (code) { case INIT_CHECK: { CHECK_INTERFACE(ICrypto, data, reply); reply->writeInt32(initCheck()); return OK; } case IS_CRYPTO_SUPPORTED: { CHECK_INTERFACE(ICrypto, data, reply); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); reply->writeInt32(isCryptoSchemeSupported(uuid)); return OK; } case CREATE_PLUGIN: { CHECK_INTERFACE(ICrypto, data, reply); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); size_t opaqueSize = data.readInt32(); void *opaqueData = NULL; if (opaqueSize > 0) { opaqueData = malloc(opaqueSize); CHECK(opaqueData != NULL); data.read(opaqueData, opaqueSize); } reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); if (opaqueData != NULL) { free(opaqueData); opaqueData = NULL; } return OK; } case DESTROY_PLUGIN: { CHECK_INTERFACE(ICrypto, data, reply); reply->writeInt32(destroyPlugin()); return OK; } case REQUIRES_SECURE_COMPONENT: { CHECK_INTERFACE(ICrypto, data, reply); const char *mime = data.readCString(); reply->writeInt32(requiresSecureDecoderComponent(mime)); return OK; } case DECRYPT: { CHECK_INTERFACE(ICrypto, data, reply); bool secure = data.readInt32() != 0; CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); uint8_t key[16]; data.read(key, sizeof(key)); uint8_t iv[16]; data.read(iv, sizeof(iv)); size_t totalSize = data.readInt32(); sp<IMemory> sharedBuffer = interface_cast<IMemory>(data.readStrongBinder()); int32_t offset = data.readInt32(); int32_t numSubSamples = data.readInt32(); CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[numSubSamples]; data.read( subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); void *secureBufferId, *dstPtr; if (secure) { secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64())); AVMediaUtils::get()->readCustomData(&data, &secureBufferId); } else { dstPtr = malloc(totalSize); CHECK(dstPtr != NULL); } AString errorDetailMsg; ssize_t result; size_t sumSubsampleSizes = 0; bool overflow = false; for (int32_t i = 0; i < numSubSamples; ++i) { CryptoPlugin::SubSample &ss = subSamples[i]; if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) { sumSubsampleSizes += ss.mNumBytesOfEncryptedData; } else { overflow = true; } if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) { sumSubsampleSizes += ss.mNumBytesOfClearData; } else { overflow = true; } } if (overflow || sumSubsampleSizes != totalSize) { result = -EINVAL; } else if (offset + totalSize > sharedBuffer->size()) { result = -EINVAL; } else { result = decrypt( secure, key, iv, mode, sharedBuffer, offset, subSamples, numSubSamples, secure ? secureBufferId : dstPtr, &errorDetailMsg); } reply->writeInt32(result); if (isCryptoError(result)) { reply->writeCString(errorDetailMsg.c_str()); } if (!secure) { if (result >= 0) { CHECK_LE(result, static_cast<ssize_t>(totalSize)); reply->write(dstPtr, result); } free(dstPtr); dstPtr = NULL; } else { AVMediaUtils::get()->closeFileDescriptor(secureBufferId); } delete[] subSamples; subSamples = NULL; return OK; } case NOTIFY_RESOLUTION: { CHECK_INTERFACE(ICrypto, data, reply); int32_t width = data.readInt32(); int32_t height = data.readInt32(); notifyResolution(width, height); return OK; } case SET_MEDIADRM_SESSION: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> sessionId; readVector(data, sessionId); reply->writeInt32(setMediaDrmSession(sessionId)); return OK; } default: return BBinder::onTransact(code, data, reply, flags); } }