Merge "added audio policy configuration files for generic target" into oc-dev
diff --git a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
index 0216b8d..6a4f8d5 100644
--- a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
@@ -114,7 +114,7 @@
     memcpy(&keyIdCount, &initData[readPosition], sizeof(keyIdCount));
     keyIdCount = ntohl(keyIdCount);
     readPosition += sizeof(keyIdCount);
-    if (readPosition + (keyIdCount * kKeyIdSize) !=
+    if (readPosition + ((uint64_t)keyIdCount * kKeyIdSize) !=
             initData.size() - sizeof(uint32_t)) {
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
diff --git a/include/ndk/NdkImage.h b/include/ndk/NdkImage.h
index 66005cb..d7443be 100644
--- a/include/ndk/NdkImage.h
+++ b/include/ndk/NdkImage.h
@@ -15,7 +15,7 @@
  */
 
 /**
- * @addtogroup Media Camera
+ * @addtogroup Media
  * @{
  */
 
diff --git a/include/ndk/NdkImageReader.h b/include/ndk/NdkImageReader.h
index e3600c2..59ae507 100644
--- a/include/ndk/NdkImageReader.h
+++ b/include/ndk/NdkImageReader.h
@@ -15,7 +15,7 @@
  */
 
 /**
- * @addtogroup Media Camera
+ * @addtogroup Media
  * @{
  */
 
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index f11f1fa..e1886ac 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -62,14 +62,14 @@
     AAUDIO_ERROR_BASE = -900, // TODO review
     AAUDIO_ERROR_DISCONNECTED,
     AAUDIO_ERROR_ILLEGAL_ARGUMENT,
-    AAUDIO_ERROR_INCOMPATIBLE,
-    AAUDIO_ERROR_INTERNAL, // an underlying API returned an error code
+    // reserved
+    AAUDIO_ERROR_INTERNAL = AAUDIO_ERROR_ILLEGAL_ARGUMENT + 2,
     AAUDIO_ERROR_INVALID_STATE,
-    AAUDIO_ERROR_UNEXPECTED_STATE,
-    AAUDIO_ERROR_UNEXPECTED_VALUE,
-    AAUDIO_ERROR_INVALID_HANDLE,
-    AAUDIO_ERROR_INVALID_QUERY,
-    AAUDIO_ERROR_UNIMPLEMENTED,
+    // reserved
+    // reserved
+    AAUDIO_ERROR_INVALID_HANDLE = AAUDIO_ERROR_INVALID_STATE + 3,
+    // reserved
+    AAUDIO_ERROR_UNIMPLEMENTED = AAUDIO_ERROR_INVALID_HANDLE + 2,
     AAUDIO_ERROR_UNAVAILABLE,
     AAUDIO_ERROR_NO_FREE_HANDLES,
     AAUDIO_ERROR_NO_MEMORY,
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index f71404d..3a827f0 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -480,7 +480,7 @@
         default:
             ALOGE("WARNING - AudioStreamInternal::processCommands() Unrecognized what = %d",
                  (int) message.what);
-            result = AAUDIO_ERROR_UNEXPECTED_VALUE;
+            result = AAUDIO_ERROR_INTERNAL;
             break;
         }
     }
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 04bf2de..76f98fa 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -51,13 +51,13 @@
         AAUDIO_CASE_ENUM(AAUDIO_OK);
         AAUDIO_CASE_ENUM(AAUDIO_ERROR_DISCONNECTED);
         AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INCOMPATIBLE);
+        // reserved
         AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL);
         AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNEXPECTED_STATE);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNEXPECTED_VALUE);
+        // reserved
+        // reserved
         AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_QUERY);
+         // reserved
         AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED);
         AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE);
         AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES);
@@ -114,7 +114,7 @@
 
 AAUDIO_API aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder** builder)
 {
-    AudioStreamBuilder *audioStreamBuilder =  new AudioStreamBuilder();
+    AudioStreamBuilder *audioStreamBuilder =  new(std::nothrow) AudioStreamBuilder();
     if (audioStreamBuilder == nullptr) {
         return AAUDIO_ERROR_NO_MEMORY;
     }
@@ -235,7 +235,7 @@
         delete streamBuilder;
         return AAUDIO_OK;
     }
