am a4ce14aa: am 44a63fa2: am d72a03bc: am dddf932f: am 41de4ba1: am cf69487d: am 6f80b09f: am 252a8c09: am 0f3ab16c: am af7e33f6: libstagefright: check overflow before memory allocation in OMXCodec.cpp
* commit 'a4ce14aaf0ef7d8bd788c02908429ff86b7b1d47':
libstagefright: check overflow before memory allocation in OMXCodec.cpp
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/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index bde35f2..7387a79 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -653,6 +653,7 @@
CHECK_INTERFACE(IMediaPlayer, data, reply);
struct sockaddr_in endpoint;
+ memset(&endpoint, 0, sizeof(endpoint));
int amt = data.readInt32();
if (amt == sizeof(endpoint)) {
data.read(&endpoint, sizeof(struct sockaddr_in));
@@ -667,6 +668,7 @@
CHECK_INTERFACE(IMediaPlayer, data, reply);
struct sockaddr_in endpoint;
+ memset(&endpoint, 0, sizeof(endpoint));
status_t res = getRetransmitEndpoint(&endpoint);
reply->writeInt32(res);
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/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 3b44bae..f738e51 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..4e20b1a 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -525,16 +525,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);
}
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 3eafd6f..b84a245 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -430,8 +430,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);
@@ -682,7 +683,6 @@
return result;
}
-
// 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,26 +698,35 @@
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);
+
Mutex::Autolock autoLock(mMutex);
- bool result = false;
mRequest.reset();
mRequest.setParameter(1, handle);
- if (sendRequest(MTP_OPERATION_GET_OBJECT)
- && mData.readDataHeader(mRequestIn1)) {
+ if (sendRequest(MTP_OPERATION_GET_OBJECT) && mData.readDataHeader(mRequestIn1)) {
uint32_t length = mData.getContainerLength();
- if (length < MTP_CONTAINER_HEADER_SIZE)
- goto fail;
+ if (length < MTP_CONTAINER_HEADER_SIZE) {
+ ALOGE("Invalid container length.");
+ return false;
+ }
length -= MTP_CONTAINER_HEADER_SIZE;
uint32_t remaining = length;
+ bool writingError = false;
int initialDataLength = 0;
void* initialData = mData.getData(initialDataLength);
if (initialData) {
if (initialDataLength > 0) {
if (write(fd, initialData, initialDataLength) != initialDataLength) {
- free(initialData);
- goto fail;
+ ALOGE("Failed to write initial data.");
+ writingError = true;
}
remaining -= initialDataLength;
}
@@ -738,29 +747,27 @@
req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
if (mData.readDataAsync(req)) {
ALOGE("readDataAsync failed");
- goto fail;
+ return false;
}
} else {
req = NULL;
}
- if (writeBuffer) {
+ if (writeBuffer && !writingError) {
// 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;
+ writingError = true;
}
- writeBuffer = NULL;
}
+ writeBuffer = NULL;
// wait for read to complete
if (req) {
int read = mData.readDataWait(mDevice);
- if (read < 0)
- goto fail;
+ if (read < 0) {
+ ALOGE("readDataWait failed.");
+ return false;
+ }
if (read > 0) {
writeBuffer = req->buffer;
@@ -774,13 +781,10 @@
}
MtpResponseCode response = readResponse();
- if (response == MTP_RESPONSE_OK)
- result = true;
+ return response == MTP_RESPONSE_OK && !writingError;
}
-fail:
- ::close(fd);
- return result;
+ return false;
}
bool MtpDevice::sendRequest(MtpOperationCode operation) {
@@ -800,7 +804,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..ef29f1b 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -101,6 +101,7 @@
size_t objectSize, void* clientData);
bool readObject(MtpObjectHandle handle, const char* destPath, int group,
int perm);
+ bool readObject(MtpObjectHandle handle, int fd);
private:
bool sendRequest(MtpOperationCode operation);
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();