Merge "Track: Check buffer size"
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 4c292ed..8cf8005 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -13,9 +13,12 @@
         "-Wno-error=deprecated-declarations",
         "-Wall",
     ],
-    shared: {
-      shared_libs: ["libutils", "liblog", "libgui"],
-    },
+    shared_libs: ["libutils", "liblog", "libgui"],
+    header_libs: [
+        "libmedia_headers",
+        "libaudioclient_headers",
+        "libaudio_system_headers",
+    ],
     clang: true,
 }
 
diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp
index 3020136..808c2b5 100644
--- a/media/libmedia/CharacterEncodingDetector.cpp
+++ b/media/libmedia/CharacterEncodingDetector.cpp
@@ -85,6 +85,8 @@
         UErrorCode status = U_ZERO_ERROR;
         UCharsetDetector *csd = ucsdet_open(&status);
         const UCharsetMatch *ucm;
+        bool goodmatch = true;
+        int highest = 0;
 
         // try combined detection of artist/album/title etc.
         char buf[1024];
@@ -116,8 +118,6 @@
             ucsdet_setText(csd, buf, strlen(buf), &status);
             int32_t matches;
             const UCharsetMatch** ucma = ucsdet_detectAll(csd, &matches, &status);
-            bool goodmatch = true;
-            int highest = 0;
             const UCharsetMatch* bestCombinedMatch = getPreferred(buf, strlen(buf),
                     ucma, matches, &goodmatch, &highest);
 
@@ -180,8 +180,24 @@
                     !strcmp(name, "genre") ||
                     !strcmp(name, "album") ||
                     !strcmp(name, "title"))) {
-                // use encoding determined from the combination of artist/album/title etc.
-                enc = combinedenc;
+                if (!goodmatch && highest < 0) {
+                    // Give it one more chance if there is no good match.
+                    ALOGV("Trying to detect %s separately", name);
+                    int32_t matches;
+                    bool goodmatchSingle = true;
+                    int highestSingle = 0;
+                    ucsdet_setText(csd, s, inputLength, &status);
+                    const UCharsetMatch** ucma = ucsdet_detectAll(csd, &matches, &status);
+                    const UCharsetMatch* bestSingleMatch = getPreferred(s, inputLength,
+                            ucma, matches, &goodmatchSingle, &highestSingle);
+                    if (goodmatchSingle || highestSingle > highest)
+                        enc = ucsdet_getName(bestSingleMatch, &status);
+                    else
+                        enc = combinedenc;
+                } else {
+                    // use encoding determined from the combination of artist/album/title etc.
+                    enc = combinedenc;
+                }
             } else {
                 if (isPrintableAscii(s, inputLength)) {
                     enc = "UTF-8";
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index 48ffb01..aa5d1e1 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -18,8 +18,8 @@
 * Documentation: Workflow summary for histogram data processing:
 * For more details on FIFO, please see system/media/audio_utils; doxygen
 * TODO: add this documentation to doxygen once it is further developed
-* 1) writing the data to a buffer
-* onWork
+* 1) Writing buffer period timestamp to the circular buffer
+* onWork()
 *     Called every period length (e.g., 4ms)
 *     Calls LOG_HIST_TS
 * LOG_HIST_TS
@@ -45,12 +45,27 @@
 *     Determines readable buffer section via pointer arithmetic on reader
 *     and writer pointers
 *
-* 2) reading the data from shared memory
+* 2) Writing LOG_HIST_FLUSH event to console when audio is turned on or off
+*    When this event is found when reading from the buffer, all histograms are
+*    printed to the console
+*    TODO: remove this: always write data to another data structure or the console
+* FastMixer::onStateChange()
+*     is called when audio is turned on/off
+*     calls LOG_HIST_FLUSH()
+* LOG_HIST_FLUSH()
+*     calls logHistFlush
+* NBLog::Writer::logHistFlush
+*     records current timestamp to write it to the console
+*     calls log(EVENT_HISTOGRAM_FLUSH)
+*     From here, everything is the same as in 1), resulting in call to fifo write
+*
+* 3) reading the data from shared memory
 * Thread::threadloop()
 *     TODO: add description?
 * NBLog::MergeThread::threadLoop()
 *     calls NBLog::Merger::merge
 * NBLog::Merger::merge
+*     Merges snapshots sorted by timestamp
 *     for each reader in vector of class NamedReader,
 *     callsNamedReader::reader()->getSnapshot
 *     TODO: check whether the rest of this function is relevant
@@ -59,11 +74,13 @@
 *     calls mFifoReader->obtain to find readable data
 *     sets snapshot.begin() and .end() iterators to boundaries of valid entries
 *     moves the fifo reader index to after the last entry read
-*     in this case, the buffer is in shared memory. in (3), the buffer is private
+*     in this case, the buffer is in shared memory. in (4), the buffer is private
 *
-* 3) reading the data from private buffer
+* 4) reading the data from private buffer
 * MediaLogService::dump
-*     calls NBLog::Reader::dump(int) on instance of subclass mergeReader
+*     TODO: when was MediaLogService::dump called?
+*     For each NBLog::Reader in vector NamedReaders (subclass mergeReader):
+*     calls NBLog::Reader::dump(int)
 * NBLog::Reader::dump(int)
 *     calls getSnapshot on the current reader
 *     calls dump(int, size_t, Snapshot)
@@ -74,7 +91,10 @@
 *     (histogram entry) to NBLog::mHists
 *     In the case of EVENT_HISTOGRAM_FLUSH, calls drawHistogram on each element in
 *     the list and erases it
