Merge "Fix uncertainty of one normal mix buffer in AudioTrack::getTimestamp" into lmp-dev
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index fe258ae..66edf45 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2804,6 +2804,7 @@
 
         // create a MonoPipe to connect our submix to FastMixer
         NBAIO_Format format = mOutputSink->format();
+        NBAIO_Format origformat = format;
         // adjust format to match that of the Fast Mixer
         format.mFormat = fastMixerFormat;
         format.mFrameSize = audio_bytes_per_sample(format.mFormat) * format.mChannelCount;
@@ -2823,14 +2824,15 @@
 #ifdef TEE_SINK
         if (mTeeSinkOutputEnabled) {
             // create a Pipe to archive a copy of FastMixer's output for dumpsys
-            Pipe *teeSink = new Pipe(mTeeSinkOutputFrames, format);
+            Pipe *teeSink = new Pipe(mTeeSinkOutputFrames, origformat);
+            const NBAIO_Format offers2[1] = {origformat};
             numCounterOffers = 0;
-            index = teeSink->negotiate(offers, 1, NULL, numCounterOffers);
+            index = teeSink->negotiate(offers2, 1, NULL, numCounterOffers);
             ALOG_ASSERT(index == 0);
             mTeeSink = teeSink;
             PipeReader *teeSource = new PipeReader(*teeSink);
             numCounterOffers = 0;
-            index = teeSource->negotiate(offers, 1, NULL, numCounterOffers);
+            index = teeSource->negotiate(offers2, 1, NULL, numCounterOffers);
             ALOG_ASSERT(index == 0);
             mTeeSource = teeSource;
         }
@@ -4053,6 +4055,9 @@
                         track->mState = TrackBase::STOPPED;
                     }
                     if (track->isStopped()) {
+                        if (track->mState == TrackBase::FLUSHED) {
+                            flushHw_l();
+                        }
                         track->reset();
                     }
                     tracksToRemove->add(track);
@@ -4225,6 +4230,12 @@
     }
 }
 
+void AudioFlinger::DirectOutputThread::flushHw_l()
+{
+    if (mOutput->stream->flush != NULL)
+        mOutput->stream->flush(mOutput->stream);
+}
+
 // ----------------------------------------------------------------------------
 
 AudioFlinger::AsyncCallbackThread::AsyncCallbackThread(
@@ -4592,7 +4603,7 @@
 
 void AudioFlinger::OffloadThread::flushHw_l()
 {
-    mOutput->stream->flush(mOutput->stream);
+    DirectOutputThread::flushHw_l();
     // Flush anything still waiting in the mixbuffer
     mCurrentWriteLength = 0;
     mBytesRemaining = 0;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index cda8095..7d3b854 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -895,6 +895,7 @@
 
     virtual     bool        checkForNewParameter_l(const String8& keyValuePair,
                                                    status_t& status);
+    virtual     void        flushHw_l();
 
 protected:
     virtual     int         getTrackName_l(audio_channel_mask_t channelMask,
@@ -930,6 +931,7 @@
     OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
                         audio_io_handle_t id, uint32_t device);
     virtual                 ~OffloadThread() {};
+    virtual     void        flushHw_l();
 
 protected:
     // threadLoop snippets
@@ -942,9 +944,6 @@
     virtual     void        onAddNewTrack_l();
 
 private:
-                void        flushHw_l();
-
-private:
     bool        mHwPaused;
     bool        mFlushPending;
     size_t      mPausedWriteLength;     // length in bytes of write interrupted by pause
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 8c2bee4..b2d53cf 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -824,6 +824,10 @@
             // remove from active track list, reset(), and trigger presentation complete
             if (playbackThread->mActiveTracks.indexOf(this) < 0) {
                 reset();
+                if (thread->type() == ThreadBase::DIRECT) {
+                    DirectOutputThread *t = (DirectOutputThread *)playbackThread;
+                    t->flushHw_l();
+                }
             }
         }
         // Prevent flush being lost if the track is flushed and then resumed
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index d0b990f..536987a 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -930,7 +930,9 @@
     sp<IOProfile> profile;
 
     // skip direct output selection if the request can obviously be attached to a mixed output
-    if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE &&
+    // and not explicitly requested
+    if (((flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
+            audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE &&
             audio_channel_count_from_out_mask(channelMask) <= 2) {
         goto non_direct_output;
     }
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 48ec730..3610362 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -1049,32 +1049,35 @@
         }
     }
 
-    if (mZslProcessor->getStreamId() != NO_STREAM) {
-        ALOGV("%s: Camera %d: Clearing out zsl stream before "
-                "creating recording stream", __FUNCTION__, mCameraId);
-        res = mStreamingProcessor->stopStream();
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Can't stop streaming to delete callback stream",
-                    __FUNCTION__, mCameraId);
-            return res;
-        }
-        res = mDevice->waitUntilDrained();
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
-                    __FUNCTION__, mCameraId, strerror(-res), res);
-        }
-        res = mZslProcessor->clearZslQueue();
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Can't clear zsl queue",
-                    __FUNCTION__, mCameraId);
-            return res;
-        }
-        res = mZslProcessor->deleteStream();
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Unable to delete zsl stream before "
-                    "record: %s (%d)", __FUNCTION__, mCameraId,
-                    strerror(-res), res);
-            return res;
+    // On current HALs, clean up ZSL before transitioning into recording
+    if (mDeviceVersion != CAMERA_DEVICE_API_VERSION_2_0) {
+        if (mZslProcessor->getStreamId() != NO_STREAM) {
+            ALOGV("%s: Camera %d: Clearing out zsl stream before "
+                    "creating recording stream", __FUNCTION__, mCameraId);
+            res = mStreamingProcessor->stopStream();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Can't stop streaming to delete callback stream",
+                        __FUNCTION__, mCameraId);
+                return res;
+            }
+            res = mDevice->waitUntilDrained();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+                        __FUNCTION__, mCameraId, strerror(-res), res);
+            }
+            res = mZslProcessor->clearZslQueue();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Can't clear zsl queue",
+                        __FUNCTION__, mCameraId);
+                return res;
+            }
+            res = mZslProcessor->deleteStream();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to delete zsl stream before "
+                        "record: %s (%d)", __FUNCTION__, mCameraId,
+                        strerror(-res), res);
+                return res;
+            }
         }
     }
 
