Merge "Camera: Improve logical camera RAW capture docs" into sc-dev
diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.cpp b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
index 7137767..30d7394 100644
--- a/media/codec2/components/mp3/C2SoftMp3Dec.cpp
+++ b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
@@ -16,6 +16,7 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "C2SoftMp3Dec"
+#include <inttypes.h>
 #include <log/log.h>
 
 #include <numeric>
@@ -485,10 +486,10 @@
         }
     }
 
-    uint64_t outTimeStamp = mProcessedSamples * 1000000ll / samplingRate;
+    int64_t outTimeStamp = mProcessedSamples * 1000000ll / samplingRate;
     mProcessedSamples += ((outSize - outOffset) / (numChannels * sizeof(int16_t)));
-    ALOGV("out buffer attr. offset %d size %d timestamp %u", outOffset, outSize - outOffset,
-          (uint32_t)(mAnchorTimeStamp + outTimeStamp));
+    ALOGV("out buffer attr. offset %d size %d timestamp %" PRId64 " ", outOffset,
+          outSize - outOffset, mAnchorTimeStamp + outTimeStamp);
     decodedSizes.clear();
     work->worklets.front()->output.flags = work->input.flags;
     work->worklets.front()->output.buffers.clear();
diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.h b/media/codec2/components/mp3/C2SoftMp3Dec.h
index 402bdc4..e2dfcf3 100644
--- a/media/codec2/components/mp3/C2SoftMp3Dec.h
+++ b/media/codec2/components/mp3/C2SoftMp3Dec.h
@@ -63,7 +63,7 @@
     bool mSignalledError;
     bool mSignalledOutputEos;
     bool mGaplessBytes;
-    uint64_t mAnchorTimeStamp;
+    int64_t mAnchorTimeStamp;
     uint64_t mProcessedSamples;
 
     status_t initDecoder();
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index e7207a5..29cc564 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -1301,17 +1301,7 @@
 
 sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
     if (buffer == nullptr) {
-        sp<Codec2Buffer> c2buffer = ConstGraphicBlockBuffer::AllocateEmpty(
-                mFormat,
-                [lbp = mLocalBufferPool](size_t capacity) {
-                    return lbp->newBuffer(capacity);
-                });
-        if (c2buffer == nullptr) {
-            ALOGD("[%s] ConstGraphicBlockBuffer::AllocateEmpty failed", mName);
-            return nullptr;
-        }
-        c2buffer->setRange(0, 0);
-        return c2buffer;
+        return new Codec2Buffer(mFormat, new ABuffer(nullptr, 0));
     } else {
         return ConstGraphicBlockBuffer::Allocate(
                 mFormat,
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
index 66b7622..41e4fff 100644
--- a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
@@ -106,6 +106,19 @@
     }
 }
 
+TEST(RawGraphicOutputBuffersTest, WrapNullBuffer) {
+    constexpr int32_t kWidth = 320;
+    constexpr int32_t kHeight = 240;
+
+    std::shared_ptr<RawGraphicOutputBuffers> buffers =
+        GetRawGraphicOutputBuffers(kWidth, kHeight);
+
+    sp<Codec2Buffer> buffer = buffers->wrap(nullptr);
+    ASSERT_EQ(nullptr, buffer->base());
+    ASSERT_EQ(0, buffer->size());
+    ASSERT_EQ(0, buffer->offset());
+}
+
 TEST(RawGraphicOutputBuffersTest, FlexYuvColorFormat) {
     constexpr int32_t kWidth = 320;
     constexpr int32_t kHeight = 240;
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 1ed240a..09d9535 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -452,8 +452,8 @@
                                             void* threadArg)
 {
     if (mHasThread) {
-        ALOGE("%s() - mHasThread already true", __func__);
-        return AAUDIO_ERROR_INVALID_STATE;
+        ALOGD("%s() - previous thread was not joined, join now to be safe", __func__);
+        joinThread_l(nullptr);
     }
     if (threadProc == nullptr) {
         return AAUDIO_ERROR_NULL;
@@ -462,6 +462,7 @@
     mThreadProc = threadProc;
     mThreadArg = threadArg;
     setPeriodNanoseconds(periodNanoseconds);
+    mHasThread = true;
     // Prevent this object from getting deleted before the thread has a chance to create
     // its strong pointer. Assume the thread will call decStrong().
     this->incStrong(nullptr);
@@ -470,6 +471,7 @@
         android::status_t status = -errno;
         ALOGE("%s() - pthread_create() failed, %d", __func__, status);
         this->decStrong(nullptr); // Because the thread won't do it.
+        mHasThread = false;
         return AAudioConvert_androidToAAudioResult(status);
     } else {
         // TODO Use AAudioThread or maybe AndroidThread
@@ -484,7 +486,6 @@
         err = pthread_setname_np(mThread, name);
         ALOGW_IF((err != 0), "Could not set name of AAudio thread. err = %d", err);
 
-        mHasThread = true;
         return AAUDIO_OK;
     }
 }
@@ -498,7 +499,7 @@
 // This must be called under mStreamLock.
 aaudio_result_t AudioStream::joinThread_l(void** returnArg) {
     if (!mHasThread) {
-        ALOGD("joinThread() - but has no thread");
+        ALOGD("joinThread() - but has no thread or already join()ed");
         return AAUDIO_ERROR_INVALID_STATE;
     }
     aaudio_result_t result = AAUDIO_OK;
@@ -515,8 +516,7 @@
             result = AAudioConvert_androidToAAudioResult(-err);
         } else {
             ALOGD("%s() pthread_join succeeded", __func__);
-            // This must be set false so that the callback thread can be created
-            // when the stream is restarted.
+            // Prevent joining a second time, which has undefined behavior.
             mHasThread = false;
         }
     } else {
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 2b45ed3..9835c8c 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -157,9 +157,13 @@
 
     virtual aaudio_result_t setBufferSize(int32_t requestedFrames) = 0;
 
-    virtual aaudio_result_t createThread_l(int64_t periodNanoseconds,
-                                           aaudio_audio_thread_proc_t threadProc,
-                                           void *threadArg);
+    aaudio_result_t createThread(int64_t periodNanoseconds,
+                                 aaudio_audio_thread_proc_t threadProc,
+                                 void *threadArg)
+                                 EXCLUDES(mStreamLock) {
+        std::lock_guard<std::mutex> lock(mStreamLock);
+        return createThread_l(periodNanoseconds, threadProc, threadArg);
+    }
 
     aaudio_result_t joinThread(void **returnArg);
 
@@ -535,6 +539,11 @@
         mSessionId = sessionId;
     }
 
