Merge "A flush of a video decoder connected to a native window must reclaim" into jb-mr2-dev
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 3503aaf..145869e 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -83,7 +83,7 @@
     uint8_t mCryptoKey[16]; // passed in from extractor
     uint32_t mCurrentAuxInfoType;
     uint32_t mCurrentAuxInfoTypeParameter;
-    uint32_t mCurrentDefaultSampleInfoSize;
+    int32_t mCurrentDefaultSampleInfoSize;
     uint32_t mCurrentSampleInfoCount;
     uint32_t mCurrentSampleInfoAllocSize;
     uint8_t* mCurrentSampleInfoSizes;
@@ -320,6 +320,21 @@
     }
 }
 
+static bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
+    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
+        // AMR NB audio is always mono, 8kHz
+        *channels = 1;
+        *rate = 8000;
+        return true;
+    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
+        // AMR WB audio is always mono, 16kHz
+        *channels = 1;
+        *rate = 16000;
+        return true;
+    }
+    return false;
+}
+
 MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
     : mSidxDuration(0),
       mMoofOffset(0),
@@ -443,6 +458,14 @@
     return track->meta;
 }
 
+static void MakeFourCCString(uint32_t x, char *s) {
+    s[0] = x >> 24;
+    s[1] = (x >> 16) & 0xff;
+    s[2] = (x >> 8) & 0xff;
+    s[3] = x & 0xff;
+    s[4] = '\0';
+}
+
 status_t MPEG4Extractor::readMetaData() {
     if (mInitCheck != NO_INIT) {
         return mInitCheck;
@@ -673,14 +696,6 @@
     return UNKNOWN_ERROR;  // Return a dummy error.
 }
 
-static void MakeFourCCString(uint32_t x, char *s) {
-    s[0] = x >> 24;
-    s[1] = (x >> 16) & 0xff;
-    s[2] = (x >> 8) & 0xff;
-    s[3] = x & 0xff;
-    s[4] = '\0';
-}
-
 struct PathAdder {
     PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
         : mPath(path) {
@@ -891,13 +906,19 @@
 
         case FOURCC('f', 'r', 'm', 'a'):
         {
-            int32_t original_fourcc;
+            uint32_t original_fourcc;
             if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
                 return ERROR_IO;
             }
             original_fourcc = ntohl(original_fourcc);
             ALOGV("read original format: %d", original_fourcc);
             mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
+            uint32_t num_channels = 0;
+            uint32_t sample_rate = 0;
+            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
+                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
+                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+            }
             *offset += chunk_size;
             break;
         }
@@ -1134,6 +1155,7 @@
         }
 
         case FOURCC('m', 'p', '4', 'a'):
+        case FOURCC('e', 'n', 'c', 'a'):
         case FOURCC('s', 'a', 'm', 'r'):
         case FOURCC('s', 'a', 'w', 'b'):
         {
@@ -1149,29 +1171,18 @@
             }
 
             uint16_t data_ref_index = U16_AT(&buffer[6]);
-            uint16_t num_channels = U16_AT(&buffer[16]);
+            uint32_t num_channels = U16_AT(&buffer[16]);
 
             uint16_t sample_size = U16_AT(&buffer[18]);
             uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
 
-            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
-                            FourCC2MIME(chunk_type))) {
-                // AMR NB audio is always mono, 8kHz
-                num_channels = 1;
-                sample_rate = 8000;
-            } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
-                               FourCC2MIME(chunk_type))) {
-                // AMR WB audio is always mono, 16kHz
-                num_channels = 1;
-                sample_rate = 16000;
+            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
+                // if the chunk type is enca, we'll get the type from the sinf/frma box later
+                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
             }
-
-#if 0
-            printf("*** coding='%s' %d channels, size %d, rate %d\n",
+            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
                    chunk, num_channels, sample_size, sample_rate);
-#endif
-
-            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
             mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
             mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
 
@@ -2297,6 +2308,7 @@
       mSrcBuffer(NULL) {
 
     mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
+    mDefaultIVSize = 0;
     mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
     uint32_t keytype;
     const void *key;
@@ -2544,13 +2556,17 @@
     if (!mDataSource->getUInt32(offset, &smplcnt)) {
         return ERROR_MALFORMED;
     }
+    mCurrentSampleInfoCount = smplcnt;
     offset += 4;
 
+    if (mCurrentDefaultSampleInfoSize != 0) {
+        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
+        return OK;
+    }
     if (smplcnt > mCurrentSampleInfoAllocSize) {
         mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
         mCurrentSampleInfoAllocSize = smplcnt;
     }
-    mCurrentSampleInfoCount = smplcnt;
 
     mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
     return OK;
@@ -2608,7 +2624,8 @@
     drmoffset += mCurrentMoofOffset;
     int ivlength;
     CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
-    int foo = 1;
+
+    // read CencSampleAuxiliaryDataFormats
     for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
         Sample *smpl = &mCurrentSamples.editItemAt(i);
 
@@ -2619,24 +2636,33 @@
 
         drmoffset += ivlength;
 
-        uint16_t numsubsamples;
-        if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
-            return ERROR_IO;
+        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
+        if (smplinfosize == 0) {
+            smplinfosize = mCurrentSampleInfoSizes[i];
         }
-        drmoffset += 2;
-        for (size_t j = 0; j < numsubsamples; j++) {
-            uint16_t numclear;
-            uint32_t numencrypted;
-            if (!mDataSource->getUInt16(drmoffset, &numclear)) {
+        if (smplinfosize > ivlength) {
+            uint16_t numsubsamples;
+            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
                 return ERROR_IO;
             }
             drmoffset += 2;
-            if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
-                return ERROR_IO;
+            for (size_t j = 0; j < numsubsamples; j++) {
+                uint16_t numclear;
+                uint32_t numencrypted;
+                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
+                    return ERROR_IO;
+                }
+                drmoffset += 2;
+                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
+                    return ERROR_IO;
+                }
+                drmoffset += 4;
+                smpl->clearsizes.add(numclear);
+                smpl->encryptedsizes.add(numencrypted);
             }
-            drmoffset += 4;
-            smpl->clearsizes.add(numclear);
-            smpl->encryptedsizes.add(numencrypted);
+        } else {
+            smpl->clearsizes.add(0);
+            smpl->encryptedsizes.add(smpl->size);
         }
     }
 
