am f6c05e4b: am 50d12164: Merge "Camera3Device: Support batch requests" into mnc-dr-dev
* commit 'f6c05e4b6becdffd6cd53747c01f545dfc6fee47':
Camera3Device: Support batch requests
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 3fe749c..00df523 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -215,7 +215,6 @@
const KeyedVector<String8, String8> *headers);
status_t setDataSource(int fd, int64_t offset, int64_t length);
- status_t setDataSource(const sp<IStreamSource> &source);
status_t setDataSource(const sp<IDataSource> &source);
status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index af904a6..999e7eb 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -722,17 +722,20 @@
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
pOutTmp = pOut;
- }else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+ } else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
if (pContext->pBundledContext->frameCount != frameCount) {
if (pContext->pBundledContext->workBuffer != NULL) {
free(pContext->pBundledContext->workBuffer);
}
pContext->pBundledContext->workBuffer =
- (LVM_INT16 *)malloc(frameCount * sizeof(LVM_INT16) * 2);
+ (LVM_INT16 *)calloc(frameCount, sizeof(LVM_INT16) * 2);
+ if (pContext->pBundledContext->workBuffer == NULL) {
+ return -ENOMEM;
+ }
pContext->pBundledContext->frameCount = frameCount;
}
pOutTmp = pContext->pBundledContext->workBuffer;
- }else{
+ } else {
ALOGV("LVM_ERROR : LvmBundle_process invalid access mode");
return -EINVAL;
}
@@ -2872,7 +2875,7 @@
EffectContext * pContext = (EffectContext *) self;
LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
int status = 0;
- int lvmStatus = 0;
+ int processStatus = 0;
LVM_INT16 *in = (LVM_INT16 *)inBuffer->raw;
LVM_INT16 *out = (LVM_INT16 *)outBuffer->raw;
@@ -2960,19 +2963,22 @@
//pContext->pBundledContext->NumberEffectsEnabled,
//pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
- if(status == -ENODATA){
+ if (status == -ENODATA){
ALOGV("\tEffect_process() processing last frame");
}
pContext->pBundledContext->NumberEffectsCalled = 0;
/* Process all the available frames, block processing is
handled internalLY by the LVM bundle */
- lvmStatus = android::LvmBundle_process( (LVM_INT16 *)inBuffer->raw,
+ processStatus = android::LvmBundle_process( (LVM_INT16 *)inBuffer->raw,
(LVM_INT16 *)outBuffer->raw,
outBuffer->frameCount,
pContext);
- if(lvmStatus != LVM_SUCCESS){
- ALOGV("\tLVM_ERROR : LvmBundle_process returned error %d", lvmStatus);
- return lvmStatus;
+ if (processStatus != 0){
+ ALOGV("\tLVM_ERROR : LvmBundle_process returned error %d", processStatus);
+ if (status == 0) {
+ status = processStatus;
+ }
+ return status;
}
} else {
//ALOGV("\tEffect_process Not Calling process with %d effects enabled, %d called: Effect %d",
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 6dd4439..de7bdd8 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -1214,9 +1214,17 @@
fr = inBuffer->frameCount;
}
if (session->inBufSize < session->framesIn + fr) {
+ int16_t *buf;
session->inBufSize = session->framesIn + fr;
- session->inBuf = (int16_t *)realloc(session->inBuf,
+ buf = (int16_t *)realloc(session->inBuf,
session->inBufSize * session->inChannelCount * sizeof(int16_t));
+ if (buf == NULL) {
+ session->framesIn = 0;
+ free(session->inBuf);
+ session->inBuf = NULL;
+ return -ENOMEM;
+ }
+ session->inBuf = buf;
}
memcpy(session->inBuf + session->framesIn * session->inChannelCount,
inBuffer->s16,
@@ -1286,9 +1294,17 @@
effect->session->apm->ProcessStream(session->procFrame);
if (session->outBufSize < session->framesOut + session->frameCount) {
+ int16_t *buf;
session->outBufSize = session->framesOut + session->frameCount;
- session->outBuf = (int16_t *)realloc(session->outBuf,
- session->outBufSize * session->outChannelCount * sizeof(int16_t));
+ buf = (int16_t *)realloc(session->outBuf,
+ session->outBufSize * session->outChannelCount * sizeof(int16_t));
+ if (buf == NULL) {
+ session->framesOut = 0;
+ free(session->outBuf);
+ session->outBuf = NULL;
+ return -ENOMEM;
+ }
+ session->outBuf = buf;
}
if (session->outResampler != NULL) {
@@ -1744,9 +1760,17 @@
fr = inBuffer->frameCount;
}
if (session->revBufSize < session->framesRev + fr) {
+ int16_t *buf;
session->revBufSize = session->framesRev + fr;
- session->revBuf = (int16_t *)realloc(session->revBuf,
- session->revBufSize * session->inChannelCount * sizeof(int16_t));
+ buf = (int16_t *)realloc(session->revBuf,
+ session->revBufSize * session->inChannelCount * sizeof(int16_t));
+ if (buf == NULL) {
+ session->framesRev = 0;
+ free(session->revBuf);
+ session->revBuf = NULL;
+ return -ENOMEM;
+ }
+ session->revBuf = buf;
}
memcpy(session->revBuf + session->framesRev * session->inChannelCount,
inBuffer->s16,
diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp
index 761b243..faf5795 100644
--- a/media/libmedia/IEffect.cpp
+++ b/media/libmedia/IEffect.cpp
@@ -85,13 +85,15 @@
data.writeInt32(size);
status_t status = remote()->transact(COMMAND, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ }
if (status != NO_ERROR) {
if (pReplySize != NULL)
*pReplySize = 0;
return status;
}
- status = reply.readInt32();
size = reply.readInt32();
if (size != 0 && pReplyData != NULL && pReplySize != NULL) {
reply.read(pReplyData, size);
@@ -155,6 +157,10 @@
char *cmd = NULL;
if (cmdSize) {
cmd = (char *)calloc(cmdSize, 1);
+ if (cmd == NULL) {
+ reply->writeInt32(NO_MEMORY);
+ return NO_ERROR;
+ }
data.read(cmd, cmdSize);
}
uint32_t replySize = data.readInt32();
@@ -162,15 +168,22 @@
char *resp = NULL;
if (replySize) {
resp = (char *)calloc(replySize, 1);
+ if (resp == NULL) {
+ free(cmd);
+ reply->writeInt32(NO_MEMORY);
+ return NO_ERROR;
+ }
}
status_t status = command(cmdCode, cmdSize, cmd, &replySz, resp);
reply->writeInt32(status);
- if (replySz < replySize) {
- replySize = replySz;
- }
- reply->writeInt32(replySize);
- if (replySize) {
- reply->write(resp, replySize);
+ if (status == NO_ERROR) {
+ if (replySz < replySize) {
+ replySize = replySz;
+ }
+ reply->writeInt32(replySize);
+ if (replySize) {
+ reply->write(resp, replySize);
+ }
}
if (cmd) {
free(cmd);
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 502ab2d..337e963 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -181,22 +181,6 @@
return err;
}
-status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
-{
- ALOGV("setDataSource");
- status_t err = UNKNOWN_ERROR;
- const sp<IMediaPlayerService>& service(getMediaPlayerService());
- if (service != 0) {
- sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
- if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
- (NO_ERROR != player->setDataSource(source))) {
- player.clear();
- }
- err = attachNewPlayer(player);
- }
- return err;
-}
-
status_t MediaPlayer::setDataSource(const sp<IDataSource> &source)
{
ALOGV("setDataSource(IDataSource)");
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 7dc9be7..27a2934 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1521,7 +1521,8 @@
queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
sp<ABuffer> buffer = mediaBufferToABuffer(
- mbuf, trackType, seekTimeUs, actualTimeUs);
+ mbuf, trackType, seekTimeUs,
+ numBuffers == 0 ? actualTimeUs : NULL);
track->mPackets->queueAccessUnit(buffer);
formatChange = false;
seeking = false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 3646828..c005f3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -635,8 +635,11 @@
flags = AUDIO_OUTPUT_FLAG_NONE;
}
- mRenderer->openAudioSink(
+ status_t err = mRenderer->openAudioSink(
format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */);
+ if (err != OK) {
+ handleError(err);
+ }
}
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 7370224..018e668 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -390,7 +390,7 @@
}
status_t NuPlayerDriver::seekTo(int msec) {
- ALOGD("seekTo(%p) %d ms", this, msec);
+ ALOGD("seekTo(%p) %d ms at state %d", this, msec, mState);
Mutex::Autolock autoLock(mLock);
int64_t seekTimeUs = msec * 1000ll;
@@ -458,7 +458,7 @@
}
status_t NuPlayerDriver::reset() {
- ALOGD("reset(%p)", this);
+ ALOGD("reset(%p) at state %d", this, mState);
Mutex::Autolock autoLock(mLock);
switch (mState) {
@@ -725,7 +725,8 @@
void NuPlayerDriver::notifyListener_l(
int msg, int ext1, int ext2, const Parcel *in) {
- ALOGD("notifyListener_l(%p), (%d, %d, %d)", this, msg, ext1, ext2);
+ ALOGD("notifyListener_l(%p), (%d, %d, %d), loop setting(%d, %d)",
+ this, msg, ext1, ext2, mAutoLoop, mLooping);
switch (msg) {
case MEDIA_PLAYBACK_COMPLETE:
{
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 0ac29a8..fbe463b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -95,6 +95,7 @@
mVideoQueueGeneration(0),
mAudioDrainGeneration(0),
mVideoDrainGeneration(0),
+ mAudioEOSGeneration(0),
mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
mAudioFirstAnchorTimeMediaUs(-1),
mAnchorTimeMediaUs(-1),
@@ -106,10 +107,12 @@
mNotifyCompleteVideo(false),
mSyncQueues(false),
mPaused(false),
+ mPauseDrainAudioAllowedUs(0),
mVideoSampleReceived(false),
mVideoRenderingStarted(false),
mVideoRenderingStartGeneration(0),
mAudioRenderingStartGeneration(0),
+ mLastAudioMediaTimeUs(-1),
mAudioOffloadPauseTimeoutGeneration(0),
mAudioTornDown(false),
mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
@@ -498,6 +501,19 @@
break;
}
+ case kWhatEOS:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("audioEOSGeneration", &generation));
+ if (generation != mAudioEOSGeneration) {
+ break;
+ }
+ status_t finalResult;
+ CHECK(msg->findInt32("finalResult", &finalResult));
+ notifyEOS(true /* audio */, finalResult);
+ break;
+ }
+
case kWhatConfigPlayback:
{
sp<AReplyToken> replyID;
@@ -630,6 +646,14 @@
return;
}
+ // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
+ if (mPaused) {
+ const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
+ if (diffUs > delayUs) {
+ delayUs = diffUs;
+ }
+ }
+
mDrainAudioQueuePending = true;
sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
msg->setInt32("drainGeneration", mAudioDrainGeneration);
@@ -845,6 +869,7 @@
postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
}
notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
+ mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
mAudioQueue.erase(mAudioQueue.begin());
entry = NULL;
@@ -1087,10 +1112,10 @@
int64_t nowUs = -1;
int64_t realTimeUs;
+ int64_t mediaTimeUs = -1;
if (mFlags & FLAG_REAL_TIME) {
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
} else {
- int64_t mediaTimeUs;
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
nowUs = ALooper::GetNowUs();
@@ -1115,6 +1140,14 @@
ALOGV("rendering video at media time %.2f secs",
(mFlags & FLAG_REAL_TIME ? realTimeUs :
mediaUs) / 1E6);
+
+ if (!(mFlags & FLAG_REAL_TIME)
+ && mLastAudioMediaTimeUs != -1
+ && mediaTimeUs > mLastAudioMediaTimeUs) {
+ // If audio ends before video, video continues to drive media clock.
+ // Also smooth out videos >= 10fps.
+ mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
+ }
}
} else {
setVideoLateByUs(0);
@@ -1151,6 +1184,13 @@
}
void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
+ if (audio && delayUs > 0) {
+ sp<AMessage> msg = new AMessage(kWhatEOS, this);
+ msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
+ msg->setInt32("finalResult", finalResult);
+ msg->post(delayUs);
+ return;
+ }
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatEOS);
notify->setInt32("audio", static_cast<int32_t>(audio));
@@ -1301,6 +1341,7 @@
if (audio) {
notifyComplete = mNotifyCompleteAudio;
mNotifyCompleteAudio = false;
+ mLastAudioMediaTimeUs = -1;
} else {
notifyComplete = mNotifyCompleteVideo;
mNotifyCompleteVideo = false;
@@ -1325,6 +1366,7 @@
flushQueue(&mAudioQueue);
++mAudioDrainGeneration;
+ ++mAudioEOSGeneration;
prepareForMediaRenderingStart_l();
// the frame count will be reset after flush.
@@ -1344,8 +1386,16 @@
mAudioSink->flush();
// Call stop() to signal to the AudioSink to completely fill the
// internal buffer before resuming playback.
+ // FIXME: this is ignored after flush().
mAudioSink->stop();
- if (!mPaused) {
+ if (mPaused) {
+ // Race condition: if renderer is paused and audio sink is stopped,
+ // we need to make sure that the audio track buffer fully drains
+ // before delivering data.
+ // FIXME: remove this if we can detect if stop() is complete.
+ const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
+ mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
+ } else {
mAudioSink->start();
}
mNumFramesWritten = 0;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 3e65649..de5f9a9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -148,6 +148,7 @@
int32_t mVideoQueueGeneration;
int32_t mAudioDrainGeneration;
int32_t mVideoDrainGeneration;
+ int32_t mAudioEOSGeneration;
sp<MediaClock> mMediaClock;
float mPlaybackRate; // audio track rate
@@ -170,13 +171,15 @@
// modified on only renderer's thread.
bool mPaused;
+ int64_t mPauseDrainAudioAllowedUs; // time when we can drain/deliver audio in pause mode.
bool mVideoSampleReceived;
bool mVideoRenderingStarted;
int32_t mVideoRenderingStartGeneration;
int32_t mAudioRenderingStartGeneration;
- int64_t mLastPositionUpdateUs;
+ // the media timestamp of last audio sample right before EOS.
+ int64_t mLastAudioMediaTimeUs;
int32_t mAudioOffloadPauseTimeoutGeneration;
bool mAudioTornDown;
diff --git a/media/libnbaio/SourceAudioBufferProvider.cpp b/media/libnbaio/SourceAudioBufferProvider.cpp
index e21ef48..04c42c9 100644
--- a/media/libnbaio/SourceAudioBufferProvider.cpp
+++ b/media/libnbaio/SourceAudioBufferProvider.cpp
@@ -61,20 +61,30 @@
// do we need to reallocate?
if (buffer->frameCount > mSize) {
free(mAllocated);
- mAllocated = malloc(buffer->frameCount * mFrameSize);
+ // Android convention is to _not_ check the return value of malloc and friends.
+ // But in this case the calloc() can also fail due to integer overflow,
+ // so we check and recover.
+ mAllocated = calloc(buffer->frameCount, mFrameSize);
+ if (mAllocated == NULL) {
+ mSize = 0;
+ goto fail;
+ }
mSize = buffer->frameCount;
}
- // read from source
- ssize_t actual = mSource->read(mAllocated, buffer->frameCount, pts);
- if (actual > 0) {
- ALOG_ASSERT((size_t) actual <= buffer->frameCount);
- mOffset = 0;
- mRemaining = actual;
- buffer->raw = mAllocated;
- buffer->frameCount = actual;
- mGetCount = actual;
- return OK;
+ {
+ // read from source
+ ssize_t actual = mSource->read(mAllocated, buffer->frameCount, pts);
+ if (actual > 0) {
+ ALOG_ASSERT((size_t) actual <= buffer->frameCount);
+ mOffset = 0;
+ mRemaining = actual;
+ buffer->raw = mAllocated;
+ buffer->frameCount = actual;
+ mGetCount = actual;
+ return OK;
+ }
}
+fail:
buffer->raw = NULL;
buffer->frameCount = 0;
mGetCount = 0;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 8d9bd21..166600b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1327,7 +1327,8 @@
}
bool stale = false;
- for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
+ for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
+ i--;
BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
if (info->mGraphicBuffer != NULL &&
@@ -1370,7 +1371,8 @@
// get oldest undequeued buffer
BufferInfo *oldest = NULL;
- for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
+ for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
+ i--;
BufferInfo *info =
&mBuffers[kPortIndexOutput].editItemAt(i);
if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index 565f156..5684de7 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -99,8 +99,8 @@
if (offset >= mLength) {
return 0; // read beyond EOF.
}
- int64_t numAvailable = mLength - offset;
- if ((int64_t)size > numAvailable) {
+ uint64_t numAvailable = mLength - offset;
+ if ((uint64_t)size > numAvailable) {
size = numAvailable;
}
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
old mode 100755
new mode 100644
index 38ae6f3..03fa57a
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -766,6 +766,11 @@
status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
ALOGV("entering parseChunk %lld/%d", (long long)*offset, depth);
+
+ if (*offset < 0) {
+ ALOGE("b/23540914");
+ return ERROR_MALFORMED;
+ }
uint32_t hdr[2];
if (mDataSource->readAt(*offset, hdr, 8) < 8) {
return ERROR_IO;
@@ -831,7 +836,12 @@
PathAdder autoAdder(&mPath, chunk_type);
- off64_t chunk_data_size = *offset + chunk_size - data_offset;
+ // (data_offset - *offset) is either 8 or 16
+ off64_t chunk_data_size = chunk_size - (data_offset - *offset);
+ if (chunk_data_size < 0) {
+ ALOGE("b/23540914");
+ return ERROR_MALFORMED;
+ }
if (chunk_type != FOURCC('c', 'p', 'r', 't')
&& chunk_type != FOURCC('c', 'o', 'v', 'r')
@@ -4677,12 +4687,18 @@
// The smallest valid chunk is 16 bytes long in this case.
return false;
}
+
} else if (chunkSize < 8) {
// The smallest valid chunk is 8 bytes long.
return false;
}
- off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
+ // (data_offset - offset) is either 8 or 16
+ off64_t chunkDataSize = chunkSize - (chunkDataOffset - offset);
+ if (chunkDataSize < 0) {
+ ALOGE("b/23540914");
+ return ERROR_MALFORMED;
+ }
char chunkstring[5];
MakeFourCCString(chunkType, chunkstring);
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
index 1a11c1e..7a8bd98 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -107,7 +107,7 @@
}
bool MetaData::findInt32(uint32_t key, int32_t *value) {
- uint32_t type;
+ uint32_t type = 0;
const void *data;
size_t size;
if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
@@ -122,7 +122,7 @@
}
bool MetaData::findInt64(uint32_t key, int64_t *value) {
- uint32_t type;
+ uint32_t type = 0;
const void *data;
size_t size;
if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
@@ -137,7 +137,7 @@
}
bool MetaData::findFloat(uint32_t key, float *value) {
- uint32_t type;
+ uint32_t type = 0;
const void *data;
size_t size;
if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
@@ -152,7 +152,7 @@
}
bool MetaData::findPointer(uint32_t key, void **value) {
- uint32_t type;
+ uint32_t type = 0;
const void *data;
size_t size;
if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
@@ -170,7 +170,7 @@
uint32_t key,
int32_t *left, int32_t *top,
int32_t *right, int32_t *bottom) {
- uint32_t type;
+ uint32_t type = 0;
const void *data;
size_t size;
if (!findData(key, &type, &data, &size) || type != TYPE_RECT) {
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 3f7b35d..e1879b4 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -1333,11 +1333,12 @@
goto exit;
}
- descLen = U32_AT(&flac[8 + typeLen]);
+ if (flacSize < 32 || flacSize - 32 < typeLen) {
+ goto exit;
+ }
- if (flacSize < 32 ||
- flacSize - 32 < typeLen ||
- flacSize - 32 - typeLen < descLen) {
+ descLen = U32_AT(&flac[8 + typeLen]);
+ if (flacSize - 32 - typeLen < descLen) {
goto exit;
}
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 48b810a..b30376d 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -199,7 +199,7 @@
mNumChannels);
}
} else {
- if (mNumChannels < 1 && mNumChannels > 8) {
+ if (mNumChannels < 1 || mNumChannels > 8) {
return ERROR_UNSUPPORTED;
}
}
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index c68264c..dc8a685 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -31,6 +31,7 @@
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
LOCAL_MODULE:= libstagefright_foundation
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
index fc85835..3b94976 100644
--- a/media/libstagefright/httplive/Android.mk
+++ b/media/libstagefright/httplive/Android.mk
@@ -15,6 +15,7 @@
LOCAL_CFLAGS += -Werror -Wall
LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
LOCAL_SHARED_LIBRARIES := \
libbinder \
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index dff6b0b..861b85a 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -31,6 +31,7 @@
#include <openssl/aes.h>
#include <openssl/md5.h>
#include <utils/Mutex.h>
+#include <inttypes.h>
namespace android {
@@ -165,7 +166,10 @@
size_t maxBytesToRead = bufferRemaining;
if (range_length >= 0) {
int64_t bytesLeftInRange = range_length - buffer->size();
- if (bytesLeftInRange < (int64_t)maxBytesToRead) {
+ if (bytesLeftInRange < 0) {
+ ALOGE("range_length %" PRId64 " wrapped around", range_length);
+ return ERROR_OUT_OF_RANGE;
+ } else if (bytesLeftInRange < (int64_t)maxBytesToRead) {
maxBytesToRead = bytesLeftInRange;
if (bytesLeftInRange == 0) {
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index fb11109..37847e3 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -1628,7 +1628,8 @@
if (mSegmentFirstPTS < 0ll) {
// get the smallest first PTS from all streams present in this parser
- for (size_t i = mPacketSources.size(); i-- > 0;) {
+ for (size_t i = mPacketSources.size(); i > 0;) {
+ i--;
const LiveSession::StreamType stream = mPacketSources.keyAt(i);
if (stream == LiveSession::STREAMTYPE_SUBTITLES) {
ALOGE("MPEG2 Transport streams do not contain subtitles.");
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
index 1e8c2b2..216668a 100644
--- a/media/libstagefright/matroska/Android.mk
+++ b/media/libstagefright/matroska/Android.mk
@@ -10,6 +10,7 @@
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
LOCAL_MODULE:= libstagefright_matroska
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index a043df9..bec99a5 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -509,7 +509,7 @@
mLastRecoveredPTS = static_cast<int64_t>(PTS_33bit);
} else {
mLastRecoveredPTS = static_cast<int64_t>(
- ((mLastRecoveredPTS - PTS_33bit + 0x100000000ll)
+ ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000ll)
& 0xfffffffe00000000ull) | PTS_33bit);
// We start from 0, but recovered PTS could be slightly below 0.
// Clamp it to 0 as rest of the pipeline doesn't take negative pts.
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 36ec367..c967463 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1121,6 +1121,10 @@
if (mFormat != NULL && currentStartCode == 0xb8) {
// GOP layer
+ if (offset + 7 >= size) {
+ ALOGE("Size too small");
+ return NULL;
+ }
gopFound = true;
isClosedGop = (data[offset + 7] & 0x40) != 0;
brokenLink = (data[offset + 7] & 0x20) != 0;
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 9f1c5d8..85668f7 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -1589,7 +1589,8 @@
void OMXNodeInstance::freeActiveBuffers() {
// Make sure to count down here, as freeBuffer will in turn remove
// the active buffer from the vector...
- for (size_t i = mActiveBuffers.size(); i--;) {
+ for (size_t i = mActiveBuffers.size(); i > 0;) {
+ i--;
freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
}
}
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index c5e8c35..8bcb29e 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -33,6 +33,7 @@
LOCAL_CFLAGS += -Werror -Wall
LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 052b700..d0ec2a6 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -25,8 +25,6 @@
#include "MtpDataPacket.h"
#include "MtpStringBuffer.h"
-#define MTP_BUFFER_SIZE 16384
-
namespace android {
MtpDataPacket::MtpDataPacket()
@@ -525,16 +523,9 @@
int MtpDataPacket::write(struct usb_request *request) {
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
-
- // send header separately from data
request->buffer = mBuffer;
- request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
+ request->buffer_length = mPacketSize;
int ret = transfer(request);
- if (ret == MTP_CONTAINER_HEADER_SIZE) {
- request->buffer = mBuffer + MTP_CONTAINER_HEADER_SIZE;
- request->buffer_length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
- ret = transfer(request);
- }
return (ret < 0 ? ret : 0);
}
@@ -547,17 +538,17 @@
#endif // MTP_HOST
-void* MtpDataPacket::getData(int& outLength) const {
+void* MtpDataPacket::getData(int* outLength) const {
int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
if (length > 0) {
void* result = malloc(length);
if (result) {
memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
- outLength = length;
+ *outLength = length;
return result;
}
}
- outLength = 0;
+ *outLength = 0;
return NULL;
}
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 13d3bd9..6240f28 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -117,7 +117,7 @@
inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
inline uint32_t getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); }
- void* getData(int& outLength) const;
+ void* getData(int* outLength) const;
};
}; // namespace android
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 3eafd6f..9878f90 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -19,6 +19,7 @@
#include "MtpDebug.h"
#include "MtpDevice.h"
#include "MtpDeviceInfo.h"
+#include "MtpEventPacket.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpStorageInfo.h"
@@ -50,6 +51,15 @@
}
#endif
+namespace {
+
+bool writeToFd(void* data, int /* unused_offset */, int length, void* clientData) {
+ const int fd = *static_cast<int*>(clientData);
+ return write(fd, data, length) == length;
+}
+
+}
+
MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
struct usb_device *device = usb_device_new(deviceName, fd);
if (!device) {
@@ -414,7 +424,7 @@
if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
- return mData.getData(outLength);
+ return mData.getData(&outLength);
}
}
outLength = 0;
@@ -430,8 +440,9 @@
parent = MTP_PARENT_ROOT;
mRequest.setParameter(1, info->mStorageID);
- mRequest.setParameter(2, info->mParent);
+ mRequest.setParameter(2, parent);
+ mData.reset();
mData.putUInt32(info->mStorageID);
mData.putUInt16(info->mFormat);
mData.putUInt16(info->mProtectionStatus);
@@ -472,17 +483,18 @@
return (MtpObjectHandle)-1;
}
-bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
+bool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) {
Mutex::Autolock autoLock(mMutex);
- int remaining = info->mCompressedSize;
+ int remaining = size;
mRequest.reset();
- mRequest.setParameter(1, info->mHandle);
+ mRequest.setParameter(1, handle);
if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
// send data header
writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
- char buffer[65536];
+ // USB writes greater than 16K don't work
+ char buffer[MTP_BUFFER_SIZE];
while (remaining > 0) {
int count = read(srcFD, buffer, sizeof(buffer));
if (count > 0) {
@@ -592,97 +604,12 @@
}
bool MtpDevice::readObject(MtpObjectHandle handle,
- bool (* callback)(void* data, int offset, int length, void* clientData),
- size_t objectSize, void* clientData) {
- Mutex::Autolock autoLock(mMutex);
- bool result = false;
-
- mRequest.reset();
- mRequest.setParameter(1, handle);
- if (sendRequest(MTP_OPERATION_GET_OBJECT)
- && mData.readDataHeader(mRequestIn1)) {
- uint32_t length = mData.getContainerLength();
- if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) {
- ALOGE("readObject error objectSize: %d, length: %d",
- objectSize, length);
- goto fail;
- }
- length -= MTP_CONTAINER_HEADER_SIZE;
- uint32_t remaining = length;
- int offset = 0;
-
- int initialDataLength = 0;
- void* initialData = mData.getData(initialDataLength);
- if (initialData) {
- if (initialDataLength > 0) {
- if (!callback(initialData, 0, initialDataLength, clientData))
- goto fail;
- remaining -= initialDataLength;
- offset += initialDataLength;
- }
- free(initialData);
- }
-
- // USB reads greater than 16K don't work
- char buffer1[16384], buffer2[16384];
- mRequestIn1->buffer = buffer1;
- mRequestIn2->buffer = buffer2;
- struct usb_request* req = mRequestIn1;
- void* writeBuffer = NULL;
- int writeLength = 0;
-
- while (remaining > 0 || writeBuffer) {
- if (remaining > 0) {
- // queue up a read request
- req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
- if (mData.readDataAsync(req)) {
- ALOGE("readDataAsync failed");
- goto fail;
- }
- } else {
- req = NULL;
- }
-
- if (writeBuffer) {
- // write previous buffer
- if (!callback(writeBuffer, offset, writeLength, clientData)) {
- ALOGE("write failed");
- // wait for pending read before failing
- if (req)
- mData.readDataWait(mDevice);
- goto fail;
- }
- offset += writeLength;
- writeBuffer = NULL;
- }
-
- // wait for read to complete
- if (req) {
- int read = mData.readDataWait(mDevice);
- if (read < 0)
- goto fail;
-
- if (read > 0) {
- writeBuffer = req->buffer;
- writeLength = read;
- remaining -= read;
- req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
- } else {
- writeBuffer = NULL;
- }
- }
- }
-
- MtpResponseCode response = readResponse();
- if (response == MTP_RESPONSE_OK)
- result = true;
- }
-
-fail:
- return result;
+ ReadObjectCallback callback,
+ size_t expectedLength,
+ void* clientData) {
+ return readObjectInternal(handle, callback, &expectedLength, clientData);
}
-
// reads the object's data and writes it to the specified file path
bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
ALOGD("readObject: %s", destPath);
@@ -698,89 +625,105 @@
fchmod(fd, perm);
umask(mask);
+ bool result = readObject(handle, fd);
+ ::close(fd);
+ return result;
+}
+
+bool MtpDevice::readObject(MtpObjectHandle handle, int fd) {
+ ALOGD("readObject: %d", fd);
+ return readObjectInternal(handle, writeToFd, NULL /* expected size */, &fd);
+}
+
+bool MtpDevice::readObjectInternal(MtpObjectHandle handle,
+ ReadObjectCallback callback,
+ const size_t* expectedLength,
+ void* clientData) {
Mutex::Autolock autoLock(mMutex);
- bool result = false;
mRequest.reset();
mRequest.setParameter(1, handle);
- if (sendRequest(MTP_OPERATION_GET_OBJECT)
- && mData.readDataHeader(mRequestIn1)) {
- uint32_t length = mData.getContainerLength();
- if (length < MTP_CONTAINER_HEADER_SIZE)
- goto fail;
- length -= MTP_CONTAINER_HEADER_SIZE;
- uint32_t remaining = length;
+ if (!sendRequest(MTP_OPERATION_GET_OBJECT)) {
+ ALOGE("Failed to send a read request.");
+ return false;
+ }
+ if (!mData.readDataHeader(mRequestIn1)) {
+ ALOGE("Failed to read header.");
+ return false;
+ }
+
+ const uint32_t fullLength = mData.getContainerLength();
+ if ((!expectedLength && fullLength < MTP_CONTAINER_HEADER_SIZE) ||
+ (expectedLength && *expectedLength + MTP_CONTAINER_HEADER_SIZE != fullLength)) {
+ ALOGE("readObject error length: %d", fullLength);
+ return false;
+ }
+
+ const uint32_t length = fullLength - MTP_CONTAINER_HEADER_SIZE;
+ uint32_t offset = 0;
+ bool writingError = false;
+
+ {
int initialDataLength = 0;
- void* initialData = mData.getData(initialDataLength);
+ void* const initialData = mData.getData(&initialDataLength);
if (initialData) {
if (initialDataLength > 0) {
- if (write(fd, initialData, initialDataLength) != initialDataLength) {
- free(initialData);
- goto fail;
+ if (!callback(initialData, offset, initialDataLength, clientData)) {
+ ALOGE("Failed to write initial data.");
+ writingError = true;
}
- remaining -= initialDataLength;
+ offset += initialDataLength;
}
free(initialData);
}
+ }
- // USB reads greater than 16K don't work
- char buffer1[16384], buffer2[16384];
- mRequestIn1->buffer = buffer1;
- mRequestIn2->buffer = buffer2;
- struct usb_request* req = mRequestIn1;
+ // USB reads greater than 16K don't work.
+ char buffer1[MTP_BUFFER_SIZE], buffer2[MTP_BUFFER_SIZE];
+ mRequestIn1->buffer = buffer1;
+ mRequestIn2->buffer = buffer2;
+ struct usb_request* req = NULL;
+
+ while (offset < length) {
+ // Wait for previous read to complete.
void* writeBuffer = NULL;
int writeLength = 0;
-
- while (remaining > 0 || writeBuffer) {
- if (remaining > 0) {
- // queue up a read request
- req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
- if (mData.readDataAsync(req)) {
- ALOGE("readDataAsync failed");
- goto fail;
- }
- } else {
- req = NULL;
+ if (req) {
+ const int read = mData.readDataWait(mDevice);
+ if (read < 0) {
+ ALOGE("readDataWait failed.");
+ return false;
}
+ writeBuffer = req->buffer;
+ writeLength = read;
+ }
- if (writeBuffer) {
- // write previous buffer
- if (write(fd, writeBuffer, writeLength) != writeLength) {
- ALOGE("write failed");
- // wait for pending read before failing
- if (req)
- mData.readDataWait(mDevice);
- goto fail;
- }
- writeBuffer = NULL;
- }
-
- // wait for read to complete
- if (req) {
- int read = mData.readDataWait(mDevice);
- if (read < 0)
- goto fail;
-
- if (read > 0) {
- writeBuffer = req->buffer;
- writeLength = read;
- remaining -= read;
- req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
- } else {
- writeBuffer = NULL;
- }
+ // Request to read next chunk.
+ const uint32_t nextOffset = offset + writeLength;
+ if (nextOffset < length) {
+ // Queue up a read request.
+ const size_t remaining = length - nextOffset;
+ req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
+ req->buffer_length =
+ remaining > MTP_BUFFER_SIZE ? static_cast<size_t>(MTP_BUFFER_SIZE) : remaining;
+ if (mData.readDataAsync(req) != 0) {
+ ALOGE("readDataAsync failed");
+ return false;
}
}
- MtpResponseCode response = readResponse();
- if (response == MTP_RESPONSE_OK)
- result = true;
+ // Write previous buffer.
+ if (writeBuffer && !writingError) {
+ if (!callback(writeBuffer, offset, writeLength, clientData)) {
+ ALOGE("write failed");
+ writingError = true;
+ }
+ }
+ offset = nextOffset;
}
-fail:
- ::close(fd);
- return result;
+ return readResponse() == MTP_RESPONSE_OK && !writingError;
}
bool MtpDevice::sendRequest(MtpOperationCode operation) {
@@ -800,7 +743,7 @@
mData.setTransactionID(mRequest.getTransactionID());
int ret = mData.write(mRequestOut);
mData.dump();
- return (ret > 0);
+ return (ret >= 0);
}
bool MtpDevice::readData() {
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 9b0acbf..d2c6d67 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -60,6 +60,7 @@
Mutex mMutex;
public:
+ typedef bool (*ReadObjectCallback)(void* data, int offset, int length, void* clientData);
MtpDevice(struct usb_device* device, int interface,
const struct usb_endpoint_descriptor *ep_in,
const struct usb_endpoint_descriptor *ep_out,
@@ -85,7 +86,7 @@
MtpObjectInfo* getObjectInfo(MtpObjectHandle handle);
void* getThumbnail(MtpObjectHandle handle, int& outLength);
MtpObjectHandle sendObjectInfo(MtpObjectInfo* info);
- bool sendObject(MtpObjectInfo* info, int srcFD);
+ bool sendObject(MtpObjectHandle handle, int size, int srcFD);
bool deleteObject(MtpObjectHandle handle);
MtpObjectHandle getParent(MtpObjectHandle handle);
MtpObjectHandle getStorageID(MtpObjectHandle handle);
@@ -95,14 +96,16 @@
MtpProperty* getDevicePropDesc(MtpDeviceProperty code);
MtpProperty* getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format);
- bool readObject(MtpObjectHandle handle,
- bool (* callback)(void* data, int offset,
- int length, void* clientData),
+ bool readObject(MtpObjectHandle handle, ReadObjectCallback callback,
size_t objectSize, void* clientData);
bool readObject(MtpObjectHandle handle, const char* destPath, int group,
int perm);
+ bool readObject(MtpObjectHandle handle, int fd);
private:
+ // If |objectSize| is not NULL, it checks object size before reading data bytes.
+ bool readObjectInternal(MtpObjectHandle handle, ReadObjectCallback callback,
+ const size_t* objectSize, void* clientData);
bool sendRequest(MtpOperationCode operation);
bool sendData();
bool readData();
diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h
index d270df5..7b80d2e 100644
--- a/media/mtp/mtp.h
+++ b/media/mtp/mtp.h
@@ -37,6 +37,9 @@
#define MTP_CONTAINER_PARAMETER_OFFSET 12
#define MTP_CONTAINER_HEADER_SIZE 12
+// Maximum buffer size for a MTP packet.
+#define MTP_BUFFER_SIZE 16384
+
// MTP Data Types
#define MTP_TYPE_UNDEFINED 0x0000 // Undefined
#define MTP_TYPE_INT8 0x0001 // Signed 8-bit integer
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 0ecd64f..b869c54 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -243,15 +243,27 @@
while (len > 0) {
numentries++;
+ if (len < 16) {
+ ALOGE("invalid PSSH data");
+ return NULL;
+ }
// skip uuid
data += 16;
len -= 16;
// get data length
+ if (len < 4) {
+ ALOGE("invalid PSSH data");
+ return NULL;
+ }
uint32_t datalen = *((uint32_t*)data);
data += 4;
len -= 4;
+ if (len < datalen) {
+ ALOGE("invalid PSSH data");
+ return NULL;
+ }
// skip the data
data += datalen;
len -= datalen;
@@ -265,6 +277,10 @@
// extra pointer for each entry, and an extra size_t for the entire PsshInfo.
size_t newsize = buffer->size() - (sizeof(uint32_t) * numentries) + sizeof(size_t)
+ ((sizeof(void*) + sizeof(size_t)) * numentries);
+ if (newsize <= buffer->size()) {
+ ALOGE("invalid PSSH data");
+ return NULL;
+ }
ex->mPsshBuf = new ABuffer(newsize);
ex->mPsshBuf->setRange(0, newsize);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9ec5802..fab1ef5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1352,12 +1352,16 @@
AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
: RefBase(),
mAudioFlinger(audioFlinger),
- // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
- mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
mPid(pid),
mTimedTrackCount(0)
{
- // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
+ size_t heapSize = kClientSharedHeapSizeBytes;
+ // Increase heap size on non low ram devices to limit risk of reconnection failure for
+ // invalidated tracks
+ if (!audioFlinger->isLowRamDevice()) {
+ heapSize *= kClientSharedHeapSizeMultiplier;
+ }
+ mMemoryDealer = new MemoryDealer(heapSize, "AudioFlinger::Client");
}
// Client destructor must be called with AudioFlinger::mClientLock held
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 20c34ef..08fa70d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -88,6 +88,12 @@
static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
+
+// Max shared memory size for audio tracks and audio records per client process
+static const size_t kClientSharedHeapSizeBytes = 1024*1024;
+// Shared memory size multiplier for non low ram devices
+static const size_t kClientSharedHeapSizeMultiplier = 4;
+
#define INCLUDING_FROM_AUDIOFLINGER_H
class AudioFlinger :
@@ -423,7 +429,7 @@
Client(const Client&);
Client& operator = (const Client&);
const sp<AudioFlinger> mAudioFlinger;
- const sp<MemoryDealer> mMemoryDealer;
+ sp<MemoryDealer> mMemoryDealer;
const pid_t mPid;
Mutex mTimedTrackLock;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index f7da209..d058255 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -712,9 +712,12 @@
// But in this case we know the mixer thread (whether normal mixer or fast mixer)
// isn't looking at this track yet: we still hold the normal mixer thread lock,
// and for fast tracks the track is not yet in the fast mixer thread's active set.
- ServerProxy::Buffer buffer;
- buffer.mFrameCount = 1;
- (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
+ // TODO: remove race condition on stop() followed by start().
+ if (mSharedBuffer == 0) { // only streaming tracks use flush().
+ ServerProxy::Buffer buffer;
+ buffer.mFrameCount = 1;
+ (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
+ }
}
} else {
status = BAD_VALUE;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b1d7b13..be648bc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1356,20 +1356,7 @@
} else {
*inputType = API_INPUT_LEGACY;
}
- // adapt channel selection to input source
- switch (inputSource) {
- case AUDIO_SOURCE_VOICE_UPLINK:
- channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
- break;
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK;
- break;
- case AUDIO_SOURCE_VOICE_CALL:
- channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
- break;
- default:
- break;
- }
+
if (inputSource == AUDIO_SOURCE_HOTWORD) {
ssize_t index = mSoundTriggerSessions.indexOfKey(session);
if (index >= 0) {
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index eefff3d..619e5c1 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -149,7 +149,10 @@
// connects to AudioPolicyService.
void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
{
-
+ if (client == 0) {
+ ALOGW("%s got NULL client", __FUNCTION__);
+ return;
+ }
Mutex::Autolock _l(mNotificationClientsLock);
uid_t uid = IPCThreadState::self()->getCallingUid();