+    aaudio_result_t createThread_l(int64_t periodNanoseconds,
+                                           aaudio_audio_thread_proc_t threadProc,
+                                           void *threadArg)
+                                           REQUIRES(mStreamLock);
+
     aaudio_result_t joinThread_l(void **returnArg) REQUIRES(mStreamLock);
 
     std::atomic<bool>    mCallbackEnabled{false};
@@ -658,6 +667,7 @@
     std::atomic<pid_t>          mErrorCallbackThread{CALLBACK_THREAD_NONE};
 
     // background thread ----------------------------------
+    // Use mHasThread to prevent joining twice, which has undefined behavior.
     bool                        mHasThread GUARDED_BY(mStreamLock) = false;
     pthread_t                   mThread  GUARDED_BY(mStreamLock) = {};
 
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 6765bdb..5f802de 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -472,7 +472,7 @@
             status = BAD_VALUE;
             goto exit;
         }
-        mStreamType = streamType;
+        mOriginalStreamType = streamType;
 
     } else {
         // stream type shouldn't be looked at, this track has audio attributes
@@ -481,7 +481,7 @@
                 " usage=%d content=%d flags=0x%x tags=[%s]",
                 __func__,
                  mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
-        mStreamType = AUDIO_STREAM_DEFAULT;
+        mOriginalStreamType = AUDIO_STREAM_DEFAULT;
         audio_flags_to_audio_output_flags(mAttributes.flags, &flags);
     }
 
@@ -1605,9 +1605,6 @@
 
 audio_stream_type_t AudioTrack::streamType() const
 {
-    if (mStreamType == AUDIO_STREAM_DEFAULT) {
-        return AudioSystem::attributesToStreamType(mAttributes);
-    }
     return mStreamType;
 }
 
@@ -1688,8 +1685,9 @@
     }
 
     IAudioFlinger::CreateTrackInput input;
-    if (mStreamType != AUDIO_STREAM_DEFAULT) {
-        input.attr = AudioSystem::streamTypeToAttributes(mStreamType);
+    if (mOriginalStreamType != AUDIO_STREAM_DEFAULT) {
+        // Legacy: This is based on original parameters even if the track is recreated.
+        input.attr = AudioSystem::streamTypeToAttributes(mOriginalStreamType);
     } else {
         input.attr = mAttributes;
     }
@@ -1745,6 +1743,7 @@
     mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
     mRoutedDeviceId = output.selectedDeviceId;
     mSessionId = output.sessionId;
+    mStreamType = output.streamType;
 
     mSampleRate = output.sampleRate;
     if (mOriginalSampleRate == 0) {
@@ -3284,8 +3283,6 @@
     result.appendFormat("  id(%d) status(%d), state(%d), session Id(%d), flags(%#x)\n",
                         mPortId, mStatus, mState, mSessionId, mFlags);
     result.appendFormat("  stream type(%d), left - right volume(%f, %f)\n",
-                        (mStreamType == AUDIO_STREAM_DEFAULT) ?
-                            AudioSystem::attributesToStreamType(mAttributes) :
                             mStreamType,
                         mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]);
     result.appendFormat("  format(%#x), channel mask(%#x), channel count(%u)\n",
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 0564cdf..e46b349 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -101,6 +101,8 @@
             legacy2aidl_audio_port_handle_t_int32_t(selectedDeviceId));
     aidl.sessionId = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(sessionId));
     aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(sampleRate));
+    aidl.streamType =  VALUE_OR_RETURN(
+            legacy2aidl_audio_stream_type_t_AudioStreamType(streamType));
     aidl.afFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(afFrameCount));
     aidl.afSampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(afSampleRate));
     aidl.afLatencyMs = VALUE_OR_RETURN(convertIntegral<int32_t>(afLatencyMs));
@@ -122,6 +124,8 @@
             aidl2legacy_int32_t_audio_port_handle_t(aidl.selectedDeviceId));
     legacy.sessionId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.sessionId));
     legacy.sampleRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+    legacy.streamType = VALUE_OR_RETURN(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
     legacy.afFrameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.afFrameCount));
     legacy.afSampleRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.afSampleRate));
     legacy.afLatencyMs = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.afLatencyMs));
diff --git a/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl b/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
index 6bdd8e4..40473fa 100644
--- a/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.media.AudioStreamType;
 import android.media.IAudioTrack;
 
 /**
@@ -34,6 +35,7 @@
     int selectedDeviceId;
     int sessionId;
     int sampleRate;
+    AudioStreamType streamType;
     long afFrameCount;
     int afSampleRate;
     int afLatencyMs;
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index f61eef2..cb00990 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -1164,8 +1164,9 @@
 
     // constant after constructor or set()
     audio_format_t          mFormat;                // as requested by client, not forced to 16-bit
-    audio_stream_type_t     mStreamType;            // mStreamType == AUDIO_STREAM_DEFAULT implies
-                                                    // this AudioTrack has valid attributes
+    // mOriginalStreamType == AUDIO_STREAM_DEFAULT implies this AudioTrack has valid attributes
+    audio_stream_type_t     mOriginalStreamType = AUDIO_STREAM_DEFAULT;
+    audio_stream_type_t     mStreamType = AUDIO_STREAM_DEFAULT;
     uint32_t                mChannelCount;
     audio_channel_mask_t    mChannelMask;
     sp<IMemory>             mSharedBuffer;
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 327b37e..0e059f7 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -110,6 +110,7 @@
 
         /* output */
         uint32_t sampleRate;
+        audio_stream_type_t streamType;
         size_t   afFrameCount;
         uint32_t afSampleRate;
         uint32_t afLatencyMs;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 9533ae5..8e05de8 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -145,15 +145,17 @@
         return;
     }
 
-    // Close socket before posting message to RTSPSource message handler.
-    if (mHandler != NULL) {
-        close(mHandler->getARTSPConnection()->getSocket());
-    }
-
     sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
 
     sp<AMessage> dummy;
     msg->postAndAwaitResponse(&dummy);
+
+    // Close socket after posting message to RTSPSource message handler.
+    if (mHandler != NULL && mHandler->getARTSPConnection()->getSocket() >= 0) {
+        ALOGD("closing rtsp socket if not closed yet.");
+        close(mHandler->getARTSPConnection()->getSocket());
+    }
+
 }
 
 status_t NuPlayer::RTSPSource::feedMoreTSData() {
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 8f4df8e..169df46 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -594,4 +594,15 @@
     return mFormat;
 }
 