@@ -3293,6 +3319,21 @@
         }
     }
 
+    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
+    const sp<MetaData> bufmeta = mBuffer->meta_data();
+    bufmeta->clear();
+    if (smpl->encryptedsizes.size()) {
+        // store clear/encrypted lengths in metadata
+        bufmeta->setData(kKeyPlainSizes, 0,
+                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
+        bufmeta->setData(kKeyEncryptedSizes, 0,
+                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
+        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
+        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
+        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
+        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
+    }
+
     if (!mIsAVC || mWantsNALFragments) {
         if (newBuffer) {
             ssize_t num_bytes_read =
@@ -3308,7 +3349,6 @@
 
             CHECK(mBuffer != NULL);
             mBuffer->set_range(0, size);
-            mBuffer->meta_data()->clear();
             mBuffer->meta_data()->setInt64(
                     kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
 
@@ -3432,7 +3472,6 @@
             mBuffer->set_range(0, dstOffset);
         }
 
-        mBuffer->meta_data()->clear();
         mBuffer->meta_data()->setInt64(
                 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
 
@@ -3445,20 +3484,6 @@
             mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
         }
 
-        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
-        if (smpl->encryptedsizes.size()) {
-            // store clear/encrypted lengths in metadata
-            sp<MetaData> bufmeta = mBuffer->meta_data();
-            bufmeta->setData(kKeyPlainSizes, 0,
-                    smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
-            bufmeta->setData(kKeyEncryptedSizes, 0,
-                    smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
-            bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
-            bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
-            bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
-            bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
-        }
-
         ++mCurrentSampleIndex;
 
         *out = mBuffer;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 0d89c0f..e4e95d2 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -534,6 +534,20 @@
                             // the shutdown complete notification.
 
                             sendErrorReponse = false;
+
+                            if (omxError == OMX_ErrorResourcesLost
+                                    && internalError == DEAD_OBJECT) {
+                                // MediaServer died, there definitely won't
+                                // be a shutdown complete notification after
+                                // all.
+
+                                // note that we're directly going from
+                                // STOPPING->UNINITIALIZED, instead of the
+                                // usual STOPPING->INITIALIZED state.
+                                setState(UNINITIALIZED);
+
+                                (new AMessage)->postReply(mReplyID);
+                            }
                             break;
                         }
 
@@ -1013,8 +1027,16 @@
 
             if (mState != INITIALIZED
                     && mState != CONFIGURED && mState != STARTED) {
+                // We may be in "UNINITIALIZED" state already without the
+                // client being aware of this if media server died while
+                // we were being stopped. The client would assume that
+                // after stop() returned, it would be safe to call release()
+                // and it should be in this case, no harm to allow a release()
+                // if we're already uninitialized.
                 sp<AMessage> response = new AMessage;
-                response->setInt32("err", INVALID_OPERATION);
+                response->setInt32(
+                        "err",
+                        mState == UNINITIALIZED ? OK : INVALID_OPERATION);
 
                 response->postReply(replyID);
                 break;
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 971875f..e7d5e74 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -299,7 +299,9 @@
     OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
 
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_GetExtensionIndex %s failed", name);
+        if (enable) {
+            ALOGE("OMX_GetExtensionIndex %s failed", name);
+        }
 
         return StatusFromOMXError(err);
     }
@@ -378,9 +380,8 @@
 
     OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
     if (err != OMX_ErrorNone) {
-        if (enable) {
-            ALOGE("OMX_GetExtensionIndex %s failed", name);
-        }
+        ALOGE("OMX_GetExtensionIndex %s failed", name);
+
         return StatusFromOMXError(err);
     }
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b3de526..87eb6aa 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -143,6 +143,7 @@
       mMode(AUDIO_MODE_INVALID),
       mBtNrecIsOff(false)
 {
+    getpid_cached = getpid();
     char value[PROPERTY_VALUE_MAX];
     bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
     if (doLog) {
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 6a58852..d15bd04 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -21,8 +21,9 @@
 
 namespace android {
 
-// This optimization assumes mediaserver process doesn't fork, which it doesn't
-const pid_t getpid_cached = getpid();
+// Not valid until initialized by AudioFlinger constructor.  It would have to be
+// re-initialized if the process containing AudioFlinger service forks (which it doesn't).
+pid_t getpid_cached;
 
 bool recordingAllowed() {
     if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index f77ec5b..80cecba 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -18,7 +18,7 @@
 
 namespace android {
 
-extern const pid_t getpid_cached;
+extern pid_t getpid_cached;
 
 bool recordingAllowed();
 bool settingsAllowed();
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index f60749d..683fdf3 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -60,7 +60,9 @@
     static const String16 sDump("android.permission.DUMP");
     if (!(IPCThreadState::self()->getCallingUid() == AID_MEDIA ||
             PermissionCache::checkCallingPermission(sDump))) {
-        fdprintf(fd, "Permission denied.\n");
+        fdprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n",
+                IPCThreadState::self()->getCallingPid(),
+                IPCThreadState::self()->getCallingUid());
         return NO_ERROR;
     }