-    return AAUDIO_ERROR_INVALID_HANDLE;
+    return AAUDIO_ERROR_NULL;
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream* stream)
@@ -247,7 +247,7 @@
         delete audioStream;
         return AAUDIO_OK;
     }
-    return AAUDIO_ERROR_INVALID_HANDLE;
+    return AAUDIO_ERROR_NULL;
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestStart(AAudioStream* stream)
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 03f1a5c..e1e3c55 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -92,7 +92,7 @@
             break;
         default:
             ALOGE("AudioStream::open(): illegal performanceMode %d", mPerformanceMode);
-            return AAUDIO_ERROR_UNEXPECTED_VALUE;
+            return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
     }
 
     return AAUDIO_OK;
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index dfac4fb..dd5e3c0 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -133,7 +133,7 @@
             break;
         default:
             ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
-            return AAUDIO_ERROR_UNEXPECTED_VALUE;
+            return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             break;
     }
     status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 2c7634e..164784d 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -212,10 +212,8 @@
         status = DEAD_OBJECT;
         break;
     case AAUDIO_ERROR_INVALID_STATE:
-    case AAUDIO_ERROR_UNEXPECTED_STATE:
         status = INVALID_OPERATION;
         break;
-    case AAUDIO_ERROR_UNEXPECTED_VALUE:
     case AAUDIO_ERROR_INVALID_RATE:
     case AAUDIO_ERROR_INVALID_FORMAT:
     case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
@@ -229,9 +227,7 @@
         status = UNEXPECTED_NULL;
         break;
     // TODO translate these result codes
-    case AAUDIO_ERROR_INCOMPATIBLE:
     case AAUDIO_ERROR_INTERNAL:
-    case AAUDIO_ERROR_INVALID_QUERY:
     case AAUDIO_ERROR_UNIMPLEMENTED:
     case AAUDIO_ERROR_UNAVAILABLE:
     case AAUDIO_ERROR_NO_FREE_HANDLES:
@@ -265,7 +261,7 @@
             result = AAUDIO_ERROR_NULL;
             break;
         case BAD_VALUE:
-            result = AAUDIO_ERROR_UNEXPECTED_VALUE;
+            result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             break;
     case WOULD_BLOCK:
         result = AAUDIO_ERROR_WOULD_BLOCK;
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 8028969..df6501b 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -148,7 +148,10 @@
                                void           *pParam,
                                uint32_t       *pValueSize,
                                void           *pValue);
-int  Equalizer_setParameter    (EffectContext *pContext, void *pParam, void *pValue);
+int  Equalizer_setParameter    (EffectContext *pContext,
+                               void *pParam,
+                               uint32_t valueSize,
+                               void *pValue);
 int  Equalizer_getParameter    (EffectContext *pContext,
                                 void          *pParam,
                                 uint32_t      *pValueSize,
@@ -2431,6 +2434,13 @@
             }
             break;
         }
+
+        if (*pValueSize < 1) {
+            status = -EINVAL;
+            android_errorWriteLog(0x534e4554, "37536407");
+            break;
+        }
+
         name = (char *)pValue;
         strncpy(name, EqualizerGetPresetName(param2), *pValueSize - 1);
         name[*pValueSize - 1] = 0;
@@ -2468,12 +2478,17 @@
 // Inputs:
 //  pEqualizer    - handle to instance data
 //  pParam        - pointer to parameter
+//  valueSize     - value size
 //  pValue        - pointer to value
+
 //
 // Outputs:
 //
 //----------------------------------------------------------------------------
