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