Fix native fault in WVMMediaSource::DecryptCallback

This change resolves a lifetime issue between the media extractor
and media sources.  The extractor was being passed as a context
object to a callout in the WV libs.  In some cases, a pointer to
the extractor would be delivered to the callout after the extractor
had been released.  This change assigns the responsibility of the
lifetime of the context object to the media source, to ensure that
a ref is always held on the context object during the lifetime of
the media source.

Change-Id: Ic7a57a1c8496a4798fe590ec356b8a19a4f69967
related-to-bug: 6502322
This commit is contained in:
Jeff Tinker
2012-05-16 11:11:14 -07:00
parent 79e250e999
commit e9c40a625c
5 changed files with 89 additions and 43 deletions

View File

@@ -93,13 +93,12 @@ bool IsWidevineMedia(const sp<DataSource>& dataSource) {
WVMExtractorImpl::WVMExtractorImpl(sp<DataSource> dataSource)
: mFileMetaData(new MetaData()),
mDataSource(dataSource),
mClientContext(new ClientContext()),
mHaveMetaData(false),
mUseAdaptiveStreaming(false),
mIsLiveStream(false),
mSession(NULL),
mSetupStatus(OK),
mUIDIsSet(false),
mCryptoPluginMode(false)
mSetupStatus(OK)
{
dataSource->getDrmInfo(sDecryptHandle, &sDrmManagerClient);
@@ -161,13 +160,13 @@ void WVMExtractorImpl::Initialize()
// Use the URI - streaming case, only for widevine:// protocol
result = WV_Setup(mSession, mDataSource->getUri().string(),
"RAW/RAW/RAW;destination=getdata", credentials,
WV_OutputFormat_ES, kStreamCacheSize, this);
WV_OutputFormat_ES, kStreamCacheSize, mClientContext.get());
} else {
// No URI supplied or not adaptive, pull data from the stagefright data source.
mFileSource = new WVMFileSource(mDataSource);
result = WV_Setup(mSession, mFileSource.get(),
"RAW/RAW/RAW;destination=getdata", credentials,
WV_OutputFormat_ES, kStreamCacheSize, this);
WV_OutputFormat_ES, kStreamCacheSize, mClientContext.get());
}
if (result != WV_Status_OK) {
@@ -198,21 +197,21 @@ void WVMExtractorImpl::SocketInfoCallback(int fd, int closing, void *context)
{
//ALOGD("WVMExtractorImpl::SocketInfoCallback(%d, %d, %p)", fd, closing, context);
WVMExtractorImpl *obj = (WVMExtractorImpl *)context;
ClientContext *obj = (ClientContext *)context;
if (!obj) {
ALOGW("SocketInfoCallback: missing context!");
// Not an error, there are some cases where this is expected
return;
} else if (!obj->mUIDIsSet) {
} else if (!obj->haveUID()) {
ALOGW("SocketInfoCallback: UID not set!");
return;
}
if (!closing) {
uint32_t kTag = *(uint32_t *)"WVEX";
int res = qtaguid_tagSocket(fd, kTag, obj->mUID);
int res = qtaguid_tagSocket(fd, kTag, obj->getUID());
if (res != 0) {
ALOGE("Failed tagging socket %d for uid %d (My UID=%d)", fd, obj->mUID, geteuid());
ALOGE("Failed tagging socket %d for uid %d (My UID=%d)", fd, obj->getUID(), geteuid());
}
} else {
int res = qtaguid_untagSocket(fd);
@@ -339,10 +338,12 @@ status_t WVMExtractorImpl::readMetaData()
}
}
bool cryptoPluginMode = mClientContext->getCryptoPluginMode();
mAudioSource = new WVMMediaSource(mSession, WV_EsSelector_Audio, audioMetaData,
mIsLiveStream, mCryptoPluginMode);
mIsLiveStream, cryptoPluginMode);
mVideoSource = new WVMMediaSource(mSession, WV_EsSelector_Video, videoMetaData,
mIsLiveStream, mCryptoPluginMode);
mIsLiveStream, cryptoPluginMode);
// Since the WVExtractor goes away soon after this, we delegate ownership of some resources
// to the constructed media source
@@ -351,13 +352,17 @@ status_t WVMExtractorImpl::readMetaData()
mVideoSource->delegateDataSource(mDataSource);
mClientContext->setAudioSource(mAudioSource);
mClientContext->setVideoSource(mVideoSource);
mVideoSource->delegateClientContext(mClientContext);
mFileMetaData->setCString(kKeyMIMEType, "video/wvm");
mHaveMetaData = true;
mInfoListener->configureHeartbeat();
if (mCryptoPluginMode) {
if (cryptoPluginMode) {
// In crypto plugin mode, need to trigger the drm plugin to begin
// license use on playback since the media player isn't involved.
sDrmManagerClient->setPlaybackStatus(sDecryptHandle, Playback::START, 0);
@@ -534,20 +539,13 @@ bool WVMExtractorImpl::getAdaptiveStreamingMode() const
void WVMExtractorImpl::setCryptoPluginMode(bool cryptoPluginMode)
{
//ALOGD("WVMExtractorImpl::setCryptoPluginMode(%d)", cryptoPluginMode);
mCryptoPluginMode = cryptoPluginMode;
}
bool WVMExtractorImpl::getCryptoPluginMode() const
{
//ALOGD("WVMExtractorImpl::getCryptoPluginMode - %d", mCryptoPluginMode);
return mCryptoPluginMode;
mClientContext->setCryptoPluginMode(cryptoPluginMode);
}
void WVMExtractorImpl::setUID(uid_t uid)
{
//ALOGD("WVMExtractorImpl::setUID(%d)", (uint32_t)uid);
mUID = uid;
mUIDIsSet = true;
mClientContext->setUID(uid);
}
} // namespace android