+bool APacketSource::isVideo() {
+    bool isVideo = false;
+
+    const char *mime;
+    if (mFormat->findCString(kKeyMIMEType, &mime)) {
+        isVideo = !strncasecmp(mime, "video/", 6);
+    }
+
+    return isVideo;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/rtsp/APacketSource.h b/media/libstagefright/rtsp/APacketSource.h
index 530e537..2b9b5ba 100644
--- a/media/libstagefright/rtsp/APacketSource.h
+++ b/media/libstagefright/rtsp/APacketSource.h
@@ -33,6 +33,8 @@
 
     virtual sp<MetaData> getFormat();
 
+    bool isVideo();
+
 protected:
     virtual ~APacketSource();
 
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 33c85a7..a4da433 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -104,6 +104,11 @@
     msg->post();
 }
 
+void ARTPConnection::seekStream() {
+    sp<AMessage> msg = new AMessage(kWhatSeekStream, this);
+    msg->post();
+}
+
 void ARTPConnection::removeStream(int rtpSocket, int rtcpSocket) {
     sp<AMessage> msg = new AMessage(kWhatRemoveStream, this);
     msg->setInt32("rtp-socket", rtpSocket);
@@ -283,6 +288,12 @@
             break;
         }
 
+        case kWhatSeekStream:
+        {
+            onSeekStream(msg);
+            break;
+        }
+
         case kWhatRemoveStream:
         {
             onRemoveStream(msg);
@@ -353,6 +364,18 @@
     }
 }
 
+void ARTPConnection::onSeekStream(const sp<AMessage> &msg) {
+    (void)msg; // unused param as of now.
+    List<StreamInfo>::iterator it = mStreams.begin();
+    while (it != mStreams.end()) {
+        for (size_t i = 0; i < it->mSources.size(); ++i) {
+            sp<ARTPSource> source = it->mSources.valueAt(i);
+            source->timeReset();
+        }
+        ++it;
+    }
+}
+
 void ARTPConnection::onRemoveStream(const sp<AMessage> &msg) {
     int32_t rtpSocket, rtcpSocket;
     CHECK(msg->findInt32("rtp-socket", &rtpSocket));
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
index ea0a374..adf9670 100644
--- a/media/libstagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -40,7 +40,7 @@
             const sp<ASessionDescription> &sessionDesc, size_t index,
             const sp<AMessage> &notify,
             bool injected);
-
+    void seekStream();
     void removeStream(int rtpSocket, int rtcpSocket);
 
     void injectPacket(int index, const sp<ABuffer> &buffer);
@@ -69,6 +69,7 @@
 private:
     enum {
         kWhatAddStream,
+        kWhatSeekStream,
         kWhatRemoveStream,
         kWhatPollStreams,
         kWhatInjectPacket,
@@ -94,6 +95,7 @@
     int32_t mCumulativeBytes;
 
     void onAddStream(const sp<AMessage> &msg);
+    void onSeekStream(const sp<AMessage> &msg);
     void onRemoveStream(const sp<AMessage> &msg);
     void onPollStreams();
     void onInjectPacket(const sp<AMessage> &msg);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 8787d65..f960482 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -130,6 +130,24 @@
     notify->post();
 }
 
+void ARTPSource::timeReset() {
+    mFirstRtpTime = 0;
+    mFirstSysTime = 0;
+    mFirstSsrc = 0;
+    mHighestNackNumber = 0;
+    mHighestSeqNumber = 0;
+    mPrevExpected = 0;
+    mBaseSeqNumber = 0;
+    mNumBuffersReceived = 0;
+    mPrevNumBuffersReceived = 0;
+    mPrevExpectedForRR = 0;
+    mPrevNumBuffersReceivedForRR = 0;
+    mLastNTPTime = 0;
+    mLastNTPTimeUpdateUs = 0;
+    mIssueFIRByAssembler = false;
+    mLastFIRRequestUs = -1;
+}
+
 bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
     uint32_t seqNum = (uint32_t)buffer->int32Data();
 
@@ -147,6 +165,11 @@
         ALOGD("first-rtp arrived: first-rtp-time=%u, sys-time=%lld, seq-num=%u, ssrc=%d",
                 mFirstRtpTime, (long long)mFirstSysTime, mHighestSeqNumber, mFirstSsrc);
         mJitterCalc->init(mFirstRtpTime, mFirstSysTime, 0, mStaticJbTimeMs * 1000);
+        if (mQueue.size() > 0) {
+            ALOGD("clearing buffers which belonged to previous timeline"
+                    " since a base timeline has been changed.");
+            mQueue.clear();
+        }
         mQueue.push_back(buffer);
         return true;
     }
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 0edff23..2d804d8 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -56,6 +56,7 @@
     };
 
     void processRTPPacket(const sp<ABuffer> &buffer);
+    void timeReset();
     void timeUpdate(uint32_t rtpTime, uint64_t ntpTime);
     void byeReceived();
 
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index ec70952..29e263d 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -327,16 +327,17 @@
 
     while (buffer->range_length() > 0) {
         const uint8_t *NALPtr = (const uint8_t *)buffer->data() + buffer->range_offset();
+        uint8_t nalType = (*NALPtr) & H264_NALU_MASK;
 
         MediaBufferBase **targetPtr = NULL;
-        if ((*NALPtr & H264_NALU_MASK) == H264_NALU_SPS) {
+        if (nalType == H264_NALU_SPS) {
             targetPtr = spsBuffer;
-        } else if ((*NALPtr & H264_NALU_MASK) == H264_NALU_PPS) {
+        } else if (nalType == H264_NALU_PPS) {
             targetPtr = ppsBuffer;
         } else {
             return;
         }
-        ALOGV("SPS(7) or PPS(8) found. Type %d", *NALPtr & H264_NALU_MASK);
+        ALOGV("SPS(7) or PPS(8) found. Type %d", nalType);
 
         uint32_t bufferSize = buffer->range_length();
         MediaBufferBase *&target = *targetPtr;
@@ -417,18 +418,18 @@
             }
         }
 
+        uint32_t targetSize;
         if (target != NULL) {
             target->release();
         }
-        uint32_t targetSize;
         // note that targetSize is never 0 as the first byte is never part
         // of a start prefix
         if (isBoundFound) {
             targetSize = i - SPCSize + 1;
-            target = MediaBufferBase::Create(j);
+            target = MediaBufferBase::Create(targetSize);
             memcpy(target->data(),
                    (const uint8_t *)buffer->data() + buffer->range_offset(),
-                   j);
+                   targetSize);
             buffer->set_range(buffer->range_offset() + targetSize + SPCSize,
                               buffer->range_length() - targetSize - SPCSize);
         } else {
@@ -994,12 +995,14 @@
     }
 
     sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
