am a3610be1: am 08723d86: am 5d76e54d: Merge "NuPlayer: do not create audio decoder if the player is still in shutdown process." into mnc-dev
* commit 'a3610be12d03da21dcb5e6ed36b98db9d0e4d692':
NuPlayer: do not create audio decoder if the player is still in shutdown process.
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/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 04a46f4..1c41c10 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -110,6 +110,7 @@
mVideoRenderingStarted(false),
mVideoRenderingStartGeneration(0),
mAudioRenderingStartGeneration(0),
+ mLastAudioMediaTimeUs(-1),
mAudioOffloadPauseTimeoutGeneration(0),
mAudioTornDown(false),
mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
@@ -845,6 +846,7 @@
postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
}
notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
+ mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
mAudioQueue.erase(mAudioQueue.begin());
entry = NULL;
@@ -1081,10 +1083,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();
@@ -1109,6 +1111,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);
@@ -1295,6 +1305,7 @@
if (audio) {
notifyComplete = mNotifyCompleteAudio;
mNotifyCompleteAudio = false;
+ mLastAudioMediaTimeUs = -1;
} else {
notifyComplete = mNotifyCompleteVideo;
mNotifyCompleteVideo = false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 3e65649..58bf121 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -176,7 +176,8 @@
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/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/libstagefright/webm/Android.mk b/media/libstagefright/webm/Android.mk
index bc53c56..7ce436a 100644
--- a/media/libstagefright/webm/Android.mk
+++ b/media/libstagefright/webm/Android.mk
@@ -5,6 +5,7 @@
LOCAL_CFLAGS += -Werror -Wall
LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
LOCAL_SRC_FILES:= EbmlUtil.cpp \
WebmElement.cpp \
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/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();