MediaCas: fixes for playback tests
- Set crypto mode to kMode_AES_CTR, since kMode_AES_CBC is not defined
on Java API, and is rejected when the sample is queued to MediaCodec.
- Wrap the plugin object in a RefBase, and hold a strong ref to it
when executing any API calls in CasImpl. This is needed because
CasImpl could be released by Java API, while MediaCodec native is
still trying to access it.
- Fix build warnings.
Tests: cts-tradefed run cts-dev --module CtsMediaTestCases --test android.media.cts.ClearKeySystemTest
It should not fail.
bug: 22804304
Change-Id: Id4ef037d57dd741d2bb22b1de3d04c8d078b69fb
diff --git a/drm/libmediadrm/CasImpl.cpp b/drm/libmediadrm/CasImpl.cpp
index de15244..fcedd6b 100644
--- a/drm/libmediadrm/CasImpl.cpp
+++ b/drm/libmediadrm/CasImpl.cpp
@@ -49,13 +49,24 @@
return result;
}
+struct CasImpl::PluginHolder : public RefBase {
+public:
+ explicit PluginHolder(CasPlugin *plugin) : mPlugin(plugin) {}
+ ~PluginHolder() { if (mPlugin != NULL) delete mPlugin; }
+ CasPlugin* get() { return mPlugin; }
+
+private:
+ CasPlugin *mPlugin;
+ DISALLOW_EVIL_CONSTRUCTORS(PluginHolder);
+};
+
CasImpl::CasImpl(const sp<ICasListener> &listener)
- : mPlugin(NULL), mListener(listener) {
- ALOGV("CTOR: mPlugin=%p", mPlugin);
+ : mPluginHolder(NULL), mListener(listener) {
+ ALOGV("CTOR");
}
CasImpl::~CasImpl() {
- ALOGV("DTOR: mPlugin=%p", mPlugin);
+ ALOGV("DTOR");
release();
}
@@ -76,7 +87,7 @@
void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin *plugin) {
mLibrary = library;
- mPlugin = plugin;
+ mPluginHolder = new PluginHolder(plugin);
}
void CasImpl::onEvent(
@@ -95,13 +106,20 @@
Status CasImpl::setPrivateData(const CasData& pvtData) {
ALOGV("setPrivateData");
- return getBinderStatus(mPlugin->setPrivateData(pvtData));
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
+ return getBinderStatus(holder->get()->setPrivateData(pvtData));
}
Status CasImpl::openSession(int32_t program_number, CasSessionId* sessionId) {
ALOGV("openSession: program_number=%d", program_number);
-
- status_t err = mPlugin->openSession(program_number, sessionId);
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
+ status_t err = holder->get()->openSession(program_number, sessionId);
ALOGV("openSession: session opened for program_number=%d, sessionId=%s",
program_number, sessionIdToString(*sessionId).string());
@@ -115,8 +133,11 @@
CasSessionId* sessionId) {
ALOGV("openSession: program_number=%d, elementary_PID=%d",
program_number, elementary_PID);
-
- status_t err = mPlugin->openSession(
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
+ status_t err = holder->get()->openSession(
program_number, elementary_PID, sessionId);
ALOGV("openSession: session opened for "
@@ -131,69 +152,92 @@
const CasSessionId &sessionId, const CasData& pvtData) {
ALOGV("setSessionPrivateData: sessionId=%s",
sessionIdToString(sessionId).string());
-
- return getBinderStatus(mPlugin->setSessionPrivateData(sessionId, pvtData));
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
+ return getBinderStatus(holder->get()->setSessionPrivateData(sessionId, pvtData));
}
Status CasImpl::closeSession(const CasSessionId &sessionId) {
ALOGV("closeSession: sessionId=%s",
sessionIdToString(sessionId).string());
-
- return getBinderStatus(mPlugin->closeSession(sessionId));
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
+ return getBinderStatus(holder->get()->closeSession(sessionId));
}
Status CasImpl::processEcm(const CasSessionId &sessionId, const ParcelableCasData& ecm) {
ALOGV("processEcm: sessionId=%s",
sessionIdToString(sessionId).string());
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
- return getBinderStatus(mPlugin->processEcm(sessionId, ecm));
+ return getBinderStatus(holder->get()->processEcm(sessionId, ecm));
}
Status CasImpl::processEmm(const ParcelableCasData& emm) {
ALOGV("processEmm");
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
- return getBinderStatus(mPlugin->processEmm(emm));
+ return getBinderStatus(holder->get()->processEmm(emm));
}
Status CasImpl::sendEvent(
int32_t event, int32_t arg, const ::std::unique_ptr<CasData> &eventData) {
ALOGV("sendEvent");
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
status_t err;
if (eventData == nullptr) {
- err = mPlugin->sendEvent(event, arg, CasData());
+ err = holder->get()->sendEvent(event, arg, CasData());
} else {
- err = mPlugin->sendEvent(event, arg, *eventData);
+ err = holder->get()->sendEvent(event, arg, *eventData);
}
return getBinderStatus(err);
}
Status CasImpl::provision(const String16& provisionString) {
ALOGV("provision: provisionString=%s", String8(provisionString).string());
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
- return getBinderStatus(mPlugin->provision(String8(provisionString)));
+ return getBinderStatus(holder->get()->provision(String8(provisionString)));
}
Status CasImpl::refreshEntitlements(
int32_t refreshType, const ::std::unique_ptr<CasData> &refreshData) {
ALOGV("refreshEntitlements");
+ sp<PluginHolder> holder = mPluginHolder;
+ if (holder == NULL) {
+ return getBinderStatus(INVALID_OPERATION);
+ }
status_t err;
if (refreshData == nullptr) {
- err = mPlugin->refreshEntitlements(refreshType, CasData());
+ err = holder->get()->refreshEntitlements(refreshType, CasData());
} else {
- err = mPlugin->refreshEntitlements(refreshType, *refreshData);
+ err = holder->get()->refreshEntitlements(refreshType, *refreshData);
}
return getBinderStatus(err);
}
Status CasImpl::release() {
- ALOGV("release: mPlugin=%p", mPlugin);
-
- if (mPlugin != NULL) {
- delete mPlugin;
- mPlugin = NULL;
- }
+ ALOGV("release: plugin=%p",
+ mPluginHolder == NULL ? mPluginHolder->get() : NULL);
+ mPluginHolder.clear();
return Status::ok();
}
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
index 221b74b..f4c3577 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
@@ -84,7 +84,7 @@
///////////////////////////////////////////////////////////////////////////////
ClearKeyCasPlugin::ClearKeyCasPlugin(
uint64_t appData, CasPluginCallback callback)
- : mAppData(appData), mCallback(callback) {
+ : mCallback(callback), mAppData(appData) {
ALOGV("CTOR");
}
@@ -93,7 +93,7 @@
ClearKeySessionLibrary::get()->destroyPlugin(this);
}
-status_t ClearKeyCasPlugin::setPrivateData(const CasData &data) {
+status_t ClearKeyCasPlugin::setPrivateData(const CasData &/*data*/) {
ALOGV("setPrivateData");
return OK;
@@ -142,7 +142,7 @@
}
status_t ClearKeyCasPlugin::setSessionPrivateData(
- const CasSessionId &sessionId, const CasData &data) {
+ const CasSessionId &sessionId, const CasData & /*data*/) {
ALOGV("setSessionPrivateData: sessionId=%s",
sessionIdToString(sessionId).string());
sp<ClearKeyCasSession> session =
@@ -167,7 +167,7 @@
return session->updateECM(mKeyFetcher.get(), (void*)ecm.data(), ecm.size());
}
-status_t ClearKeyCasPlugin::processEmm(const CasEmm& emm) {
+status_t ClearKeyCasPlugin::processEmm(const CasEmm& /*emm*/) {
ALOGV("processEmm");
Mutex::Autolock lock(mKeyFetcherLock);
@@ -212,8 +212,8 @@
}
status_t ClearKeyCasPlugin::refreshEntitlements(
- int32_t refreshType, const CasData &refreshData) {
- ALOGV("refreshEntitlements");
+ int32_t refreshType, const CasData &/*refreshData*/) {
+ ALOGV("refreshEntitlements: refreshType=%d", refreshType);
Mutex::Autolock lock(mKeyFetcherLock);
return OK;
@@ -344,7 +344,7 @@
AES_BLOCK_SIZE * 8, &mKeyInfo[keyIndex].contentKey);
mKeyInfo[keyIndex].valid = (result == 0);
if (!mKeyInfo[keyIndex].valid) {
- ALOGE("updateECM: failed to set key %d, key_id=%d",
+ ALOGE("updateECM: failed to set key %zu, key_id=%d",
keyIndex, keys[keyIndex].key_id);
}
}
@@ -356,6 +356,10 @@
bool secure, DescramblerPlugin::ScramblingControl scramblingControl,
size_t numSubSamples, const DescramblerPlugin::SubSample *subSamples,
const void *srcPtr, void *dstPtr, AString * /* errorDetailMsg */) {
+ if (secure) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
AES_KEY contentKey;
if (scramblingControl != DescramblerPlugin::kScrambling_Unscrambled) {
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
index 210bab3..cb69f91 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "ClearKeyFetcher"
#include <algorithm>
+#include <inttypes.h>
#include <string>
#include "ClearKeyFetcher.h"
@@ -70,7 +71,7 @@
bool same_parity = (((container.descriptor(0).id() & 0x01) ^
(container.descriptor(1).id() & 0x01)) == 0);
if (same_parity) {
- ALOGW("asset_id=%llu: malformed Ecm, "
+ ALOGW("asset_id=%" PRIu64 ": malformed Ecm, "
"content keys have same parity, id0=%d, id1=%d",
container.descriptor(0).ecm().asset_id(),
container.descriptor(0).id(),
@@ -88,7 +89,7 @@
// asset_id change. If it sends an EcmContainer with 2 Ecms with different
// asset_ids (old and new) then it might be best to prefetch the Emm.
if ((asset_.id() != 0) && (*asset_id != asset_.id())) {
- ALOGW("Asset_id change from %llu to %llu", asset_.id(), *asset_id);
+ ALOGW("Asset_id change from %" PRIu64 " to %" PRIu64, asset_.id(), *asset_id);
asset_.Clear();
}
diff --git a/drm/mediacas/plugins/clearkey/ecm_generator.cpp b/drm/mediacas/plugins/clearkey/ecm_generator.cpp
index f1aa973..7d29659 100644
--- a/drm/mediacas/plugins/clearkey/ecm_generator.cpp
+++ b/drm/mediacas/plugins/clearkey/ecm_generator.cpp
@@ -80,7 +80,7 @@
CHECK(default_fields);
if (ecm->size() < kTotalEcmSize) {
- ALOGE("Short ECM: expected_length=%zu, actual_length=%zu",
+ ALOGE("Short ECM: expected_length=%d, actual_length=%zu",
kTotalEcmSize, ecm->size());
return BAD_VALUE;
}
diff --git a/include/media/CasImpl.h b/include/media/CasImpl.h
index 80c901e..3c07092 100644
--- a/include/media/CasImpl.h
+++ b/include/media/CasImpl.h
@@ -84,8 +84,9 @@
virtual Status release() override;
private:
+ struct PluginHolder;
sp<SharedLibrary> mLibrary;
- CasPlugin *mPlugin;
+ sp<PluginHolder> mPluginHolder;
sp<ICasListener> mListener;
DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index b933002..6bac1db 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -577,7 +577,7 @@
// fill in CryptoInfo fields for AnotherPacketSource::read()
// MediaCas doesn't use cryptoMode, but set to non-zero value here.
scrambledAccessUnit->meta()->setInt32(
- "cryptoMode", CryptoPlugin::kMode_AES_CBC);
+ "cryptoMode", CryptoPlugin::kMode_AES_CTR);
scrambledAccessUnit->meta()->setInt32("cryptoKey", keyId);
scrambledAccessUnit->meta()->setBuffer("clearBytes", clearSizes);
scrambledAccessUnit->meta()->setBuffer("encBytes", encSizes);