-
     if (mediaBuf->range_length() + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE
             + RTP_PAYLOAD_ROOM_SIZE <= buffer->capacity()) {
         // The data fits into a single packet
         uint8_t *data = buffer->data();
         data[0] = 0x80;
+        if (mRTPCVOExtMap > 0) {
+            data[0] |= 0x10;
+        }
         if (isNonVCL) {
             data[1] = mPayloadType;  // Marker bit should not be set in case of Non-VCL
         } else {
@@ -1016,144 +1019,6 @@
         data[10] = (mSourceID >> 8) & 0xff;
         data[11] = mSourceID & 0xff;
 
-        memcpy(&data[12],
-               mediaData, mediaBuf->range_length());
-
-        buffer->setRange(0, mediaBuf->range_length() + 12);
-
-        send(buffer, false /* isRTCP */);
-
-        ++mSeqNo;
-        ++mNumRTPSent;
-        mNumRTPOctetsSent += buffer->size() - 12;
-    } else {
-        // FU-A
-
-        unsigned nalType = (mediaData[0] >> 1) & H265_NALU_MASK;
-        ALOGV("H265 nalType 0x%x, data[0]=0x%x", nalType, mediaData[0]);
-        size_t offset = 2; //H265 payload header is 16 bit.
-
-        bool firstPacket = true;
-        while (offset < mediaBuf->range_length()) {
-            size_t size = mediaBuf->range_length() - offset;
-            bool lastPacket = true;
-            if (size + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE +
-                    RTP_FU_HEADER_SIZE + RTP_PAYLOAD_ROOM_SIZE > buffer->capacity()) {
-                lastPacket = false;
-                size = buffer->capacity() - TCPIP_HEADER_SIZE - RTP_HEADER_SIZE -
-                    RTP_HEADER_EXT_SIZE - RTP_FU_HEADER_SIZE - RTP_PAYLOAD_ROOM_SIZE;
-            }
-
-            uint8_t *data = buffer->data();
-            data[0] = 0x80;
-            data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType;  // M-bit
-            data[2] = (mSeqNo >> 8) & 0xff;
-            data[3] = mSeqNo & 0xff;
-            data[4] = rtpTime >> 24;
-            data[5] = (rtpTime >> 16) & 0xff;
-            data[6] = (rtpTime >> 8) & 0xff;
-            data[7] = rtpTime & 0xff;
-            data[8] = mSourceID >> 24;
-            data[9] = (mSourceID >> 16) & 0xff;
-            data[10] = (mSourceID >> 8) & 0xff;
-            data[11] = mSourceID & 0xff;
-
-            /*  H265 payload header is 16 bit
-                 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
-                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-                |F|     Type  |  Layer ID | TID |
-                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-            */
-            ALOGV("H265 payload header 0x%x %x", mediaData[0], mediaData[1]);
-            // excludes Type from 1st byte of H265 payload header.
-            data[12] = mediaData[0] & 0x81;
-            // fills Type as FU (49 == 0x31)
-            data[12] = data[12] | (0x31 << 1);
-            data[13] = mediaData[1];
-
-            ALOGV("H265 FU header 0x%x %x", data[12], data[13]);
-
-            CHECK(!firstPacket || !lastPacket);
-            /*
-                FU INDICATOR HDR
-                0 1 2 3 4 5 6 7
-                +-+-+-+-+-+-+-+
-                |S|E|   Type  |
-                +-+-+-+-+-+-+-+
-            */
-
-            data[14] =
-                (firstPacket ? 0x80 : 0x00)
-                | (lastPacket ? 0x40 : 0x00)
-                | (nalType & H265_NALU_MASK);
-            ALOGV("H265 FU indicator 0x%x", data[14]);
-
-            memcpy(&data[15], &mediaData[offset], size);
-
-            buffer->setRange(0, 15 + size);
-
-            send(buffer, false /* isRTCP */);
-
-            ++mSeqNo;
-            ++mNumRTPSent;
-            mNumRTPOctetsSent += buffer->size() - 12;
-
-            firstPacket = false;
-            offset += size;
-        }
-    }
-
-    mLastRTPTime = rtpTime;
-    mLastNTPTime = GetNowNTP();
-
-}
-
-void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
-    // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
-    CHECK_GE(kMaxPacketSize, 12u + 2u);
-
-    int64_t timeUs;
-    CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
-
-    sendSPSPPSIfIFrame(mediaBuf, timeUs);
-
-    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
-
-    CHECK(mediaBuf->range_length() > 0);
-    const uint8_t *mediaData =
-        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
-
-    int32_t sps, pps;
-    bool isSpsPps = false;
-    if (mediaBuf->meta_data().findInt32(kKeySps, &sps) ||
-            mediaBuf->meta_data().findInt32(kKeyPps, &pps)) {
-        isSpsPps = true;
-    }
-
-    mTrafficRec->updateClock(ALooper::GetNowUs() / 1000);
-    sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
-    if (mediaBuf->range_length() + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE
-            + RTP_PAYLOAD_ROOM_SIZE <= buffer->capacity()) {
-        // The data fits into a single packet
-        uint8_t *data = buffer->data();
-        data[0] = 0x80;
-        if (mRTPCVOExtMap > 0)
-            data[0] |= 0x10;
-        if (isSpsPps)
-            data[1] = mPayloadType;  // Marker bit should not be set in case of sps/pps
-        else
-            data[1] = (1 << 7) | mPayloadType;
-        data[2] = (mSeqNo >> 8) & 0xff;
-        data[3] = mSeqNo & 0xff;
-        data[4] = rtpTime >> 24;
-        data[5] = (rtpTime >> 16) & 0xff;
-        data[6] = (rtpTime >> 8) & 0xff;
-        data[7] = rtpTime & 0xff;
-        data[8] = mSourceID >> 24;
-        data[9] = (mSourceID >> 16) & 0xff;
-        data[10] = (mSourceID >> 8) & 0xff;
-        data[11] = mSourceID & 0xff;
-
         int rtpExtIndex = 0;
         if (mRTPCVOExtMap > 0) {
             /*
@@ -1202,8 +1067,9 @@
     } else {
         // FU-A
 
-        unsigned nalType = mediaData[0];
-        size_t offset = 1;
+        unsigned nalType = (mediaData[0] >> 1) & H265_NALU_MASK;
+        ALOGV("H265 nalType 0x%x, data[0]=0x%x", nalType, mediaData[0]);
+        size_t offset = 2; //H265 payload header is 16 bit.
 
         bool firstPacket = true;
         while (offset < mediaBuf->range_length()) {
@@ -1218,8 +1084,9 @@
 
             uint8_t *data = buffer->data();
             data[0] = 0x80;
-            if (lastPacket && mRTPCVOExtMap > 0)
+            if (lastPacket && mRTPCVOExtMap > 0) {
                 data[0] |= 0x10;
+            }
             data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType;  // M-bit
             data[2] = (mSeqNo >> 8) & 0xff;
             data[3] = mSeqNo & 0xff;
@@ -1245,14 +1112,222 @@
                 rtpExtIndex = 8;
             }
 
-            data[12 + rtpExtIndex] = 28 | (nalType & 0xe0);
+            /*  H265 payload header is 16 bit
+                 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+                |F|    Type   |  Layer ID | TID |
+                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            */
+            ALOGV("H265 payload header 0x%x %x", mediaData[0], mediaData[1]);
+            // excludes Type from 1st byte of H265 payload header.
+            data[12 + rtpExtIndex] = mediaData[0] & 0x81;
+            // fills Type as FU (49 == 0x31)
+            data[12 + rtpExtIndex] = data[12 + rtpExtIndex] | (0x31 << 1);
+            data[13 + rtpExtIndex] = mediaData[1];
+
+            ALOGV("H265 FU header 0x%x %x", data[12 + rtpExtIndex], data[13 + rtpExtIndex]);
 
             CHECK(!firstPacket || !lastPacket);
+            /*
+                FU INDICATOR HDR
+                 0 1 2 3 4 5 6 7
+                +-+-+-+-+-+-+-+-+
+                |S|E|   Type    |
+                +-+-+-+-+-+-+-+-+
+            */
+
+            data[14 + rtpExtIndex] =
+                (firstPacket ? 0x80 : 0x00)
+                | (lastPacket ? 0x40 : 0x00)
+                | (nalType & H265_NALU_MASK);
+            ALOGV("H265 FU indicator 0x%x", data[14]);
+
+            memcpy(&data[15 + rtpExtIndex], &mediaData[offset], size);
+
+            buffer->setRange(0, 15 + rtpExtIndex + size);
+
+            send(buffer, false /* isRTCP */);
+
+            ++mSeqNo;
+            ++mNumRTPSent;
+            mNumRTPOctetsSent += buffer->size() - (12 + rtpExtIndex);
+
+            firstPacket = false;
+            offset += size;
+        }
+    }
+
+    mLastRTPTime = rtpTime;
+    mLastNTPTime = GetNowNTP();
+}
+
+void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
+    // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
+    CHECK_GE(kMaxPacketSize, 12u + 2u);
+
+    int64_t timeUs;
+    CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
+
+    sendSPSPPSIfIFrame(mediaBuf, timeUs);
+
+    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
+
+    CHECK(mediaBuf->range_length() > 0);
+    const uint8_t *mediaData =
+        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+
+    int32_t sps, pps;
+    bool isSpsPps = false;
+    if (mediaBuf->meta_data().findInt32(kKeySps, &sps) ||
+            mediaBuf->meta_data().findInt32(kKeyPps, &pps)) {
+        isSpsPps = true;
+    }
+
+    mTrafficRec->updateClock(ALooper::GetNowUs() / 1000);
+    sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
+    if (mediaBuf->range_length() + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE
+            + RTP_PAYLOAD_ROOM_SIZE <= buffer->capacity()) {
+        // The data fits into a single packet
+        uint8_t *data = buffer->data();
+        data[0] = 0x80;
+        if (mRTPCVOExtMap > 0) {
+            data[0] |= 0x10;
+        }
+        if (isSpsPps) {
+            data[1] = mPayloadType;  // Marker bit should not be set in case of sps/pps
+        } else {
+            data[1] = (1 << 7) | mPayloadType;
+        }
+        data[2] = (mSeqNo >> 8) & 0xff;
+        data[3] = mSeqNo & 0xff;
+        data[4] = rtpTime >> 24;
+        data[5] = (rtpTime >> 16) & 0xff;
+        data[6] = (rtpTime >> 8) & 0xff;
+        data[7] = rtpTime & 0xff;
+        data[8] = mSourceID >> 24;
+        data[9] = (mSourceID >> 16) & 0xff;
+        data[10] = (mSourceID >> 8) & 0xff;
+        data[11] = mSourceID & 0xff;
+
+        int rtpExtIndex = 0;
+        if (mRTPCVOExtMap > 0) {
+            /*
+                0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+               |       0xBE    |    0xDE       |           length=3            |
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+               |  ID   | L=0   |     data      |  ID   |  L=1  |   data...
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+                     ...data   |    0 (pad)    |    0 (pad)    |  ID   | L=3   |
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+               |                          data                                 |
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+              In the one-byte header form of extensions, the 16-bit value required
+              by the RTP specification for a header extension, labeled in the RTP
+              specification as "defined by profile", takes the fixed bit pattern
+              0xBEDE (the first version of this specification was written on the
+              feast day of the Venerable Bede).
+            */
+            data[12] = 0xBE;
+            data[13] = 0xDE;
+            // put a length of RTP Extension.
+            data[14] = 0x00;
+            data[15] = 0x01;
+            // put extmap of RTP assigned for CVO.
+            data[16] = (mRTPCVOExtMap << 4) | 0x0;
+            // put image degrees as per CVO specification.
+            data[17] = mRTPCVODegrees;
+            data[18] = 0x0;
+            data[19] = 0x0;
+            rtpExtIndex = 8;
+        }
+
+        memcpy(&data[12 + rtpExtIndex],
+               mediaData, mediaBuf->range_length());
+
+        buffer->setRange(0, mediaBuf->range_length() + (12 + rtpExtIndex));
+
+        send(buffer, false /* isRTCP */);
+
+        ++mSeqNo;
+        ++mNumRTPSent;
+        mNumRTPOctetsSent += buffer->size() - (12 + rtpExtIndex);
+    } else {
+        // FU-A
+
+        unsigned nalType = mediaData[0] & H264_NALU_MASK;
+        ALOGV("H264 nalType 0x%x, data[0]=0x%x", nalType, mediaData[0]);
+        size_t offset = 1;
+
+        bool firstPacket = true;
+        while (offset < mediaBuf->range_length()) {
+            size_t size = mediaBuf->range_length() - offset;
+            bool lastPacket = true;
+            if (size + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE +
+                    RTP_FU_HEADER_SIZE + RTP_PAYLOAD_ROOM_SIZE > buffer->capacity()) {
+                lastPacket = false;
+                size = buffer->capacity() - TCPIP_HEADER_SIZE - RTP_HEADER_SIZE -
+                    RTP_HEADER_EXT_SIZE - RTP_FU_HEADER_SIZE - RTP_PAYLOAD_ROOM_SIZE;
+            }
+
+            uint8_t *data = buffer->data();
+            data[0] = 0x80;
+            if (lastPacket && mRTPCVOExtMap > 0) {
+                data[0] |= 0x10;
+            }
+            data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType;  // M-bit
+            data[2] = (mSeqNo >> 8) & 0xff;
+            data[3] = mSeqNo & 0xff;
+            data[4] = rtpTime >> 24;
+            data[5] = (rtpTime >> 16) & 0xff;
+            data[6] = (rtpTime >> 8) & 0xff;
+            data[7] = rtpTime & 0xff;
+            data[8] = mSourceID >> 24;
+            data[9] = (mSourceID >> 16) & 0xff;
+            data[10] = (mSourceID >> 8) & 0xff;
+            data[11] = mSourceID & 0xff;
+
+            int rtpExtIndex = 0;
+            if (lastPacket && mRTPCVOExtMap > 0) {
+                data[12] = 0xBE;
+                data[13] = 0xDE;
+                data[14] = 0x00;
+                data[15] = 0x01;
+                data[16] = (mRTPCVOExtMap << 4) | 0x0;
+                data[17] = mRTPCVODegrees;
+                data[18] = 0x0;
+                data[19] = 0x0;
+                rtpExtIndex = 8;
+            }
+
+            /*  H264 payload header is 8 bit
+                 0 1 2 3 4 5 6 7
+                +-+-+-+-+-+-+-+-+
+                |F|NRI|  Type   |
+                +-+-+-+-+-+-+-+-+
+            */
+            ALOGV("H264 payload header 0x%x", mediaData[0]);
+            // excludes Type from 1st byte of H264 payload header.
+            data[12 + rtpExtIndex] = mediaData[0] & 0xe0;
+            // fills Type as FU (28 == 0x1C)
+            data[12 + rtpExtIndex] = data[12 + rtpExtIndex] | 0x1C;
+
+            CHECK(!firstPacket || !lastPacket);
+            /*
+                FU header
+                 0 1 2 3 4 5 6 7
+                +-+-+-+-+-+-+-+-+
+                |S|E|R|  Type   |
+                +-+-+-+-+-+-+-+-+
+            */
 
             data[13 + rtpExtIndex] =
                 (firstPacket ? 0x80 : 0x00)
                 | (lastPacket ? 0x40 : 0x00)
-                | (nalType & 0x1f);
+                | (nalType & H264_NALU_MASK);
+            ALOGV("H264 FU header 0x%x", data[13]);
 
             memcpy(&data[14 + rtpExtIndex], &mediaData[offset], size);
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 0fdf431..988cec7 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -74,7 +74,8 @@
 
 // The allowed maximum number of stale access units at the beginning of
 // a new sequence.
-static int32_t kMaxAllowedStaleAccessUnits = 20;
+static int32_t kMaxAllowedStaleAudioAccessUnits = 20;
+static int32_t kMaxAllowedStaleVideoAccessUnits = 400;
 
 static int64_t kTearDownTimeoutUs = 3000000ll;
 
@@ -108,6 +109,10 @@
     }
 }
 