-*     TODO: when do these events occur?
+*     TODO: get rid of the FLUSH, instead add every HISTOGRAM_ENTRY_TS to two
+*     circular buffers: one short-term and one long-term (can add even longer-term
+*     structures in the future). When dump is called, print everything currently
+*     in the buffer.
 * NBLog::drawHistogram
 *     input: timestamp array
 *     buckets this to a histogram and prints
@@ -82,7 +102,7 @@
 */
 
 #define LOG_TAG "NBLog"
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
 
 #include <algorithm>
 #include <climits>
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ab33cea..5bfee24 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -4841,9 +4841,9 @@
                             rect.nTop < 0 ||
                             rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
                             rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
-                            ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
+                            ALOGE("Wrong cropped rect (%d, %d, %u, %u) vs. frame (%u, %u)",
                                     rect.nLeft, rect.nTop,
-                                    rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
+                                    rect.nWidth, rect.nHeight,
                                     videoDef->nFrameWidth, videoDef->nFrameHeight);
                             return BAD_VALUE;
                         }
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index acb2b37..6887120 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -60,7 +60,7 @@
     def.eDir = OMX_DirInput;
     def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = 32 * 1024;
+    def.nBufferSize = 64 * 1024;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
@@ -78,7 +78,7 @@
     def.eDir = OMX_DirOutput;
     def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = 32 * 1024;
+    def.nBufferSize = 64 * 1024;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 98a9f54..920dd18 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -62,6 +62,7 @@
         mCropWidth(width),
         mCropHeight(height),
         mOutputPortSettingsChange(NONE),
+        mUpdateColorAspects(false),
         mMinInputBufferSize(384), // arbitrary, using one uncompressed macroblock
         mMinCompressionRatio(1),  // max input size is normally the output size
         mComponentRole(componentRole),
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b2d0a72..753901f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6926,6 +6926,12 @@
     if (mActiveTracks.size() == 0) {
         dprintf(fd, "  No active record clients\n");
     }
+
+    if (input != nullptr) {
+        dprintf(fd, "  Hal stream dump:\n");
+        (void)input->stream->dump(fd);
+    }
+
     dprintf(fd, "  Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
     dprintf(fd, "  Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
 
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index e03ec66..9bc31b9 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -138,7 +138,8 @@
         mInputBuffer(nullptr),
         mProducer(nullptr),
         mInputProducer(nullptr),
-        mInputProducerSlot(-1) {
+        mInputProducerSlot(-1),
+        mBuffersToDetach(0) {
     // Initialize buffer queue and frame list based on pipeline max depth.
     size_t pipelineMaxDepth = kDefaultMaxPipelineDepth;
     if (client != 0) {
@@ -430,6 +431,11 @@
 void ZslProcessor::notifyInputReleased() {
     Mutex::Autolock l(mInputMutex);
 
+    mBuffersToDetach++;
+    mBuffersToDetachSignal.signal();
+}
+
+void ZslProcessor::doNotifyInputReleasedLocked() {
     assert(nullptr != mInputBuffer.get());
     assert(nullptr != mInputProducer.get());
 
@@ -736,9 +742,18 @@
 }
 
 bool ZslProcessor::threadLoop() {
-    // TODO: remove dependency on thread. For now, shut thread down right
-    // away.
-    return false;
+    Mutex::Autolock l(mInputMutex);
+
+    if (mBuffersToDetach == 0) {
+        status_t res = mBuffersToDetachSignal.waitRelative(mInputMutex, kWaitDuration);
+        if (res == TIMED_OUT) return true;
+    }
+    while (mBuffersToDetach > 0) {
+        doNotifyInputReleasedLocked();
+        mBuffersToDetach--;
+    }
+
+    return true;
 }
 
 void ZslProcessor::dumpZslQueue(int fd) const {
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.h b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
index 6113d58..1db2403 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
@@ -142,6 +142,9 @@
     sp<IGraphicBufferProducer>               mInputProducer;
     int                                      mInputProducerSlot;
 
+    Condition                                mBuffersToDetachSignal;
+    int                                      mBuffersToDetach;
+
     virtual bool threadLoop();
 
     status_t clearZslQueueLocked();
@@ -156,6 +159,7 @@
         nsecs_t* actualTimestamp);
     status_t clearInputRingBufferLocked(nsecs_t* latestTimestamp);
     void notifyInputReleased();
+    void doNotifyInputReleasedLocked();
 
     bool isFixedFocusMode(uint8_t afMode) const;
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4571db8..d6ed3ff 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2360,6 +2360,25 @@
     nsecs_t sensorTimestamp = request.sensorTimestamp;
     nsecs_t shutterTimestamp = request.shutterTimestamp;
 
+    bool skipResultMetadata = false;
+    if (request.requestStatus != OK) {
+        switch (request.requestStatus) {
+            case CAMERA3_MSG_ERROR_DEVICE:
+            case CAMERA3_MSG_ERROR_REQUEST:
+            case CAMERA3_MSG_ERROR_RESULT:
+                skipResultMetadata = true;
+                break;
+            case CAMERA3_MSG_ERROR_BUFFER:
+                //Result metadata should return in this case.
+                skipResultMetadata = false;
+                break;
+            default:
+                SET_ERR("Unknown error message: %d", request.requestStatus);
+                skipResultMetadata = false;
+                break;
+        }
+    }
+
     // Check if it's okay to remove the request from InFlightMap:
     // In the case of a successful request:
     //      all input and output buffers, all result metadata, shutter callback
@@ -2367,7 +2386,7 @@
     // In the case of a unsuccessful request:
     //      all input and output buffers arrived.
     if (request.numBuffersLeft == 0 &&
-            (request.requestStatus != OK ||
+            (skipResultMetadata ||
             (request.haveResultMetadata && shutterTimestamp != 0))) {
         ATRACE_ASYNC_END("frame capture", frameNumber);