-int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue){
+int Equalizer_setParameter (EffectContext *pContext,
+                            void *pParam,
+                            uint32_t valueSize,
+                            void *pValue) {
     int status = 0;
     int32_t preset;
     int32_t band;
@@ -2485,6 +2500,10 @@
     //ALOGV("\tEqualizer_setParameter start");
     switch (param) {
     case EQ_PARAM_CUR_PRESET:
+        if (valueSize < sizeof(int16_t)) {
+          status = -EINVAL;
+          break;
+        }
         preset = (int32_t)(*(uint16_t *)pValue);
 
         //ALOGV("\tEqualizer_setParameter() EQ_PARAM_CUR_PRESET %d", preset);
@@ -2495,6 +2514,10 @@
         EqualizerSetPreset(pContext, preset);
         break;
     case EQ_PARAM_BAND_LEVEL:
+        if (valueSize < sizeof(int16_t)) {
+          status = -EINVAL;
+          break;
+        }
         band =  *pParamTemp;
         level = (int32_t)(*(int16_t *)pValue);
         //ALOGV("\tEqualizer_setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
@@ -2510,6 +2533,10 @@
         break;
     case EQ_PARAM_PROPERTIES: {
         //ALOGV("\tEqualizer_setParameter() EQ_PARAM_PROPERTIES");
+        if (valueSize < sizeof(int16_t)) {
+          status = -EINVAL;
+          break;
+        }
         int16_t *p = (int16_t *)pValue;
         if ((int)p[0] >= EqualizerGetNumPresets()) {
             status = -EINVAL;
@@ -2518,6 +2545,13 @@
         if (p[0] >= 0) {
             EqualizerSetPreset(pContext, (int)p[0]);
         } else {
+            if (valueSize < (2 + FIVEBAND_NUMBANDS) * sizeof(int16_t)) {
+              android_errorWriteLog(0x534e4554, "37563371");
+              ALOGE("\tERROR Equalizer_setParameter() EQ_PARAM_PROPERTIES valueSize %d < %d",
+                    (int)valueSize, (int)((2 + FIVEBAND_NUMBANDS) * sizeof(int16_t)));
+              status = -EINVAL;
+              break;
+            }
             if ((int)p[1] != FIVEBAND_NUMBANDS) {
                 status = -EINVAL;
                 break;
@@ -3290,7 +3324,8 @@
 
                 *(int *)pReplyData = android::Equalizer_setParameter(pContext,
                                                                     (void *)p->data,
-                                                                     p->data + p->psize);
+                                                                    p->vsize,
+                                                                    p->data + p->psize);
             }
             if(pContext->EffectType == LVM_VOLUME){
                 //ALOGV("\tVolume_command cmdCode Case: EFFECT_CMD_SET_PARAM start");
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 685065a..b976721 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -1023,9 +1023,12 @@
         return NO_INIT;
     }
 
-    // Only allowing it in player's prepared state
-    if (!(mCurrentState & MEDIA_PLAYER_PREPARED)) {
-        ALOGE("prepareDrm must only be called in the prepared state.");
+    // Only allowed it in player's preparing/prepared state.
+    // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
+    // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
+    // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
+    if (!(mCurrentState & (MEDIA_PLAYER_PREPARING | MEDIA_PLAYER_PREPARED))) {
+        ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
         return INVALID_OPERATION;
     }
 
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 00a1f9c..d83c406 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1979,7 +1979,8 @@
     // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
     notifyFlagsChanged(
             (mIsSecure ? FLAG_SECURE : 0) |
-            (mIsDrmProtected ? FLAG_PROTECTED : 0) |
+            // Setting "protected screen" only for L1: b/38390836
+            (mIsSecure ? FLAG_PROTECTED : 0) |
             FLAG_CAN_PAUSE |
             FLAG_CAN_SEEK_BACKWARD |
             FLAG_CAN_SEEK_FORWARD |
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index b0c6695..4064133 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -222,6 +222,7 @@
     int32_t mFetchTimedTextDataGeneration;
     int64_t mDurationUs;
     bool mAudioIsVorbis;
+    // Secure codec is required.
     bool mIsSecure;
     bool mIsStreaming;
     bool mUIDValid;
@@ -310,7 +311,9 @@
             bool seeking, bool formatChange, media_track_type trackType, Track *track);
 
     // Modular DRM
+    // The source is DRM protected and is prepared for DRM.
     bool mIsDrmProtected;
+    // releaseDrm has been processed.
     bool mIsDrmReleased;
     Vector<String8> mMimes;
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index e7cca27..8ba9c0d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -38,8 +38,8 @@
         FLAG_CAN_SEEK_FORWARD   = 4,  // the "10 sec forward button"
         FLAG_CAN_SEEK           = 8,  // the "seek bar"
         FLAG_DYNAMIC_DURATION   = 16,
-        FLAG_SECURE             = 32,
-        FLAG_PROTECTED          = 64,
+        FLAG_SECURE             = 32, // Secure codec is required.
+        FLAG_PROTECTED          = 64, // The screen needs to be protected (screenshot is disabled).
     };
 
     enum {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 9f1be22..9d6dad3 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1039,7 +1039,10 @@
         array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
     }
     if (portIndex == kPortIndexInput) {
-        mBufferChannel->setInputBufferArray(array);
+        err = mBufferChannel->setInputBufferArray(array);
+        if (err != OK) {
+            return err;
+        }
     } else if (portIndex == kPortIndexOutput) {
         mBufferChannel->setOutputBufferArray(array);
     } else {
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 0d9696f..796d3dc 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -284,7 +284,7 @@
     return dealer;
 }
 
-void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
+status_t ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
     if (hasCryptoOrDescrambler()) {
         size_t totalSize = std::accumulate(
                 array.begin(), array.end(), 0u,
@@ -311,11 +311,15 @@
         if (hasCryptoOrDescrambler()) {
             sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity());
         }
+        if (elem.mBuffer->data() == NULL && sharedEncryptedBuffer == NULL) {
+            return BAD_VALUE;
+        }
         inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
     }
     std::atomic_store(
             &mInputBuffers,
             std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
+    return OK;
 }
 
 void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index f695717..280dd95 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -734,6 +734,9 @@
             // XXX: save indication that it's crypto in some way...
             mAnalyticsItem->setInt32(kCodecCrypto, 1);
         }
+    } else if (mFlags & kFlagIsSecure) {
+        ALOGE("Crypto or descrambler should be given for secure codec");
+        return BAD_VALUE;
     }
 
     // save msg for reset
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp
index 96bbb85..67c31af 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp
@@ -266,10 +266,6 @@
                 return OMX_ErrorUndefined;
             }
 
-            if (formatParams->nIndex > 0) {
-                return OMX_ErrorNoMore;
-            }
-
             if ((formatParams->nPortIndex == 0
                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
                 || (formatParams->nPortIndex == 1
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 44415e2..96e668e 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -305,10 +305,6 @@
                 return OMX_ErrorUndefined;
             }
 
-            if (formatParams->nIndex > 0) {
-                return OMX_ErrorNoMore;
-            }
-
             if ((formatParams->nPortIndex == 0
                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
                 || (formatParams->nPortIndex == 1
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index edf648d..7553153 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -309,7 +309,7 @@
         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
 
-        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+        if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
             inQueue.erase(inQueue.begin());
             inInfo->mOwnedByUs = false;
             notifyEmptyBufferDone(inHeader);
@@ -471,7 +471,7 @@
             mNumSamplesOutput += kNumSamplesPerFrameWB;
         }
 
-        if (inHeader->nFilledLen == 0) {
+        if (inHeader->nFilledLen == 0 && (inHeader->nFlags & OMX_BUFFERFLAG_EOS) == 0) {
             inInfo->mOwnedByUs = false;
             inQueue.erase(inQueue.begin());
             inInfo = NULL;
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index aaa6731..f97c44f 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -226,10 +226,6 @@
                 return OMX_ErrorUndefined;
             }
 
-            if (formatParams->nIndex > 0) {
-                return OMX_ErrorNoMore;
-            }
-
             if ((formatParams->nPortIndex == 0
                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
                 || (formatParams->nPortIndex == 1
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index 9d50c4e..f05f552 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -264,10 +264,6 @@
                 return OMX_ErrorUndefined;
             }
 
-            if (formatParams->nIndex > 0) {
-                return OMX_ErrorNoMore;
-            }
-
             if ((formatParams->nPortIndex == 0
                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
                 || (formatParams->nPortIndex == 1
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 78436f6..248ab6d 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -644,6 +644,7 @@
                 handlePortSettingsChange(&portWillReset, width, height);
                 if (portWillReset) {
                     resetDecoder();
+                    resetPlugin();
                     return;
                 }
             } else if (mUpdateColorAspects) {
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 9f7b590..f7c0429 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -219,7 +219,7 @@
         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
 
-        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+        if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
             inQueue.erase(inQueue.begin());
             inInfo->mOwnedByUs = false;
             notifyEmptyBufferDone(inHeader);
@@ -266,11 +266,15 @@
         outHeader->nFilledLen = inHeader->nFilledLen * sizeof(int16_t);
         outHeader->nFlags = 0;
 
-        inInfo->mOwnedByUs = false;
-        inQueue.erase(inQueue.begin());
-        inInfo = NULL;
-        notifyEmptyBufferDone(inHeader);
-        inHeader = NULL;
+        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+            inHeader->nFilledLen = 0;
+        } else {
+            inInfo->mOwnedByUs = false;
+            inQueue.erase(inQueue.begin());
+            inInfo = NULL;
+            notifyEmptyBufferDone(inHeader);
+            inHeader = NULL;
+        }
 
         outInfo->mOwnedByUs = false;
         outQueue.erase(outQueue.begin());
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
index 04d5a33..11999b4 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
@@ -202,7 +202,7 @@
         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
 
-        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+        if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
             inQueue.erase(inQueue.begin());
             inInfo->mOwnedByUs = false;
             notifyEmptyBufferDone(inHeader);
@@ -246,11 +246,15 @@
         outHeader->nFilledLen = n * sizeof(int16_t);
         outHeader->nFlags = 0;
 
-        inInfo->mOwnedByUs = false;
-        inQueue.erase(inQueue.begin());
-        inInfo = NULL;
-        notifyEmptyBufferDone(inHeader);
-        inHeader = NULL;
+        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+            inHeader->nFilledLen = 0;
+        } else {
+            inInfo->mOwnedByUs = false;
+            inQueue.erase(inQueue.begin());
+            inInfo = NULL;
+            notifyEmptyBufferDone(inHeader);
+            inHeader = NULL;
+        }
 
         outInfo->mOwnedByUs = false;
         outQueue.erase(outQueue.begin());
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index a3fd336..2745087 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -635,6 +635,7 @@
 
                 if (portWillReset) {
                     resetDecoder();
+                    resetPlugin();
                     return;
                 }
             } else if (mUpdateColorAspects) {
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 1dd631a..411a251 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -255,13 +255,28 @@
             mSignalledError = true;
             return;
         }
+
+        // Need to check if header contains new info, e.g., width/height, etc.
+        VopHeaderInfo header_info;
+        uint8_t *bitstreamTmp = bitstream;
+        if (PVDecodeVopHeader(
+                    mHandle, &bitstreamTmp, &timestamp, &tmp,
+                    &header_info, &useExtTimestamp,
+                    outHeader->pBuffer) != PV_TRUE) {
+            ALOGE("failed to decode vop header.");
+
+            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            mSignalledError = true;
+            return;
+        }
+        if (handlePortSettingsChange()) {
+            return;
+        }
+
         // The PV decoder is lying to us, sometimes it'll claim to only have
         // consumed a subset of the buffer when it clearly consumed all of it.
         // ignore whatever it says...
-        if (PVDecodeVideoFrame(
-                    mHandle, &bitstream, &timestamp, &tmp,
-                    &useExtTimestamp,
-                    outHeader->pBuffer) != PV_TRUE) {
+        if (PVDecodeVopBody(mHandle, &tmp) != PV_TRUE) {
             ALOGE("failed to decode video frame.");
 
             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
index 60c79a6..f18f789 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -15,6 +15,8 @@
  * and limitations under the License.
  * -------------------------------------------------------------------
  */
+#include "log/log.h"
+
 #include "mp4dec_lib.h"
 #include "bitstream.h"
 #include "vlc_decode.h"
@@ -1336,8 +1338,7 @@
             }
             tmpvar = BitstreamReadBits16(stream, 9);
 
-            video->displayWidth = (tmpvar + 1) << 2;
-            video->width = (video->displayWidth + 15) & -16;
+            int tmpDisplayWidth = (tmpvar + 1) << 2;
             /* marker bit */
             if (!BitstreamRead1Bits(stream))
             {
@@ -1350,14 +1351,21 @@
                 status = PV_FAIL;
                 goto return_point;
             }
-            video->displayHeight = tmpvar << 2;
-            video->height = (video->displayHeight + 15) & -16;
+            int tmpDisplayHeight = tmpvar << 2;
+            int tmpHeight = (tmpDisplayHeight + 15) & -16;
+            int tmpWidth = (tmpDisplayWidth + 15) & -16;
 
-            if (video->height * video->width > video->size)
+            if (tmpHeight * tmpWidth > video->size)
             {
+                // This is just possibly "b/37079296".
+                ALOGE("b/37079296");
                 status = PV_FAIL;
                 goto return_point;
             }
+            video->displayWidth = tmpDisplayWidth;
+            video->width = tmpWidth;
+            video->displayHeight = tmpDisplayHeight;
+            video->height = tmpHeight;
 
             video->nTotalMB = video->width / MB_SIZE * video->height / MB_SIZE;
 
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index c2b7c8d..7ab8f45 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -773,7 +773,7 @@
             || (size_t)(size + (size >> 1)) > SIZE_MAX / sizeof(PIXEL)) {
         goto CLEAN_UP;
     }
-    video->currVop->yChan = (PIXEL *)M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for currVop Y */
+    video->currVop->allChan = video->currVop->yChan = (PIXEL *)M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for currVop Y */
     if (video->currVop->yChan == NULL) goto CLEAN_UP;
     video->currVop->uChan = video->currVop->yChan + size;/* Memory for currVop U */
     video->currVop->vChan = video->currVop->uChan + (size >> 2);/* Memory for currVop V */
@@ -791,7 +791,7 @@
 
     video->prevBaseVop = (Vop *) M4VENC_MALLOC(sizeof(Vop));         /* Memory for Previous Base Vop */
     if (video->prevBaseVop == NULL) goto CLEAN_UP;
-    video->prevBaseVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for prevBaseVop Y */
+    video->prevBaseVop->allChan = video->prevBaseVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for prevBaseVop Y */
     if (video->prevBaseVop->yChan == NULL) goto CLEAN_UP;
     video->prevBaseVop->uChan = video->prevBaseVop->yChan + size; /* Memory for prevBaseVop U */
     video->prevBaseVop->vChan = video->prevBaseVop->uChan + (size >> 2); /* Memory for prevBaseVop V */
@@ -808,7 +808,7 @@
     {
         video->nextBaseVop = (Vop *) M4VENC_MALLOC(sizeof(Vop));         /* Memory for Next Base Vop */
         if (video->nextBaseVop == NULL) goto CLEAN_UP;
-        video->nextBaseVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for nextBaseVop Y */
+        video->nextBaseVop->allChan = video->nextBaseVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for nextBaseVop Y */
         if (video->nextBaseVop->yChan == NULL) goto CLEAN_UP;
         video->nextBaseVop->uChan = video->nextBaseVop->yChan + size; /* Memory for nextBaseVop U */
         video->nextBaseVop->vChan = video->nextBaseVop->uChan + (size >> 2); /* Memory for nextBaseVop V */
@@ -825,7 +825,7 @@
     {
         video->prevEnhanceVop = (Vop *) M4VENC_MALLOC(sizeof(Vop));      /* Memory for Previous Enhancement Vop */
         if (video->prevEnhanceVop == NULL) goto CLEAN_UP;
-        video->prevEnhanceVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for Previous Ehancement Y */
+        video->prevEnhanceVop->allChan = video->prevEnhanceVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for Previous Ehancement Y */
         if (video->prevEnhanceVop->yChan == NULL) goto CLEAN_UP;
         video->prevEnhanceVop->uChan = video->prevEnhanceVop->yChan + size; /* Memory for Previous Enhancement U */
         video->prevEnhanceVop->vChan = video->prevEnhanceVop->uChan + (size >> 2); /* Memory for Previous Enhancement V */
@@ -1196,39 +1196,35 @@
 
         if (video->currVop)
         {
-            if (video->currVop->yChan)
+            if (video->currVop->allChan)
             {
-                video->currVop->yChan -= offset;
-                M4VENC_FREE(video->currVop->yChan);
+                M4VENC_FREE(video->currVop->allChan);
             }
             M4VENC_FREE(video->currVop);
         }
 
         if (video->nextBaseVop)
         {
-            if (video->nextBaseVop->yChan)
+            if (video->nextBaseVop->allChan)
             {
-                video->nextBaseVop->yChan -= offset;
-                M4VENC_FREE(video->nextBaseVop->yChan);
+                M4VENC_FREE(video->nextBaseVop->allChan);
             }
             M4VENC_FREE(video->nextBaseVop);
         }
 
         if (video->prevBaseVop)
         {
-            if (video->prevBaseVop->yChan)
+            if (video->prevBaseVop->allChan)
             {
-                video->prevBaseVop->yChan -= offset;
-                M4VENC_FREE(video->prevBaseVop->yChan);
+                M4VENC_FREE(video->prevBaseVop->allChan);
             }
             M4VENC_FREE(video->prevBaseVop);
         }
         if (video->prevEnhanceVop)
         {
-            if (video->prevEnhanceVop->yChan)
+            if (video->prevEnhanceVop->allChan)
             {
-                video->prevEnhanceVop->yChan -= offset;
-                M4VENC_FREE(video->prevEnhanceVop->yChan);
+                M4VENC_FREE(video->prevEnhanceVop->allChan);
             }
             M4VENC_FREE(video->prevEnhanceVop);
         }
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h b/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h
index 3bc9421..b05099c 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h
@@ -39,6 +39,7 @@
 
 typedef struct tagVOP
 {
+    PIXEL   *allChan;           /* [yuv]Chan point into this buffer */
     PIXEL   *yChan;             /* The Y component */
     PIXEL   *uChan;             /* The U component */
     PIXEL   *vChan;             /* The V component */
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index ce28faf..8a569c9 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -752,6 +752,7 @@
 
                 if (portWillReset) {
                     resetDecoder();
+                    resetPlugin();
                     return;
                 }
             } else if (mUpdateColorAspects) {
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index 8d69bd5..a5666da 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -137,6 +137,8 @@
     mCodecConfiguration->rc_end_usage = mBitrateControlMode;
     // Disable frame drop - not allowed in MediaCodec now.
     mCodecConfiguration->rc_dropframe_thresh = 0;
+    // Disable lagged encoding.
+    mCodecConfiguration->g_lag_in_frames = 0;
     if (mBitrateControlMode == VPX_CBR) {
         // Disable spatial resizing.
         mCodecConfiguration->rc_resize_allowed = 0;
@@ -157,8 +159,6 @@
         mCodecConfiguration->rc_buf_sz = 1000;
         // Enable error resilience - needed for packet loss.
         mCodecConfiguration->g_error_resilient = 1;
-        // Disable lagged encoding.
-        mCodecConfiguration->g_lag_in_frames = 0;
         // Maximum key frame interval - for CBR boost to 3000
         mCodecConfiguration->kf_max_dist = 3000;
         // Encoder determines optimal key frame placement automatically.
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index 2e44ed7..2ac6ce0 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -430,7 +430,7 @@
         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
 
-        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+        if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
             inQueue.erase(inQueue.begin());
             inInfo->mOwnedByUs = false;
             notifyEmptyBufferDone(inHeader);
@@ -498,11 +498,15 @@
 
         mNumFramesOutput += numFrames;
 
-        inInfo->mOwnedByUs = false;
-        inQueue.erase(inQueue.begin());
-        inInfo = NULL;
-        notifyEmptyBufferDone(inHeader);
-        inHeader = NULL;
+        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+            inHeader->nFilledLen = 0;
+        } else {
+            inInfo->mOwnedByUs = false;
+            inQueue.erase(inQueue.begin());
+            inInfo = NULL;
+            notifyEmptyBufferDone(inHeader);
+            inHeader = NULL;
+        }
 
         outInfo->mOwnedByUs = false;
         outQueue.erase(outQueue.begin());
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 0da2e81..349f1f8 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -87,8 +87,9 @@
      *
      * @param array     Newly allocated buffers. Empty if buffers are
      *                  deallocated.
+     * @return OK if no error.
      */
-    void setInputBufferArray(const std::vector<BufferAndId> &array);
+    status_t setInputBufferArray(const std::vector<BufferAndId> &array);
     /**
      * Set output buffer array.
      *
diff --git a/media/libstagefright/include/RemoteDataSource.h b/media/libstagefright/include/RemoteDataSource.h
index 255b7ae..c91ddfc 100644
--- a/media/libstagefright/include/RemoteDataSource.h
+++ b/media/libstagefright/include/RemoteDataSource.h
@@ -54,6 +54,9 @@
         return mSource->getSize(size);
     }
     virtual void close() {
+        // Protect strong pointer assignments. This also can be called from the binder
+        // clean-up procedure which is running on a separate thread.
+        Mutex::Autolock lock(mCloseLock);
         mSource = nullptr;
         mMemory = nullptr;
     }
@@ -75,6 +78,7 @@
     sp<IMemory> mMemory;
     sp<DataSource> mSource;
     String8 mName;
+    Mutex mCloseLock;
 
     explicit RemoteDataSource(const sp<DataSource> &source) {
         mSource = source;
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 103a3e9..47d80bb 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -827,6 +827,10 @@
         ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, nullptr);
         ALOGV("submitEndOfInputStream_l: buffer submitted, bufferId=%u@%zd", codecBufferId, cbix);
         mEndOfStreamSent = true;
+
+        // no need to hold onto any buffers for frame repeating
+        ++mRepeatLastFrameGeneration;
+        mLatestBuffer.mBuffer.reset();
     }
 }
 
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 409cef7..98a9f54 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -430,10 +430,6 @@
                 return OMX_ErrorBadPortIndex;
             }
 
-            if (formatParams->nIndex != 0) {
-                return OMX_ErrorNoMore;
-            }
-
             if (formatParams->nPortIndex == kInputPortIndex) {
                 if (formatParams->eCompressionFormat != mCodingType
                         || formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 9fe6018..2aa88af 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -551,6 +551,7 @@
         srcVStride = buffer->height;
         // convert stride from pixels to bytes
         if (format != HAL_PIXEL_FORMAT_YV12 &&
+            format != HAL_PIXEL_FORMAT_YCrCb_420_SP &&
             format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
             // TODO do we need to support other formats?
             srcStride *= 4;
@@ -613,26 +614,24 @@
 
     switch (format) {
         case HAL_PIXEL_FORMAT_YV12:  // YCrCb / YVU planar
-            // convert to flex YUV
             ycbcr.y = bits;
             ycbcr.cr = (uint8_t *)bits + srcStride * srcVStride;
             ycbcr.cb = (uint8_t *)ycbcr.cr + (srcStride >> 1) * (srcVStride >> 1);
             ycbcr.chroma_step = 1;
-            ycbcr.cstride = srcVStride >> 1;
-            ycbcr.ystride = srcVStride;
+            ycbcr.cstride = srcStride >> 1;
+            ycbcr.ystride = srcStride;
             ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height);
             break;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // YCrCb / YVU semiplanar, NV21
-            // convert to flex YUV
             ycbcr.y = bits;
             ycbcr.cr = (uint8_t *)bits + srcStride * srcVStride;
             ycbcr.cb = (uint8_t *)ycbcr.cr + 1;
             ycbcr.chroma_step = 2;
-            ycbcr.cstride = srcVStride;
-            ycbcr.ystride = srcVStride;
+            ycbcr.cstride = srcStride;
+            ycbcr.ystride = srcStride;
             ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height);
             break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:  // YCbCr / YUV planar
             ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height);
             break;
         case HAL_PIXEL_FORMAT_RGBX_8888:
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index 9bc69c4..6a5320d 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -25,6 +25,7 @@
 #include <string>
 
 #include <android-base/logging.h>
+#include <utils/misc.h>
 
 // from LOCAL_C_INCLUDES
 #include "IcuUtils.h"
@@ -47,6 +48,13 @@
         20 /* upper limit as percentage of physical RAM */);
 
     signal(SIGPIPE, SIG_IGN);
+
+    //b/62255959: this forces libutis.so to dlopen vendor version of libutils.so
+    //before minijail is on. This is dirty but required since some syscalls such
+    //as pread64 are used by linker but aren't allowed in the minijail. By
+    //calling the function before entering minijail, we can force dlopen.
+    android::report_sysprop_change();
+
     SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
 
     InitializeIcuOrDie();