+static int32_t GetMaxAllowedStaleCount(bool isVideo) {
+    return isVideo ? kMaxAllowedStaleVideoAccessUnits : kMaxAllowedStaleAudioAccessUnits;
+}
+
 struct MyHandler : public AHandler {
     enum {
         kWhatConnected                  = 'conn',
@@ -1330,6 +1335,8 @@
 
                         ALOGV("rtp-info: %s", response->mHeaders.valueAt(i).c_str());
 
+                        mRTPConn->seekStream();
+
                         ALOGI("seek completed.");
                     }
                 }
@@ -1514,7 +1521,7 @@
             TrackInfo *info = &mTracks.editItemAt(trackIndex);
             info->mFirstSeqNumInSegment = seq;
             info->mNewSegment = true;
-            info->mAllowedStaleAccessUnits = kMaxAllowedStaleAccessUnits;
+            info->mAllowedStaleAccessUnits = GetMaxAllowedStaleCount(info->mIsVideo);
 
             CHECK(GetAttribute((*it).c_str(), "rtptime", &val));
 
@@ -1556,6 +1563,7 @@
         int mRTPSocket;
         int mRTCPSocket;
         bool mUsingInterleavedTCP;
+        bool mIsVideo;
         uint32_t mFirstSeqNumInSegment;
         bool mNewSegment;
         int32_t mAllowedStaleAccessUnits;