@@ -1082,34 +1085,53 @@
     // and we can't fail record start without stagefright asserting.
     params.previewCallbackFlags = 0;
 
-    bool recordingStreamNeedsUpdate;
-    res = mStreamingProcessor->recordingStreamNeedsUpdate(params, &recordingStreamNeedsUpdate);
-    if (res != OK) {
-        ALOGE("%s: Camera %d: Can't query recording stream",
-                __FUNCTION__, mCameraId);
-        return res;
-    }
-
-    if (recordingStreamNeedsUpdate) {
-        // Need to stop stream here so updateProcessorStream won't trigger configureStream
-        // Right now camera device cannot handle configureStream failure gracefully
-        // when device is streaming
-        res = mStreamingProcessor->stopStream();
+    if (mDeviceVersion != CAMERA_DEVICE_API_VERSION_2_0) {
+        // For newer devices, may need to reconfigure video snapshot JPEG sizes
+        // during recording startup, so need a more complex sequence here to
+        // ensure an early stream reconfiguration doesn't happen
+        bool recordingStreamNeedsUpdate;
+        res = mStreamingProcessor->recordingStreamNeedsUpdate(params, &recordingStreamNeedsUpdate);
         if (res != OK) {
-            ALOGE("%s: Camera %d: Can't stop streaming to update record stream",
+            ALOGE("%s: Camera %d: Can't query recording stream",
                     __FUNCTION__, mCameraId);
             return res;
         }
-        res = mDevice->waitUntilDrained();
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
-                    __FUNCTION__, mCameraId, strerror(-res), res);
+
+        if (recordingStreamNeedsUpdate) {
+            // Need to stop stream here so updateProcessorStream won't trigger configureStream
+            // Right now camera device cannot handle configureStream failure gracefully
+            // when device is streaming
+            res = mStreamingProcessor->stopStream();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Can't stop streaming to update record "
+                        "stream", __FUNCTION__, mCameraId);
+                return res;
+            }
+            res = mDevice->waitUntilDrained();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Waiting to stop streaming failed: "
+                        "%s (%d)", __FUNCTION__, mCameraId,
+                        strerror(-res), res);
+            }
+
+            res = updateProcessorStream<
+                    StreamingProcessor,
+                    &StreamingProcessor::updateRecordingStream>(
+                        mStreamingProcessor,
+                        params);
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to update recording stream: "
+                        "%s (%d)", __FUNCTION__, mCameraId,
+                        strerror(-res), res);
+                return res;
+            }
         }
+    } else {
+        // Maintain call sequencing for HALv2 devices.
         res = updateProcessorStream<
                 StreamingProcessor,
                 &StreamingProcessor::updateRecordingStream>(mStreamingProcessor,
-                                                            params);
-
+                    params);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to update recording stream: %s (%d)",
                     __FUNCTION__, mCameraId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index cda98be..b433781 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -89,14 +89,27 @@
         mCaptureConsumer->setFrameAvailableListener(this);
         mCaptureConsumer->setName(String8("Camera2Client::CaptureConsumer"));
         mCaptureWindow = new Surface(producer);
+    }
+
+    // Since ashmem heaps are rounded up to page size, don't reallocate if
+    // the capture heap isn't exactly the same size as the required JPEG buffer
+    const size_t HEAP_SLACK_FACTOR = 2;
+    if (mCaptureHeap == 0 ||
+            (mCaptureHeap->getSize() < static_cast<size_t>(maxJpegSize)) ||
+            (mCaptureHeap->getSize() >
+                    static_cast<size_t>(maxJpegSize) * HEAP_SLACK_FACTOR) ) {
         // Create memory for API consumption
-        mCaptureHeap = new MemoryHeapBase(maxJpegSize, 0, "Camera2Client::CaptureHeap");
+        mCaptureHeap.clear();
+        mCaptureHeap =
+                new MemoryHeapBase(maxJpegSize, 0, "Camera2Client::CaptureHeap");
         if (mCaptureHeap->getSize() == 0) {
             ALOGE("%s: Camera %d: Unable to allocate memory for capture",
                     __FUNCTION__, mId);
             return NO_MEMORY;
         }
     }
+    ALOGV("%s: Camera %d: JPEG capture heap now %d bytes; requested %d bytes",
+            __FUNCTION__, mId, mCaptureHeap->getSize(), maxJpegSize);
 
     if (mCaptureStreamId != NO_STREAM) {
         // Check if stream parameters have to change
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index bb72206..8f78103 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -154,7 +154,7 @@
                     mId, strerror(-res), res);
             return res;
         }
-        if (mDeleted || currentWidth != (uint32_t)params.fastInfo.arrayWidth ||
+        if (currentWidth != (uint32_t)params.fastInfo.arrayWidth ||
                 currentHeight != (uint32_t)params.fastInfo.arrayHeight) {
             res = device->deleteReprocessStream(mZslReprocessStreamId);
             if (res != OK) {