Merge "Don't process objects with empty name" into nyc-mr1-dev
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 0c310c5..91f9fc7 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -25,6 +25,7 @@
#include <time.h>
#include <math.h>
#include <audio_effects/effect_visualizer.h>
+#include <cutils/log.h>
extern "C" {
@@ -599,6 +600,14 @@
} break;
case VISUALIZER_CMD_MEASURE: {
+ if (pReplyData == NULL || replySize == NULL ||
+ *replySize < (sizeof(int32_t) * MEASUREMENT_COUNT)) {
+ ALOGV("VISUALIZER_CMD_MEASURE() error *replySize %" PRIu32
+ " < (sizeof(int32_t) * MEASUREMENT_COUNT) %" PRIu32, *replySize,
+ sizeof(int32_t) * MEASUREMENT_COUNT);
+ android_errorWriteLog(0x534e4554, "30229821");
+ return -EINVAL;
+ }
uint16_t peakU16 = 0;
float sumRmsSquared = 0.0f;
uint8_t nbValidMeasurements = 0;
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index 26dd2c9..302e6ee 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -150,10 +150,10 @@
if (isCryptoError(result)) {
errorDetailMsg->setTo(reply.readCString());
- }
-
- if (dstType == kDestinationTypeVmPointer && result >= 0) {
- reply.read(dstPtr, result);
+ } else if (dstType == kDestinationTypeVmPointer) {
+ // For the non-secure case, copy the decrypted
+ // data from shared memory to its final destination
+ memcpy(dstPtr, sharedBuffer->pointer(), result);
}
return result;
@@ -369,7 +369,11 @@
if (dstType == kDestinationTypeVmPointer) {
if (result >= 0) {
CHECK_LE(result, static_cast<ssize_t>(totalSize));
- reply->write(dstPtr, result);
+ // For the non-secure case, pass the decrypted
+ // data back via the shared buffer rather than
+ // copying it separately over binder to avoid
+ // binder's 1MB limit.
+ memcpy(sharedBuffer->pointer(), dstPtr, result);
}
free(dstPtr);
dstPtr = NULL;
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index 5289c5f..595bad9 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -412,11 +412,11 @@
reply->writeInt32(offset);
reply->writeInt32(length);
buf->meta_data()->writeToParcel(*reply);
- if (transferBuf == buf) {
- buf->addRemoteRefcount(1);
- if (!supportNonblockingRead()) {
- maxNumBuffers = 0; // stop readMultiple with one shared buffer.
- }
+ transferBuf->addRemoteRefcount(1);
+ if (transferBuf != buf) {
+ transferBuf->release(); // release local ref
+ } else if (!supportNonblockingRead()) {
+ maxNumBuffers = 0; // stop readMultiple with one shared buffer.
}
} else {
ALOGV_IF(buf->mMemory != nullptr,
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 8ebb355..1090a83 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -775,31 +775,35 @@
// mark the last page as inaccessible, to avoid exploitation
// of codecs that access past the end of the allocation because
// they didn't check the size
- mprotect((char*)params + allocSize - pageSize, pageSize, PROT_NONE);
- switch (code) {
- case GET_PARAMETER:
- err = getParameter(node, index, params, size);
- break;
- case SET_PARAMETER:
- err = setParameter(node, index, params, size);
- break;
- case GET_CONFIG:
- err = getConfig(node, index, params, size);
- break;
- case SET_CONFIG:
- err = setConfig(node, index, params, size);
- break;
- case SET_INTERNAL_OPTION:
- {
- InternalOptionType type =
- (InternalOptionType)data.readInt32();
+ if (mprotect((char*)params + allocSize - pageSize, pageSize,
+ PROT_NONE) != 0) {
+ ALOGE("mprotect failed: %s", strerror(errno));
+ } else {
+ switch (code) {
+ case GET_PARAMETER:
+ err = getParameter(node, index, params, size);
+ break;
+ case SET_PARAMETER:
+ err = setParameter(node, index, params, size);
+ break;
+ case GET_CONFIG:
+ err = getConfig(node, index, params, size);
+ break;
+ case SET_CONFIG:
+ err = setConfig(node, index, params, size);
+ break;
+ case SET_INTERNAL_OPTION:
+ {
+ InternalOptionType type =
+ (InternalOptionType)data.readInt32();
- err = setInternalOption(node, index, type, params, size);
- break;
+ err = setInternalOption(node, index, type, params, size);
+ break;
+ }
+
+ default:
+ TRESPASS();
}
-
- default:
- TRESPASS();
}
}
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 7cb568d..0ce7a5e 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -55,6 +55,10 @@
enum {
// max track header chunk to return
kMaxTrackHeaderSize = 32,
+
+ // maximum size of an atom. Some atoms can be bigger according to the spec,
+ // but we only allow up to this size.
+ kMaxAtomSize = 64 * 1024 * 1024,
};
class MPEG4Source : public MediaSource {
@@ -880,6 +884,13 @@
ALOGE("b/23540914");
return ERROR_MALFORMED;
}
+ if (chunk_type != FOURCC('m', 'd', 'a', 't') && chunk_data_size > kMaxAtomSize) {
+ char errMsg[100];
+ sprintf(errMsg, "%s atom has size %" PRId64, chunk, chunk_data_size);
+ ALOGE("%s (b/28615448)", errMsg);
+ android_errorWriteWithInfoLog(0x534e4554, "28615448", -1, errMsg, strlen(errMsg));
+ return ERROR_MALFORMED;
+ }
if (chunk_type != FOURCC('c', 'p', 'r', 't')
&& chunk_type != FOURCC('c', 'o', 'v', 'r')
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index f84f484..5e96c2b 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2481,12 +2481,16 @@
ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
mOwner->mMaxFileSizeLimitBytes);
mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+ copy->release();
+ mSource->stop();
break;
}
if (mOwner->exceedsFileDurationLimit()) {
ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
mOwner->mMaxFileDurationLimitUs);
mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
+ copy->release();
+ mSource->stop();
break;
}
@@ -2507,6 +2511,7 @@
int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
copy->release();
+ mSource->stop();
mIsMalformed = true;
break;
}
@@ -2514,6 +2519,7 @@
int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
copy->release();
+ mSource->stop();
mIsMalformed = true;
break;
}
@@ -2525,6 +2531,7 @@
timestampUs -= previousPausedDurationUs;
if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
copy->release();
+ mSource->stop();
mIsMalformed = true;
break;
}
@@ -2553,6 +2560,7 @@
timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
copy->release();
+ mSource->stop();
mIsMalformed = true;
break;
}
@@ -2566,6 +2574,7 @@
(cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
copy->release();
+ mSource->stop();
mIsMalformed = true;
break;
}
@@ -2609,6 +2618,7 @@
if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
copy->release();
+ mSource->stop();
mIsMalformed = true;
break;
}
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index ad7b6fd..54c9fa3 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -94,8 +94,6 @@
+ mFirstChunk;
if (!mInitialized || chunk != mCurrentChunkIndex) {
- mCurrentChunkIndex = chunk;
-
status_t err;
if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) {
ALOGE("getChunkOffset return error");
@@ -106,18 +104,21 @@
uint32_t firstChunkSampleIndex =
mFirstChunkSampleIndex
- + mSamplesPerChunk * (mCurrentChunkIndex - mFirstChunk);
+ + mSamplesPerChunk * (chunk - mFirstChunk);
for (uint32_t i = 0; i < mSamplesPerChunk; ++i) {
size_t sampleSize;
if ((err = getSampleSizeDirect(
firstChunkSampleIndex + i, &sampleSize)) != OK) {
ALOGE("getSampleSizeDirect return error");
+ mCurrentChunkSampleSizes.clear();
return err;
}
mCurrentChunkSampleSizes.push(sampleSize);
}
+
+ mCurrentChunkIndex = chunk;
}
uint32_t chunkRelativeSampleIndex =
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 60ef662..568837a 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -186,10 +186,6 @@
break;
}
- if (img == NULL) {
- ALOGE("error pushing blank frames: lock returned NULL buffer");
- break;
- }
*img = 0;
err = buf->unlock();
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index e9ed570..5f903a9 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -1310,7 +1310,6 @@
}
CHECK_EQ(header->pAppPrivate, buffer_meta);
- memset(header->pBuffer, 0, header->nAllocLen);
*buffer = makeBufferID(header);
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index b0780a4..93f7ce5 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -412,6 +412,7 @@
}
ftDump->mUnderruns = underruns;
ftDump->mFramesReady = framesReady;
+ ftDump->mFramesWritten = trackFramesWritten;
}
if (anyEnabledTracks) {
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/FastMixerDumpState.cpp
index 2326e2a..6475f22 100644
--- a/services/audioflinger/FastMixerDumpState.cpp
+++ b/services/audioflinger/FastMixerDumpState.cpp
@@ -168,7 +168,7 @@
uint32_t trackMask = mTrackMask;
dprintf(fd, " Fast tracks: sMaxFastTracks=%u activeMask=%#x\n",
FastMixerState::sMaxFastTracks, trackMask);
- dprintf(fd, " Index Active Full Partial Empty Recent Ready\n");
+ dprintf(fd, " Index Active Full Partial Empty Recent Ready Written\n");
for (uint32_t i = 0; i < FastMixerState::sMaxFastTracks; ++i, trackMask >>= 1) {
bool isActive = trackMask & 1;
const FastTrackDump *ftDump = &mTracks[i];
@@ -188,11 +188,13 @@
mostRecent = "?";
break;
}
- dprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no",
+ dprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu %10lld\n",
+ i, isActive ? "yes" : "no",
(underruns.mBitFields.mFull) & UNDERRUN_MASK,
(underruns.mBitFields.mPartial) & UNDERRUN_MASK,
(underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
- mostRecent, ftDump->mFramesReady);
+ mostRecent, ftDump->mFramesReady,
+ (long long)ftDump->mFramesWritten);
}
}
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/FastMixerDumpState.h
index ac15e7c..301c5b1 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/FastMixerDumpState.h
@@ -57,6 +57,7 @@
/*virtual*/ ~FastTrackDump() { }
FastTrackUnderruns mUnderruns;
size_t mFramesReady; // most recent value only; no long-term statistics kept
+ int64_t mFramesWritten; // last value from track
};
struct FastMixerDumpState : FastThreadDumpState {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index a91fc26..897873b 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1826,6 +1826,15 @@
audio_output_flags_t flags = output != NULL ? output->flags : AUDIO_OUTPUT_FLAG_NONE;
String8 flagsAsString = outputFlagsToString(flags);
dprintf(fd, " AudioStreamOut: %p flags %#x (%s)\n", output, flags, flagsAsString.string());
+ dprintf(fd, " Frames written: %lld\n", (long long)mFramesWritten);
+ dprintf(fd, " Suspended frames: %lld\n", (long long)mSuspendedFrames);
+ if (mPipeSink.get() != nullptr) {
+ dprintf(fd, " PipeSink frames written: %lld\n", (long long)mPipeSink->framesWritten());
+ }
+ if (output != nullptr) {
+ dprintf(fd, " Hal stream dump:\n");
+ (void)output->stream->common.dump(&output->stream->common, fd);
+ }
}
// Thread virtuals
@@ -4588,10 +4597,25 @@
return mixerStatus;
}
+// trackCountForUid_l() must be called with ThreadBase::mLock held
+uint32_t AudioFlinger::PlaybackThread::trackCountForUid_l(uid_t uid)
+{
+ uint32_t trackCount = 0;
+ for (size_t i = 0; i < mTracks.size() ; i++) {
+ if (mTracks[i]->uid() == (int)uid) {
+ trackCount++;
+ }
+ }
+ return trackCount;
+}
+
// getTrackName_l() must be called with ThreadBase::mLock held
int AudioFlinger::MixerThread::getTrackName_l(audio_channel_mask_t channelMask,
- audio_format_t format, audio_session_t sessionId)
+ audio_format_t format, audio_session_t sessionId, uid_t uid)
{
+ if (trackCountForUid_l(uid) > (PlaybackThread::kMaxTracksPerUid - 1)) {
+ return -1;
+ }
return mAudioMixer->getTrackName(channelMask, format, sessionId);
}
@@ -4696,7 +4720,7 @@
mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
for (size_t i = 0; i < mTracks.size() ; i++) {
int name = getTrackName_l(mTracks[i]->mChannelMask,
- mTracks[i]->mFormat, mTracks[i]->mSessionId);
+ mTracks[i]->mFormat, mTracks[i]->mSessionId, mTracks[i]->uid());
if (name < 0) {
break;
}
@@ -5141,8 +5165,11 @@
// getTrackName_l() must be called with ThreadBase::mLock held
int AudioFlinger::DirectOutputThread::getTrackName_l(audio_channel_mask_t channelMask __unused,
- audio_format_t format __unused, audio_session_t sessionId __unused)
+ audio_format_t format __unused, audio_session_t sessionId __unused, uid_t uid)
{
+ if (trackCountForUid_l(uid) > (PlaybackThread::kMaxTracksPerUid - 1)) {
+ return -1;
+ }
return 0;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 1d5d3c8..f353f3b 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -506,6 +506,8 @@
static const int8_t kMaxTrackRetriesOffload = 20;
static const int8_t kMaxTrackStartupRetriesOffload = 100;
static const int8_t kMaxTrackStopRetriesOffload = 2;
+ // 14 tracks max per client allows for 2 misbehaving application leaving 4 available tracks.
+ static const uint32_t kMaxTracksPerUid = 14;
PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
@@ -736,8 +738,8 @@
// Allocate a track name for a given channel mask.
// Returns name >= 0 if successful, -1 on failure.
- virtual int getTrackName_l(audio_channel_mask_t channelMask,
- audio_format_t format, audio_session_t sessionId) = 0;
+ virtual int getTrackName_l(audio_channel_mask_t channelMask, audio_format_t format,
+ audio_session_t sessionId, uid_t uid) = 0;
virtual void deleteTrackName_l(int name) = 0;
// Time to sleep between cycles when:
@@ -767,6 +769,8 @@
&& mHwSupportsPause
&& (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
+ uint32_t trackCountForUid_l(uid_t uid);
+
private:
friend class AudioFlinger; // for numerous
@@ -889,8 +893,8 @@
protected:
virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
- virtual int getTrackName_l(audio_channel_mask_t channelMask,
- audio_format_t format, audio_session_t sessionId);
+ virtual int getTrackName_l(audio_channel_mask_t channelMask, audio_format_t format,
+ audio_session_t sessionId, uid_t uid);
virtual void deleteTrackName_l(int name);
virtual uint32_t idleSleepTimeUs() const;
virtual uint32_t suspendSleepTimeUs() const;
@@ -969,8 +973,8 @@
virtual void flushHw_l();
protected:
- virtual int getTrackName_l(audio_channel_mask_t channelMask,
- audio_format_t format, audio_session_t sessionId);
+ virtual int getTrackName_l(audio_channel_mask_t channelMask, audio_format_t format,
+ audio_session_t sessionId, uid_t uid);
virtual void deleteTrackName_l(int name);
virtual uint32_t activeSleepTimeUs() const;
virtual uint32_t idleSleepTimeUs() const;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 3cca054..ba6e6e5 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -388,7 +388,7 @@
}
mServerProxy = mAudioTrackServerProxy;
- mName = thread->getTrackName_l(channelMask, format, sessionId);
+ mName = thread->getTrackName_l(channelMask, format, sessionId, uid);
if (mName < 0) {
ALOGE("no more track names available");
return;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 9095cde..cc76ce1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1903,19 +1903,21 @@
continue;
}
routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
- audio_devices_t curStreamDevice = getDeviceForStrategy(curStrategy, true /*fromCache*/);
- if ((curStreamDevice & device) == 0) {
+ audio_devices_t curStreamDevice = getDeviceForStrategy(curStrategy, false /*fromCache*/);
+ if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) &&
+ ((curStreamDevice & device) == 0)) {
continue;
}
- bool applyDefault = false;
+ bool applyVolume;
if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
curStreamDevice |= device;
- } else if (!mVolumeCurves->hasVolumeIndexForDevice(
- stream, Volume::getDeviceForVolume(curStreamDevice))) {
- applyDefault = true;
+ applyVolume = (curDevice & curStreamDevice) != 0;
+ } else {
+ applyVolume = !mVolumeCurves->hasVolumeIndexForDevice(
+ stream, Volume::getDeviceForVolume(curStreamDevice));
}
- if (applyDefault || ((curDevice & curStreamDevice) != 0)) {
+ if (applyVolume) {
//FIXME: workaround for truncated touch sounds
// delayed volume change for system stream to be removed when the problem is
// handled by system UI