@@ -1640,9 +1648,10 @@
         info->mURL = trackURL;
         info->mPacketSource = source;
         info->mUsingInterleavedTCP = false;
+        info->mIsVideo = source->isVideo();
         info->mFirstSeqNumInSegment = 0;
         info->mNewSegment = true;
-        info->mAllowedStaleAccessUnits = kMaxAllowedStaleAccessUnits;
+        info->mAllowedStaleAccessUnits = GetMaxAllowedStaleCount(info->mIsVideo);
         info->mRTPSocket = -1;
         info->mRTCPSocket = -1;
         info->mRTPAnchor = 0;
@@ -1838,11 +1847,12 @@
                 // by ARTPSource. Only the low 16 bits of seq in RTP-Info of reply of
                 // RTSP "PLAY" command should be used to detect the first RTP packet
                 // after seeking.
+                int32_t maxAllowedStaleAccessUnits = GetMaxAllowedStaleCount(track->mIsVideo);
                 if (mSeekable) {
                     if (track->mAllowedStaleAccessUnits > 0) {
                         uint32_t seqNum16 = seqNum & 0xffff;
                         uint32_t firstSeqNumInSegment16 = track->mFirstSeqNumInSegment & 0xffff;
-                        if (seqNum16 > firstSeqNumInSegment16 + kMaxAllowedStaleAccessUnits
+                        if (seqNum16 > firstSeqNumInSegment16 + maxAllowedStaleAccessUnits
                                 || seqNum16 < firstSeqNumInSegment16) {
                             // Not the first rtp packet of the stream after seeking, discarding.
                             track->mAllowedStaleAccessUnits--;
@@ -1857,7 +1867,7 @@
                         mNumAccessUnitsReceived = 0;
                         ALOGW_IF(track->mAllowedStaleAccessUnits == 0,
                              "Still no first rtp packet after %d stale ones",
-                             kMaxAllowedStaleAccessUnits);
+                             maxAllowedStaleAccessUnits);
                         track->mAllowedStaleAccessUnits = -1;
                         return UNKNOWN_ERROR;
                     }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 54a6425..65a163f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -947,6 +947,7 @@
         output.frameCount = input.frameCount;
         output.notificationFrameCount = input.notificationFrameCount;
         output.flags = input.flags;
+        output.streamType = streamType;
 
         track = thread->createTrack_l(client, streamType, localAttr, &output.sampleRate,
                                       input.config.format, input.config.channel_mask,
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9e099ce..b9cdab8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8220,6 +8220,7 @@
 status_t AudioFlinger::RecordThread::shareAudioHistory_l(
         const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
         int64_t sharedAudioStartMs) {
+
     if ((hasAudioSession_l(sharedSessionId) & ThreadBase::TRACK_SESSION) == 0) {
         return BAD_VALUE;
     }
@@ -8234,18 +8235,21 @@
     // after one wraparound
     // We assume recent wraparounds on mRsmpInRear only given it is unlikely that the requesting
     // app waits several hours after the start time was computed.
-    const int64_t sharedAudioStartFrames = sharedAudioStartMs * mSampleRate / 1000;
+    int64_t sharedAudioStartFrames = sharedAudioStartMs * mSampleRate / 1000;
     const int32_t sharedOffset = audio_utils::safe_sub_overflow(mRsmpInRear,
           (int32_t)sharedAudioStartFrames);
-    if (sharedOffset < 0
-          || sharedOffset > mRsmpInFrames) {
-      return BAD_VALUE;
+    // Bring the start frame position within the input buffer to match the documented
+    // "best effort" behavior of the API.
+    if (sharedOffset < 0) {
+        sharedAudioStartFrames = mRsmpInRear;
+    } else if (sharedOffset > mRsmpInFrames) {
+        sharedAudioStartFrames =
+                audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
     }
 
     mSharedAudioPackageName = sharedAudioPackageName;
     if (mSharedAudioPackageName.empty()) {
-        mSharedAudioSessionId = AUDIO_SESSION_NONE;
-        mSharedAudioStartFrames = -1;
+        resetAudioHistory_l();
     } else {
         mSharedAudioSessionId = sharedSessionId;
         mSharedAudioStartFrames = (int32_t)sharedAudioStartFrames;
@@ -8253,6 +8257,12 @@
     return NO_ERROR;
 }
 
+void AudioFlinger::RecordThread::resetAudioHistory_l() {
+    mSharedAudioSessionId = AUDIO_SESSION_NONE;
+    mSharedAudioStartFrames = -1;
+    mSharedAudioPackageName = "";
+}
+
 void AudioFlinger::RecordThread::updateMetadata_l()
 {
     if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
@@ -8862,23 +8872,22 @@
 int32_t AudioFlinger::RecordThread::getOldestFront_l()
 {
     if (mTracks.size() == 0) {
-        return 0;
+        return mRsmpInRear;
     }
     int32_t oldestFront = mRsmpInRear;
     int32_t maxFilled = 0;
     for (size_t i = 0; i < mTracks.size(); i++) {
         int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
         int32_t filled;
-        if (front <= mRsmpInRear) {
-            filled = mRsmpInRear - front;
-        } else {
-            filled = (int32_t)((int64_t)mRsmpInRear + UINT32_MAX + 1 - front);
-        }
+        (void)__builtin_sub_overflow(mRsmpInRear, front, &filled);
         if (filled > maxFilled) {
             oldestFront = front;
             maxFilled = filled;
         }
     }
+    if (maxFilled > mRsmpInFrames) {
+        (void)__builtin_sub_overflow(mRsmpInRear, mRsmpInFrames, &oldestFront);
+    }
     return oldestFront;
 }
 
@@ -8928,7 +8937,7 @@
                 "resizeInputBuffer_l() called with shared history and unallocated buffer");
         size_t rsmpInFrames = (size_t)maxSharedAudioHistoryMs * mSampleRate / 1000;
         // never reduce resampler input buffer size
-        if (rsmpInFrames < mRsmpInFrames) {
+        if (rsmpInFrames <= mRsmpInFrames) {
             return;
         }
         mRsmpInFrames = rsmpInFrames;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index eee1f2b..16082a9 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1789,6 +1789,7 @@
             status_t    shareAudioHistory_l(const std::string& sharedAudioPackageName,
                                           audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
                                           int64_t sharedAudioStartMs = -1);
+            void        resetAudioHistory_l();
 
     virtual bool        isStreamInitialized() {
                             return !(mInput == nullptr || mInput->stream == nullptr);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index a6e3c06..d2a30b1 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2458,7 +2458,7 @@
             RecordThread *recordThread = (RecordThread *) thread.get();
             priorState = mState;
             if (!mSharedAudioPackageName.empty()) {
-                recordThread->shareAudioHistory_l("");
+                recordThread->resetAudioHistory_l();
             }
             recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
         }
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index b4b6ddf..9987252 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -675,7 +675,7 @@
         sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId,
                                                              selectedDeviceId, adjAttributionSource,
                                                              canCaptureOutput, canCaptureHotword,
-                                                             mAudioCommandThread);
+                                                             mOutputCommandThread);
         mAudioRecordClients.add(portId, client);
     }
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 3deea6b..dc101ff 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -237,10 +237,16 @@
         }
     }
 
-    //Derive primary rear/front cameras, and filter their charactierstics.
-    //This needs to be done after all cameras are enumerated and camera ids are sorted.
+    // Derive primary rear/front cameras, and filter their charactierstics.
+    // This needs to be done after all cameras are enumerated and camera ids are sorted.
     if (SessionConfigurationUtils::IS_PERF_CLASS) {
-        filterSPerfClassCharacteristics();
+        // Assume internal cameras are advertised from the same
+        // provider. If multiple providers are registered at different time,
+        // and each provider contains multiple internal color cameras, the current
+        // logic may filter the characteristics of more than one front/rear color
+        // cameras.
+        Mutex::Autolock l(mServiceLock);
+        filterSPerfClassCharacteristicsLocked();
     }
 
     return OK;
@@ -313,7 +319,7 @@
     filterAPI1SystemCameraLocked(mNormalDeviceIds);
 }
 
