Merge "NuPlayerRenderer: discard pending kWhatDrainAudioQueue message when AudioSink is opened in callback mode." into mnc-dev
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 71cb194..a57d4cf 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -777,10 +777,13 @@
 
             // If using gralloc or native source input metadata buffers, allocate largest
             // metadata size as we prefer to generate native source metadata, but component
-            // may require gralloc source.
+            // may require gralloc source. For camera source, allocate at least enough
+            // size for native metadata buffers.
             int32_t allottedSize = bufSize;
-            if (portIndex == kPortIndexInput && type > 0) {
+            if (portIndex == kPortIndexInput && type >= kMetadataBufferTypeGrallocSource) {
                 bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata));
+            } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) {
+                bufSize = max(bufSize, (int32_t)sizeof(VideoNativeMetadata));
             }
 
             ALOGV("[%s] Allocating %u buffers of size %d/%d (from %u using %s) on %s port",
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 7e92da8..692667f 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -683,7 +683,7 @@
     }
 
     CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT(
-            *buffer, portIndex, "%u@%p", allottedSize, params->pointer()));
+            *buffer, portIndex, "%u(%zu)@%p", allottedSize, params->size(), params->pointer()));
     return OK;
 }
 
@@ -1024,8 +1024,8 @@
         bufferSource->addCodecBuffer(header);
     }
 
-    CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%u@%p :> %p",
-            allottedSize, params->pointer(), header->pBuffer));
+    CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %u@%p",
+            params->size(), params->pointer(), allottedSize, header->pBuffer));
 
     return OK;
 }
@@ -1087,18 +1087,6 @@
     Mutex::Autolock autoLock(mLock);
 
     OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
-    // rangeLength and rangeOffset must be a subset of the allocated data in the buffer.
-    // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0.
-    if (rangeOffset > header->nAllocLen
-            || rangeLength > header->nAllocLen - rangeOffset) {
-        if (fenceFd >= 0) {
-            ::close(fenceFd);
-        }
-        return BAD_VALUE;
-    }
-    header->nFilledLen = rangeLength;
-    header->nOffset = rangeOffset;
-
     BufferMeta *buffer_meta =
         static_cast<BufferMeta *>(header->pAppPrivate);
     sp<ABuffer> backup = buffer_meta->getBuffer(header, true /* backup */);
@@ -1112,11 +1100,25 @@
                     == kMetadataBufferTypeANWBuffer) {
         VideoNativeMetadata &backupMeta = *(VideoNativeMetadata *)backup->base();
         VideoGrallocMetadata &codecMeta = *(VideoGrallocMetadata *)codec->base();
-        ALOGV("converting ANWB %p to handle %p", backupMeta.pBuffer, backupMeta.pBuffer->handle);
+        CLOG_BUFFER(emptyBuffer, "converting ANWB %p to handle %p",
+                backupMeta.pBuffer, backupMeta.pBuffer->handle);
         codecMeta.pHandle = backupMeta.pBuffer->handle;
         codecMeta.eType = kMetadataBufferTypeGrallocSource;
-        header->nFilledLen = sizeof(codecMeta);
+        header->nFilledLen = rangeLength ? sizeof(codecMeta) : 0;
+        header->nOffset = 0;
     } else {
+        // rangeLength and rangeOffset must be a subset of the allocated data in the buffer.
+        // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0.
+        if (rangeOffset > header->nAllocLen
+                || rangeLength > header->nAllocLen - rangeOffset) {
+            if (fenceFd >= 0) {
+                ::close(fenceFd);
+            }
+            return BAD_VALUE;
+        }
+        header->nFilledLen = rangeLength;
+        header->nOffset = rangeOffset;
+
         buffer_meta->CopyToOMX(header);
     }
 
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index ba47172..78dfbb1 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -11,13 +11,15 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	main_mediaserver.cpp
+	main_mediaserver.cpp \
+	icuutils.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libaudioflinger \
 	libaudiopolicyservice \
 	libcamera_metadata\
 	libcameraservice \
+	libicuuc \
 	libmedialogservice \
 	libresourcemanagerservice \
 	libcutils \
diff --git a/media/mediaserver/IcuUtils.h b/media/mediaserver/IcuUtils.h
new file mode 100644
index 0000000..52fab6d
--- /dev/null
+++ b/media/mediaserver/IcuUtils.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ICU_UTILS_H
+#define ICU_UTILS_H
+
+// Initializes ICU or dies trying. This must be called when the process
+// is single threaded.
+void initializeIcuOrDie();
+
+#endif  // ICU_UTILS_H
+
diff --git a/media/mediaserver/icuutils.cpp b/media/mediaserver/icuutils.cpp
new file mode 100644
index 0000000..4015849
--- /dev/null
+++ b/media/mediaserver/icuutils.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "IcuUtils.h"
+
+#include "unicode/putil.h"
+#include "unicode/uclean.h"
+#include "unicode/utypes.h"
+#include "utils/Log.h"
+
+#include <stdlib.h>
+
+void initializeIcuOrDie() {
+    const char* systemPathPrefix = getenv("ANDROID_ROOT");
+    LOG_ALWAYS_FATAL_IF(systemPathPrefix == NULL, "ANDROID_ROOT environment variable not set");
+
+    char buf[256];
+    const int num_written = snprintf(buf, sizeof(buf), "%s/usr/icu/", systemPathPrefix);
+    LOG_ALWAYS_FATAL_IF((num_written < 0 || static_cast<size_t>(num_written) >= sizeof(buf)),
+            "Unable to construct ICU path.");
+
+    u_setDataDirectory(buf);
+    UErrorCode status = U_ZERO_ERROR;
+
+    // u_setDataDirectory doesn't try doing anything with the directory we gave
+    // it, so we'll have to call u_init to make sure it was successful.
+    u_init(&status);
+    LOG_ALWAYS_FATAL_IF(!U_SUCCESS(status), "Failed to initialize ICU %s", u_errorName(status));
+}
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 06b3c6e..27a40b2 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -31,6 +31,7 @@
 // from LOCAL_C_INCLUDES
 #include "AudioFlinger.h"
 #include "CameraService.h"
+#include "IcuUtils.h"
 #include "MediaLogService.h"
 #include "MediaPlayerService.h"
 #include "ResourceManagerService.h"
@@ -124,6 +125,7 @@
             prctl(PR_SET_PDEATHSIG, SIGKILL);   // if parent media.log dies before me, kill me also
             setpgid(0, 0);                      // but if I die first, don't kill my parent
         }
+        initializeIcuOrDie();
         sp<ProcessState> proc(ProcessState::self());
         sp<IServiceManager> sm = defaultServiceManager();
         ALOGI("ServiceManager: %p", sm.get());