-void CameraService::filterSPerfClassCharacteristics() {
+void CameraService::filterSPerfClassCharacteristicsLocked() {
     // To claim to be S Performance primary cameras, the cameras must be
     // backward compatible. So performance class primary camera Ids must be API1
     // compatible.
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1fb7104..9021170 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -945,9 +945,10 @@
     void updateCameraNumAndIds();
 
     /**
-     * Filter camera characteristics for S Performance class primary cameras
+     * Filter camera characteristics for S Performance class primary cameras.
+     * mServiceLock should be locked.
      */
-    void filterSPerfClassCharacteristics();
+    void filterSPerfClassCharacteristicsLocked();
 
     // File descriptor to temp file used for caching previous open
     // session dumpsys info.
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 7045128..4f2b878 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -476,15 +476,16 @@
         const hardware::hidl_string& /*fqName*/,
         const hardware::hidl_string& name,
         bool preexisting) {
+    status_t res = OK;
     std::lock_guard<std::mutex> providerLock(mProviderLifecycleLock);
     {
         std::lock_guard<std::mutex> lock(mInterfaceMutex);
 
-        addProviderLocked(name, preexisting);
+        res = addProviderLocked(name, preexisting);
     }
 
     sp<StatusListener> listener = getStatusListener();
-    if (nullptr != listener.get()) {
+    if (nullptr != listener.get() && res == OK) {
         listener->onNewProviderRegistered();
     }
 
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index ab861ad..03b77fc 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -657,17 +657,17 @@
         size_t remainingBuffers = (mState == STATE_PREPARING ? mTotalBufferCount :
                                    camera_stream::max_buffers) - mHandoutTotalBufferCount;
         mLock.unlock();
-        std::unique_lock<std::mutex> batchLock(mBatchLock);
 
         nsecs_t dequeueStart = systemTime(SYSTEM_TIME_MONOTONIC);
 
-        if (mBatchSize == 1) {
+        size_t batchSize = mBatchSize.load();
+        if (batchSize == 1) {
             sp<ANativeWindow> anw = consumer;
             res = anw->dequeueBuffer(anw.get(), anb, fenceFd);
         } else {
+            std::unique_lock<std::mutex> batchLock(mBatchLock);
             res = OK;
             if (mBatchedBuffers.size() == 0) {
-                size_t batchSize = mBatchSize;
                 if (remainingBuffers == 0) {
                     ALOGE("%s: cannot get buffer while all buffers are handed out", __FUNCTION__);
                     return INVALID_OPERATION;
@@ -675,13 +675,17 @@
                 if (batchSize > remainingBuffers) {
                     batchSize = remainingBuffers;
                 }
+                batchLock.unlock();
                 // Refill batched buffers
-                mBatchedBuffers.resize(batchSize);
-                res = consumer->dequeueBuffers(&mBatchedBuffers);
+                std::vector<Surface::BatchBuffer> batchedBuffers;
+                batchedBuffers.resize(batchSize);
+                res = consumer->dequeueBuffers(&batchedBuffers);
+                batchLock.lock();
                 if (res != OK) {
                     ALOGE("%s: batch dequeueBuffers call failed! %s (%d)",
                             __FUNCTION__, strerror(-res), res);
-                    mBatchedBuffers.clear();
+                } else {
+                    mBatchedBuffers = std::move(batchedBuffers);
                 }
             }
 
@@ -692,7 +696,6 @@
                 mBatchedBuffers.pop_back();
             }
         }
-        batchLock.unlock();
 
         nsecs_t dequeueEnd = systemTime(SYSTEM_TIME_MONOTONIC);
         mDequeueBufferLatency.add(dequeueStart, dequeueEnd);
@@ -1129,7 +1132,6 @@
 
 status_t Camera3OutputStream::setBatchSize(size_t batchSize) {
     Mutex::Autolock l(mLock);
-    std::lock_guard<std::mutex> lock(mBatchLock);
     if (batchSize == 0) {
         ALOGE("%s: invalid batch size 0", __FUNCTION__);
         return BAD_VALUE;
@@ -1145,31 +1147,36 @@
         return INVALID_OPERATION;
     }
 
-    if (batchSize != mBatchSize) {
-        if (mBatchedBuffers.size() != 0) {
-            ALOGE("%s: change batch size from %zu to %zu dynamically is not supported",
-                    __FUNCTION__, mBatchSize, batchSize);
-            return INVALID_OPERATION;
-        }
-
-        if (camera_stream::max_buffers < batchSize) {
-            ALOGW("%s: batch size is capped by max_buffers %d", __FUNCTION__,
-                    camera_stream::max_buffers);
-            batchSize = camera_stream::max_buffers;
-        }
-        mBatchSize = batchSize;
+    if (camera_stream::max_buffers < batchSize) {
+        ALOGW("%s: batch size is capped by max_buffers %d", __FUNCTION__,
+                camera_stream::max_buffers);
+        batchSize = camera_stream::max_buffers;
     }
+
+    size_t defaultBatchSize = 1;
+    if (!mBatchSize.compare_exchange_strong(defaultBatchSize, batchSize)) {
+        ALOGE("%s: change batch size from %zu to %zu dynamically is not supported",
+                __FUNCTION__, defaultBatchSize, batchSize);
+        return INVALID_OPERATION;
+    }
+
     return OK;
 }
 
 void Camera3OutputStream::returnPrefetchedBuffersLocked() {
-    std::lock_guard<std::mutex> batchLock(mBatchLock);
-    if (mBatchedBuffers.size() != 0) {
-        ALOGW("%s: %zu extra prefetched buffers detected. Returning",
-                __FUNCTION__, mBatchedBuffers.size());
+    std::vector<Surface::BatchBuffer> batchedBuffers;
 
-        mConsumer->cancelBuffers(mBatchedBuffers);
-        mBatchedBuffers.clear();
+    {
+        std::lock_guard<std::mutex> batchLock(mBatchLock);
+        if (mBatchedBuffers.size() != 0) {
+            ALOGW("%s: %zu extra prefetched buffers detected. Returning",
+                   __FUNCTION__, mBatchedBuffers.size());
+            batchedBuffers = std::move(mBatchedBuffers);
+        }
+    }
+
+    if (batchedBuffers.size() > 0) {
+        mConsumer->cancelBuffers(batchedBuffers);
     }
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 00e4854..ad03b53 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -312,15 +312,14 @@
     bool mDropBuffers;
 
 
-    // Protecting batch states below, must be acquired after mLock
-    std::mutex mBatchLock;
 
     // The batch size for buffer operation
-    size_t mBatchSize = 1;
+    std::atomic_size_t mBatchSize = 1;
 
+    // Protecting batch states below, must be acquired after mLock
+    std::mutex mBatchLock;
     // Prefetched buffers (ready to be handed to client)
     std::vector<Surface::BatchBuffer> mBatchedBuffers;
-
     // ---- End of mBatchLock protected scope ----
 
     /**
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 0d453cf..5fbcadb 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -126,9 +126,9 @@
     // Prevent this object from getting deleted before the thread has a chance to create
     // its strong pointer. Assume the thread will call decStrong().
     this->incStrong(nullptr);
-    aaudio_result_t result = getStreamInternal()->createThread_l(periodNanos,
-                                                                 aaudio_endpoint_thread_proc,
-                                                                 this);
+    aaudio_result_t result = getStreamInternal()->createThread(periodNanos,
+                                                               aaudio_endpoint_thread_proc,
+                                                               this);
     if (result != AAUDIO_OK) {
         this->decStrong(nullptr); // Because the thread won't do it.
     }