Merge "IAudioFlinger: fix incorrect audio patch handle" into sc-dev
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 1cde4c6..52cd4b4 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -8908,13 +8908,27 @@
      * camera's crop region is set to maximum size, the FOV of the physical streams for the
      * ultrawide lens will be the same as the logical stream, by making the crop region
      * smaller than its active array size to compensate for the smaller focal length.</p>
-     * <p>Even if the underlying physical cameras have different RAW characteristics (such as
-     * size or CFA pattern), a logical camera can still advertise RAW capability. In this
-     * case, when the application configures a RAW stream, the camera device will make sure
-     * the active physical camera will remain active to ensure consistent RAW output
-     * behavior, and not switch to other physical cameras.</p>
+     * <p>There are two ways for the application to capture RAW images from a logical camera
+     * with RAW capability:</p>
+     * <ul>
+     * <li>Because the underlying physical cameras may have different RAW capabilities (such
+     * as resolution or CFA pattern), to maintain backward compatibility, when a RAW stream
+     * is configured, the camera device makes sure the default active physical camera remains
+     * active and does not switch to other physical cameras. (One exception is that, if the
+     * logical camera consists of identical image sensors and advertises multiple focalLength
+     * due to different lenses, the camera device may generate RAW images from different
+     * physical cameras based on the focalLength being set by the application.) This
+     * backward-compatible approach usually results in loss of optical zoom, to telephoto
+     * lens or to ultrawide lens.</li>
+     * <li>Alternatively, to take advantage of the full zoomRatio range of the logical camera,
+     * the application should use <a href="https://developer.android.com/reference/android/hardware/camera2/MultiResolutionImageReader.html">MultiResolutionImageReader</a>
+     * to capture RAW images from the currently active physical camera. Because different
+     * physical camera may have different RAW characteristics, the application needs to use
+     * the characteristics and result metadata of the active physical camera for the
+     * relevant RAW metadata.</li>
+     * </ul>
      * <p>The capture request and result metadata tags required for backward compatible camera
-     * functionalities will be solely based on the logical camera capabiltity. On the other
+     * functionalities will be solely based on the logical camera capability. On the other
      * hand, the use of manual capture controls (sensor or post-processing) with a
      * logical camera may result in unexpected behavior when the HAL decides to switch
      * between physical cameras with different characteristics under the hood. For example,
diff --git a/drm/drmserver/drmserver.rc b/drm/drmserver/drmserver.rc
index de46fb9..eb176c1 100644
--- a/drm/drmserver/drmserver.rc
+++ b/drm/drmserver/drmserver.rc
@@ -1,5 +1,12 @@
 service drm /system/bin/drmserver
+    disabled
     class main
     user drm
     group drm system inet drmrpc readproc
     writepid /dev/cpuset/foreground/tasks
+
+on property:drm.service.enabled=true
+    start drm
+
+on property:drm.service.enabled=1
+    start drm
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index b0a441b..a2cac3f 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -52,25 +52,13 @@
 const sp<IDrmManagerService>& DrmManagerClientImpl::getDrmManagerService() {
     Mutex::Autolock lock(sMutex);
     if (NULL == sDrmManagerService.get()) {
-        char value[PROPERTY_VALUE_MAX];
-        if (property_get("drm.service.enabled", value, NULL) == 0) {
-            // Drm is undefined for this device
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder = sm->getService(String16("drm.drmManager"));
+        if (binder == NULL) {
+            // Do NOT retry; IServiceManager already waits for ~5 seconds
+            // in getService if a service doesn't yet exist.
             return sDrmManagerService;
         }
-
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder;
-        do {
-            binder = sm->getService(String16("drm.drmManager"));
-            if (binder != 0) {
-                break;
-            }
-            ALOGW("DrmManagerService not published, waiting...");
-            struct timespec reqt;
-            reqt.tv_sec  = 0;
-            reqt.tv_nsec = 500000000; //0.5 sec
-            nanosleep(&reqt, NULL);
-        } while (true);
         if (NULL == sDeathNotifier.get()) {
             sDeathNotifier = new DeathNotifier();
         }
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/hidl/1.0/vts/functional/video/Android.bp b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
index f211ecf..ecc4f9d 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
@@ -36,6 +36,8 @@
         "libgui",
         "libutils",
         "libcrypto",
+        "libdatasource",
+        "libui",
     ],
     data: [":media_c2_v1_video_decode_res"],
     test_config: "VtsHalMediaC2V1_0TargetVideoDecTest.xml",
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index c331d0b..4c90eee 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -33,11 +33,18 @@
 #include <gui/IConsumerListener.h>
 #include <gui/IProducerListener.h>
 #include <system/window.h>
+#include <gui/GLConsumer.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
 
 #include "media_c2_hidl_test_common.h"
 #include "media_c2_video_hidl_test_common.h"
 
-using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
+constexpr size_t kSmoothnessFactor = 4;
+constexpr size_t kRenderingDepth = 3;
+enum surfaceMode_t { NO_SURFACE, NULL_SURFACE, SURFACE };
+
+using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool, surfaceMode_t>;
 static std::vector<DecodeTestParameters> gDecodeTestParameters;
 
 using CsdFlushTestParameters = std::tuple<std::string, std::string, bool>;
@@ -392,6 +399,36 @@
     return false;
 }
 
+void setOutputSurface(const std::shared_ptr<android::Codec2Client::Component>& component,
+                      surfaceMode_t surfMode) {
+    using namespace android;
+    sp<IGraphicBufferProducer> producer = nullptr;
+    static std::atomic_uint32_t surfaceGeneration{0};
+    uint32_t generation =
+            (getpid() << 10) |
+            ((surfaceGeneration.fetch_add(1, std::memory_order_relaxed) + 1) & ((1 << 10) - 1));
+    int32_t maxDequeueBuffers = kSmoothnessFactor + kRenderingDepth;
+    if (surfMode == SURFACE) {
+        sp<IGraphicBufferConsumer> consumer = nullptr;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+        ASSERT_NE(producer, nullptr) << "createBufferQueue returned invalid producer";
+        ASSERT_NE(consumer, nullptr) << "createBufferQueue returned invalid consumer";
+
+        sp<GLConsumer> texture =
+                new GLConsumer(consumer, 0 /* tex */, GLConsumer::TEXTURE_EXTERNAL,
+                               true /* useFenceSync */, false /* isControlledByApp */);
+
+        sp<ANativeWindow> gSurface = new Surface(producer);
+        ASSERT_NE(gSurface, nullptr) << "getSurface failed";
+
+        producer->setGenerationNumber(generation);
+    }
+
+    c2_status_t err = component->setOutputSurface(C2BlockPool::BASIC_GRAPHIC, producer, generation,
+                                                  maxDequeueBuffers);
+    ASSERT_EQ(err, C2_OK) << "setOutputSurface failed";
+}
+
 void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
                    std::mutex& queueLock, std::condition_variable& queueCondition,
                    std::list<std::unique_ptr<C2Work>>& workQueue,
@@ -550,6 +587,7 @@
     if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
     bool signalEOS = std::get<3>(GetParam());
+    surfaceMode_t surfMode = std::get<4>(GetParam());
     mTimestampDevTest = true;
 
     android::Vector<FrameInfo> Info;
@@ -594,6 +632,10 @@
         refChksum.close();
     }
 
+    if (surfMode != NO_SURFACE) {
+        ASSERT_NO_FATAL_FAILURE(setOutputSurface(mComponent, surfMode));
+    }
+
     ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
                                           mFlushedIndices, mLinearPool, eleStream, &Info, 0,
                                           (int)Info.size(), signalEOS));
@@ -1061,18 +1103,23 @@
     parseArgs(argc, argv);
     gTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
     for (auto params : gTestParameters) {
+        // mOutputBufferQueue->configure() crashes when surface is NULL
+        std::initializer_list<surfaceMode_t> surfaceMode = {
+                surfaceMode_t::NO_SURFACE, surfaceMode_t::NULL_SURFACE, surfaceMode_t::SURFACE};
+        for (surfaceMode_t mode : surfaceMode) {
+            gDecodeTestParameters.push_back(
+                    std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false, mode));
+            gDecodeTestParameters.push_back(
+                    std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true, mode));
+        }
         gDecodeTestParameters.push_back(
-                std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false));
+                std::make_tuple(std::get<0>(params), std::get<1>(params), 1, false, NO_SURFACE));
         gDecodeTestParameters.push_back(
-                std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true));
+                std::make_tuple(std::get<0>(params), std::get<1>(params), 1, true, NO_SURFACE));
         gDecodeTestParameters.push_back(
-                std::make_tuple(std::get<0>(params), std::get<1>(params), 1, false));
+                std::make_tuple(std::get<0>(params), std::get<1>(params), 2, false, NO_SURFACE));
         gDecodeTestParameters.push_back(
-                std::make_tuple(std::get<0>(params), std::get<1>(params), 1, true));
-        gDecodeTestParameters.push_back(
-                std::make_tuple(std::get<0>(params), std::get<1>(params), 2, false));
-        gDecodeTestParameters.push_back(
-                std::make_tuple(std::get<0>(params), std::get<1>(params), 2, true));
+                std::make_tuple(std::get<0>(params), std::get<1>(params), 2, true, NO_SURFACE));
 
         gCsdFlushTestParameters.push_back(
                 std::make_tuple(std::get<0>(params), std::get<1>(params), true));
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index 6a00edd..a6507e7 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -334,6 +334,12 @@
     int bytesCount = nWidth * nHeight * 3 >> 1;
     int32_t timestampIncr = ENCODER_TIMESTAMP_INCREMENT;
     c2_status_t err = C2_OK;
+
+    // Query component's memory usage flags
+    std::vector<std::unique_ptr<C2Param>> params;
+    C2StreamUsageTuning::input compUsage(0u, 0u);
+    component->query({&compUsage}, {}, C2_DONT_BLOCK, &params);
+
     while (1) {
         if (nFrames == 0) break;
         uint32_t flags = 0;
@@ -384,7 +390,8 @@
         }
         std::shared_ptr<C2GraphicBlock> block;
         err = graphicPool->fetchGraphicBlock(nWidth, nHeight, HAL_PIXEL_FORMAT_YV12,
-                                             {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+                                             {C2MemoryUsage::CPU_READ | compUsage.value,
+                                                 C2MemoryUsage::CPU_WRITE | compUsage.value},
                                              &block);
         if (err != C2_OK) {
             fprintf(stderr, "fetchGraphicBlock failed : %d\n", err);
diff --git a/media/codec2/hidl/client/output.cpp b/media/codec2/hidl/client/output.cpp
index 8cd4934..de34c24 100644
--- a/media/codec2/hidl/client/output.cpp
+++ b/media/codec2/hidl/client/output.cpp
@@ -181,7 +181,7 @@
                                   int maxDequeueBufferCount,
                                   std::shared_ptr<V1_2::SurfaceSyncObj> *syncObj) {
     uint64_t consumerUsage = 0;
-    if (igbp->getConsumerUsage(&consumerUsage) != OK) {
+    if (igbp && igbp->getConsumerUsage(&consumerUsage) != OK) {
         ALOGW("failed to get consumer usage");
     }
 
@@ -254,6 +254,9 @@
         mBqId = bqId;
         mOwner = std::make_shared<int>(0);
         mMaxDequeueBufferCount = maxDequeueBufferCount;
+        if (igbp == nullptr) {
+            return false;
+        }
         for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) {
             if (mBqId == 0 || !mBuffers[i]) {
                 continue;
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 691bab1..4070478 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -491,7 +491,7 @@
                         * align(mHeight, 64) / plane.rowSampling;
             }
 
-            if ((maxPtr - minPtr + 1) <= planeSize) {
+            if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
                 // FIXME: this is risky as reading/writing data out of bound results
                 //        in an undefined behavior, but gralloc does assume a
                 //        contiguous mapping
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 0e2bdab..cae81f0 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/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d94cecf..9ae7ddb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2856,10 +2856,43 @@
 
     CHECK(msg->findInt32("payload-type", &payloadType));
 
+    int32_t rtpSeq = 0, rtpTime = 0;
+    int64_t ntpTime = 0, recvTimeUs = 0;
+
     Parcel in;
     in.writeInt32(payloadType);
 
     switch (payloadType) {
+        case ARTPSource::RTP_FIRST_PACKET:
+        {
+            CHECK(msg->findInt32("rtp-time", &rtpTime));
+            CHECK(msg->findInt32("rtp-seq-num", &rtpSeq));
+            CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
+            in.writeInt32(rtpTime);
+            in.writeInt32(rtpSeq);
+            in.writeInt32(recvTimeUs >> 32);
+            in.writeInt32(recvTimeUs & 0xFFFFFFFF);
+            break;
+        }
+        case ARTPSource::RTCP_FIRST_PACKET:
+        {
+            CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
+            in.writeInt32(recvTimeUs >> 32);
+            in.writeInt32(recvTimeUs & 0xFFFFFFFF);
+            break;
+        }
+        case ARTPSource::RTCP_SR:
+        {
+            CHECK(msg->findInt32("rtp-time", &rtpTime));
+            CHECK(msg->findInt64("ntp-time", &ntpTime));
+            CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
+            in.writeInt32(rtpTime);
+            in.writeInt32(ntpTime >> 32);
+            in.writeInt32(ntpTime & 0xFFFFFFFF);
+            in.writeInt32(recvTimeUs >> 32);
+            in.writeInt32(recvTimeUs & 0xFFFFFFFF);
+            break;
+        }
         case ARTPSource::RTCP_TSFB:   // RTCP TSFB
         case ARTPSource::RTCP_PSFB:   // RTCP PSFB
         case ARTPSource::RTP_AUTODOWN:
@@ -2882,6 +2915,8 @@
             int32_t feedbackType, bitrate;
             int32_t highestSeqNum, baseSeqNum, prevExpected;
             int32_t numBufRecv, prevNumBufRecv;
+            int32_t latestRtpTime, jbTimeMs, rtpRtcpSrTimeGapMs;
+            int64_t recvTimeUs;
             CHECK(msg->findInt32("feedback-type", &feedbackType));
             CHECK(msg->findInt32("bit-rate", &bitrate));
             CHECK(msg->findInt32("highest-seq-num", &highestSeqNum));
@@ -2889,6 +2924,10 @@
             CHECK(msg->findInt32("prev-expected", &prevExpected));
             CHECK(msg->findInt32("num-buf-recv", &numBufRecv));
             CHECK(msg->findInt32("prev-num-buf-recv", &prevNumBufRecv));
+            CHECK(msg->findInt32("latest-rtp-time", &latestRtpTime));
+            CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
+            CHECK(msg->findInt32("rtp-jitter-time-ms", &jbTimeMs));
+            CHECK(msg->findInt32("rtp-rtcpsr-time-gap-ms", &rtpRtcpSrTimeGapMs));
             in.writeInt32(feedbackType);
             in.writeInt32(bitrate);
             in.writeInt32(highestSeqNum);
@@ -2896,6 +2935,11 @@
             in.writeInt32(prevExpected);
             in.writeInt32(numBufRecv);
             in.writeInt32(prevNumBufRecv);
+            in.writeInt32(latestRtpTime);
+            in.writeInt32(recvTimeUs >> 32);
+            in.writeInt32(recvTimeUs & 0xFFFFFFFF);
+            in.writeInt32(jbTimeMs);
+            in.writeInt32(rtpRtcpSrTimeGapMs);
             break;
         }
         case ARTPSource::RTP_CVO:
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
index d2d978a..4d6a483 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -395,23 +395,13 @@
                 CHECK(msg->findInt64("ntp-time", (int64_t *)&ntpTime));
 
                 onTimeUpdate(trackIndex, rtpTime, ntpTime);
-                break;
-            }
-
-            int32_t firstRTCP;
-            if (msg->findInt32("first-rtcp", &firstRTCP)) {
-                // There won't be an access unit here, it's just a notification
-                // that the data communication worked since we got the first
-                // rtcp packet.
-                ALOGV("first-rtcp");
-                break;
             }
 
             int32_t IMSRxNotice;
             if (msg->findInt32("rtcp-event", &IMSRxNotice)) {
-                int32_t payloadType, feedbackType;
+                int32_t payloadType = 0, feedbackType = 0;
                 CHECK(msg->findInt32("payload-type", &payloadType));
-                CHECK(msg->findInt32("feedback-type", &feedbackType));
+                msg->findInt32("feedback-type", &feedbackType);
 
                 sp<AMessage> notify = dupNotify();
                 notify->setInt32("what", kWhatIMSRxNotice);
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
index 5b724aa..b9fb041 100644
--- a/media/libstagefright/CodecBase.cpp
+++ b/media/libstagefright/CodecBase.cpp
@@ -40,4 +40,31 @@
     buf->size = size;
 }
 
+status_t CodecBase::querySupportedParameters(std::vector<std::string> *names) {
+    if (names == nullptr) {
+        return BAD_VALUE;
+    }
+    names->clear();
+    return OK;
+}
+
+status_t CodecBase::describeParameter(const std::string &, CodecParameterDescriptor *) {
+    return ERROR_UNSUPPORTED;
+}
+
+status_t CodecBase::subscribeToParameters(const std::vector<std::string> &names) {
+    if (names.empty()) {
+        return OK;
+    }
+    return ERROR_UNSUPPORTED;
+}
+
+status_t CodecBase::unsubscribeFromParameters(const std::vector<std::string> &names) {
+    if (names.empty()) {
+        return OK;
+    }
+    return ERROR_UNSUPPORTED;
+}
+
+
 } // namespace android
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index efb2f86..48721ec 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -252,9 +252,7 @@
      *         INVALID_OPERATION if already released;
      *         ERROR_UNSUPPORTED if not supported.
      */
-    virtual status_t querySupportedParameters([[maybe_unused]] std::vector<std::string> *names) {
-        return ERROR_UNSUPPORTED;
-    }
+    virtual status_t querySupportedParameters(std::vector<std::string> *names);
     /**
      * Fill |desc| with description of the parameter with |name|.
      *
@@ -267,10 +265,8 @@
      *         ERROR_UNSUPPORTED if not supported.
      */
     virtual status_t describeParameter(
-            [[maybe_unused]] const std::string &name,
-            [[maybe_unused]] CodecParameterDescriptor *desc) {
-        return ERROR_UNSUPPORTED;
-    }
+            const std::string &name,
+            CodecParameterDescriptor *desc);
     /**
      * Subscribe to parameters in |names| and get output format change event
      * when they change.
@@ -281,10 +277,7 @@
      *         INVALID_OPERATION if already released;
      *         ERROR_UNSUPPORTED if not supported.
      */
-    virtual status_t subscribeToParameters(
-            [[maybe_unused]] const std::vector<std::string> &names) {
-        return ERROR_UNSUPPORTED;
-    }
+    virtual status_t subscribeToParameters(const std::vector<std::string> &names);
     /**
      * Unsubscribe from parameters in |names| and no longer get
      * output format change event when they change.
@@ -295,10 +288,7 @@
      *         INVALID_OPERATION if already released;
      *         ERROR_UNSUPPORTED if not supported.
      */
-    virtual status_t unsubscribeFromParameters(
-            [[maybe_unused]] const std::vector<std::string> &names) {
-        return ERROR_UNSUPPORTED;
-    }
+    virtual status_t unsubscribeFromParameters(const std::vector<std::string> &names);
 
     typedef CodecBase *(*CreateCodecFunc)(void);
     typedef PersistentSurface *(*CreateInputSurfaceFunc)(void);
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index e1cc5ec..3f4d662 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -44,6 +44,7 @@
       mNextExpectedSeqNo(0),
       mAccessUnitDamaged(false),
       mFirstIFrameProvided(false),
+      mLastCvo(-1),
       mLastIFrameProvidedAtMs(0),
       mLastRtpTimeJitterDataUs(0),
       mWidth(0),
@@ -137,7 +138,7 @@
     }
     source->putInterArrivalJitterData(rtpTime, nowTimeUs);
 
-    const int64_t startTimeMs = source->mFirstSysTime / 1000;
+    const int64_t startTimeMs = source->mSysAnchorTime / 1000;
     const int64_t nowTimeMs = nowTimeUs / 1000;
     const int32_t staticJitterTimeMs = source->getStaticJitterTimeMs();
     const int32_t baseJitterTimeMs = source->getBaseJitterTimeMs();
@@ -195,33 +196,38 @@
 
     if (!isExpired) {
         ALOGV("buffering in jitter buffer.");
+        // set an alarm for jitter buffer time expiration.
+        // adding 1ms because jitter buffer time is keep changing.
+        int64_t expTimeUs = (RtpToMs(std::abs(diffTimeRtp), clockRate) + 1) * 1000;
+        source->setJbAlarmTime(nowTimeUs, expTimeUs);
         return NOT_ENOUGH_DATA;
     }
 
     if (isFirstLineBroken) {
-        if (isSecondLineBroken) {
-            int64_t totalDiffTimeMs = RtpToMs(diffTimeRtp + jitterTimeRtp, clockRate);
-            ALOGE("buffer too late... \t RTP diff from exp =%lld \t MS diff from stamp = %lld\t\t"
+        int64_t totalDiffTimeMs = RtpToMs(diffTimeRtp + jitterTimeRtp, clockRate);
+        String8 info;
+        info.appendFormat("RTP diff from exp =%lld \t MS diff from stamp = %lld\t\t"
                     "Seq# %d \t ExpSeq# %d \t"
                     "JitterMs %d + (%d + %d * %.3f)",
                     (long long)diffTimeRtp, (long long)totalDiffTimeMs,
                     buffer->int32Data(), mNextExpectedSeqNo,
                     jitterTimeMs, tryJbTimeMs, dynamicJbTimeMs, JITTER_MULTIPLE);
+        if (isSecondLineBroken) {
+            ALOGE("%s", info.string());
             printNowTimeMs(startTimeMs, nowTimeMs, playedTimeMs);
             printRTPTime(rtpTime, playedTimeRtp, expiredTimeRtp, isExpired);
 
-            mNextExpectedSeqNo = pickProperSeq(queue, firstRTPTime, playedTimeRtp, jitterTimeRtp);
         }  else {
-            ALOGW("=== WARNING === buffer arrived after %d + %d = %d ms === WARNING === ",
-                    jitterTimeMs, tryJbTimeMs, jitterTimeMs + tryJbTimeMs);
+            ALOGW("%s", info.string());
         }
     }
 
     if (mNextExpectedSeqNoValid) {
-        int32_t size = queue->size();
+        mNextExpectedSeqNo = pickStartSeq(queue, firstRTPTime, playedTimeRtp, jitterTimeRtp);
         int32_t cntRemove = deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
 
         if (cntRemove > 0) {
+            int32_t size = queue->size();
             source->noticeAbandonBuffer(cntRemove);
             ALOGW("delete %d of %d buffers", cntRemove, size);
         }
@@ -441,7 +447,6 @@
     uint32_t rtpTimeStartAt;
     CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTimeStartAt));
     uint32_t startSeqNo = buffer->int32Data();
-    bool pFrame = nalType == 0x1;
 
     if (data[1] & 0x40) {
         // Huh? End bit also set on the first buffer.
@@ -451,8 +456,6 @@
         complete = true;
     } else {
         List<sp<ABuffer> >::iterator it = ++queue->begin();
-        int32_t connected = 1;
-        bool snapped = false;
         while (it != queue->end()) {
             ALOGV("sequence length %zu", totalCount);
 
@@ -463,33 +466,26 @@
 
             if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
                 ALOGD("sequence not complete, expected seqNo %u, got %u, nalType %u",
-                     expectedSeqNo, (unsigned)buffer->int32Data(), nalType);
-                snapped = true;
-
-                if (!pFrame) {
-                    return WRONG_SEQUENCE_NUMBER;
-                }
-            }
-
-            if (!snapped) {
-                connected++;
+                     expectedSeqNo, (uint32_t)buffer->int32Data(), nalType);
             }
 
             uint32_t rtpTime;
             CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
-            if (size < 2
-                    || data[0] != indicator
+            if (size < 2) {
+                ALOGV("Ignoring malformed FU buffer.");
+                it = queue->erase(it);
+                continue;
+            }
+            if (data[0] != indicator
                     || (data[1] & 0x1f) != nalType
                     || (data[1] & 0x80)
                     || rtpTime != rtpTimeStartAt) {
-                ALOGV("Ignoring malformed FU buffer.");
-
-                // Delete the whole start of the FU.
-
-                mNextExpectedSeqNo = expectedSeqNo + 1;
-                deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
-
-                return MALFORMED_PACKET;
+                // Assembler already have given enough time by jitter buffer
+                ALOGD("Seems another frame. Incomplete frame [%d ~ %d) \t %d FUs",
+                        startSeqNo, expectedSeqNo, (int)queue->distance(queue->begin(), it));
+                expectedSeqNo = (uint32_t)buffer->int32Data();
+                complete = true;
+                break;
             }
 
             totalSize += size - 2;
@@ -498,14 +494,6 @@
             expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
 
             if (data[1] & 0x40) {
-                if (pFrame && !recycleUnit(startSeqNo, expectedSeqNo,
-                            connected, totalCount, 0.5f)) {
-                    mNextExpectedSeqNo = expectedSeqNo;
-                    deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
-
-                    return MALFORMED_PACKET;
-                }
-
                 // This is the last fragment.
                 complete = true;
                 break;
@@ -557,6 +545,9 @@
 
     if (cvo >= 0) {
         unit->meta()->setInt32("cvo", cvo);
+        mLastCvo = cvo;
+    } else if (mLastCvo >= 0) {
+        unit->meta()->setInt32("cvo", mLastCvo);
     }
     if (source != nullptr) {
         unit->meta()->setObject("source", source);
@@ -621,35 +612,32 @@
     msg->post();
 }
 
-int32_t AAVCAssembler::pickProperSeq(const Queue *queue,
+int32_t AAVCAssembler::pickStartSeq(const Queue *queue,
         uint32_t first, int64_t play, int64_t jit) {
+    // pick the first sequence number has the start bit.
     sp<ABuffer> buffer = *(queue->begin());
-    int32_t nextSeqNo = buffer->int32Data();
+    int32_t firstSeqNo = buffer->int32Data();
 
-    Queue::const_iterator it = queue->begin();
-    while (it != queue->end()) {
-        int64_t rtpTime = findRTPTime(first, *it);
-        // if pkt in time exists, that should be the next pivot
+    // This only works for FU-A type & non-start sequence
+    unsigned nalType = buffer->data()[0] & 0x1f;
+    if (nalType != 28 || buffer->data()[1] & 0x80) {
+        return firstSeqNo;
+    }
+
+    for (auto it : *queue) {
+        const uint8_t *data = it->data();
+        int64_t rtpTime = findRTPTime(first, it);
         if (rtpTime + jit >= play) {
-            nextSeqNo = (*it)->int32Data();
             break;
         }
-        it++;
+        if ((data[1] & 0x80)) {
+            const int32_t seqNo = it->int32Data();
+            ALOGE("finding [HEAD] pkt. \t Seq# (%d ~ )[%d", firstSeqNo, seqNo);
+            firstSeqNo = seqNo;
+            break;
+        }
     }
-    return nextSeqNo;
-}
-
-bool AAVCAssembler::recycleUnit(uint32_t start, uint32_t end, uint32_t connected,
-        size_t avail, float goodRatio) {
-    float total = end - start;
-    float valid = connected;
-    float exist = avail;
-    bool isRecycle = (valid / total) >= goodRatio;
-
-    ALOGV("checking p-frame losses.. recvBufs %f valid %f diff %f recycle? %d",
-            exist, valid, total, isRecycle);
-
-    return isRecycle;
+    return firstSeqNo;
 }
 
 int32_t AAVCAssembler::deleteUnitUnderSeq(Queue *queue, uint32_t seq) {
diff --git a/media/libstagefright/rtsp/AAVCAssembler.h b/media/libstagefright/rtsp/AAVCAssembler.h
index 8d19773..2f8b8ba 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.h
+++ b/media/libstagefright/rtsp/AAVCAssembler.h
@@ -22,6 +22,7 @@
 
 #include <utils/List.h>
 #include <utils/RefBase.h>
+#include <utils/String8.h>
 
 namespace android {
 
@@ -47,6 +48,7 @@
     uint32_t mNextExpectedSeqNo;
     bool mAccessUnitDamaged;
     bool mFirstIFrameProvided;
+    int32_t mLastCvo;
     uint64_t mLastIFrameProvidedAtMs;
     int64_t mLastRtpTimeJitterDataUs;
     int32_t mWidth;
@@ -64,9 +66,7 @@
 
     void submitAccessUnit();
 
-    int32_t pickProperSeq(const Queue *q, uint32_t first, int64_t play, int64_t jit);
-    bool recycleUnit(uint32_t start, uint32_t end, uint32_t connected,
-            size_t avail, float goodRatio);
+    int32_t pickStartSeq(const Queue *q, uint32_t first, int64_t play, int64_t jit);
     int32_t deleteUnitUnderSeq(Queue *q, uint32_t seq);
 
     DISALLOW_EVIL_CONSTRUCTORS(AAVCAssembler);
diff --git a/media/libstagefright/rtsp/AHEVCAssembler.cpp b/media/libstagefright/rtsp/AHEVCAssembler.cpp
index d32e85d..b240339 100644
--- a/media/libstagefright/rtsp/AHEVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AHEVCAssembler.cpp
@@ -51,6 +51,7 @@
       mNextExpectedSeqNo(0),
       mAccessUnitDamaged(false),
       mFirstIFrameProvided(false),
+      mLastCvo(-1),
       mLastIFrameProvidedAtMs(0),
       mLastRtpTimeJitterDataUs(0),
       mWidth(0),
@@ -147,7 +148,7 @@
     }
     source->putInterArrivalJitterData(rtpTime, nowTimeUs);
 
-    const int64_t startTimeMs = source->mFirstSysTime / 1000;
+    const int64_t startTimeMs = source->mSysAnchorTime / 1000;
     const int64_t nowTimeMs = nowTimeUs / 1000;
     const int32_t staticJitterTimeMs = source->getStaticJitterTimeMs();
     const int32_t baseJitterTimeMs = source->getBaseJitterTimeMs();
@@ -205,33 +206,38 @@
 
     if (!isExpired) {
         ALOGV("buffering in jitter buffer.");
+        // set an alarm for jitter buffer time expiration.
+        // adding 1ms because jitter buffer time is keep changing.
+        int64_t expTimeUs = (RtpToMs(std::abs(diffTimeRtp), clockRate) + 1) * 1000;
+        source->setJbAlarmTime(nowTimeUs, expTimeUs);
         return NOT_ENOUGH_DATA;
     }
 
     if (isFirstLineBroken) {
-        if (isSecondLineBroken) {
-            int64_t totalDiffTimeMs = RtpToMs(diffTimeRtp + jitterTimeRtp, clockRate);
-            ALOGE("buffer too late... \t RTP diff from exp =%lld \t MS diff from stamp = %lld\t\t"
+        int64_t totalDiffTimeMs = RtpToMs(diffTimeRtp + jitterTimeRtp, clockRate);
+        String8 info;
+        info.appendFormat("RTP diff from exp =%lld \t MS diff from stamp = %lld\t\t"
                     "Seq# %d \t ExpSeq# %d \t"
                     "JitterMs %d + (%d + %d * %.3f)",
                     (long long)diffTimeRtp, (long long)totalDiffTimeMs,
                     buffer->int32Data(), mNextExpectedSeqNo,
                     jitterTimeMs, tryJbTimeMs, dynamicJbTimeMs, JITTER_MULTIPLE);
+        if (isSecondLineBroken) {
+            ALOGE("%s", info.string());
             printNowTimeMs(startTimeMs, nowTimeMs, playedTimeMs);
             printRTPTime(rtpTime, playedTimeRtp, expiredTimeRtp, isExpired);
 
-            mNextExpectedSeqNo = pickProperSeq(queue, firstRTPTime, playedTimeRtp, jitterTimeRtp);
         }  else {
-            ALOGW("=== WARNING === buffer arrived after %d + %d = %d ms === WARNING === ",
-                    jitterTimeMs, tryJbTimeMs, jitterTimeMs + tryJbTimeMs);
+            ALOGW("%s", info.string());
         }
     }
 
     if (mNextExpectedSeqNoValid) {
-        int32_t size = queue->size();
+        mNextExpectedSeqNo = pickStartSeq(queue, firstRTPTime, playedTimeRtp, jitterTimeRtp);
         int32_t cntRemove = deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
 
         if (cntRemove > 0) {
+            int32_t size = queue->size();
             source->noticeAbandonBuffer(cntRemove);
             ALOGW("delete %d of %d buffers", cntRemove, size);
         }
@@ -466,7 +472,6 @@
     uint32_t rtpTimeStartAt;
     CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTimeStartAt));
     uint32_t startSeqNo = buffer->int32Data();
-    bool pFrame = (nalType < 0x10);
 
     if (data[2] & 0x40) {
         // Huh? End bit also set on the first buffer.
@@ -476,8 +481,6 @@
         complete = true;
     } else {
         List<sp<ABuffer> >::iterator it = ++queue->begin();
-        int32_t connected = 1;
-        bool snapped = false;
         while (it != queue->end()) {
             ALOGV("sequence length %zu", totalCount);
 
@@ -488,33 +491,26 @@
 
             if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
                 ALOGV("sequence not complete, expected seqNo %u, got %u, nalType %u",
-                     expectedSeqNo, (uint32_t)buffer->int32Data(), nalType);
-                snapped = true;
-
-                if (!pFrame) {
-                    return WRONG_SEQUENCE_NUMBER;
-                }
-            }
-
-            if (!snapped) {
-                connected++;
+                     expectedSeqNo, (unsigned)buffer->int32Data(), nalType);
             }
 
             uint32_t rtpTime;
             CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
-            if (size < 3
-                    || ((data[0] >> 1) & H265_NALU_MASK) != indicator
+            if (size < 3) {
+                ALOGV("Ignoring malformed FU buffer.");
+                it = queue->erase(it);
+                continue;
+            }
+            if (((data[0] >> 1) & H265_NALU_MASK) != indicator
                     || (data[2] & H265_NALU_MASK) != nalType
                     || (data[2] & 0x80)
                     || rtpTime != rtpTimeStartAt) {
-                ALOGV("Ignoring malformed FU buffer.");
-
-                // Delete the whole start of the FU.
-
-                mNextExpectedSeqNo = expectedSeqNo + 1;
-                deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
-
-                return MALFORMED_PACKET;
+                // Assembler already have given enough time by jitter buffer
+                ALOGD("Seems another frame. Incomplete frame [%d ~ %d) \t %d FUs",
+                        startSeqNo, expectedSeqNo, (int)queue->distance(queue->begin(), it));
+                expectedSeqNo = (uint32_t)buffer->int32Data();
+                complete = true;
+                break;
             }
 
             totalSize += size - 3;
@@ -523,13 +519,6 @@
             expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
 
             if (data[2] & 0x40) {
-                if (pFrame && !recycleUnit(startSeqNo, expectedSeqNo,
-                        connected, totalCount, 0.5f)) {
-                    mNextExpectedSeqNo = expectedSeqNo;
-                    deleteUnitUnderSeq(queue, mNextExpectedSeqNo);
-
-                    return MALFORMED_PACKET;
-                }
                 // This is the last fragment.
                 complete = true;
                 break;
@@ -579,6 +568,9 @@
 
     if (cvo >= 0) {
         unit->meta()->setInt32("cvo", cvo);
+        mLastCvo = cvo;
+    } else if (mLastCvo >= 0) {
+        unit->meta()->setInt32("cvo", mLastCvo);
     }
 
     addSingleNALUnit(unit);
@@ -635,35 +627,32 @@
     msg->post();
 }
 
-int32_t AHEVCAssembler::pickProperSeq(const Queue *queue,
+int32_t AHEVCAssembler::pickStartSeq(const Queue *queue,
         uint32_t first, int64_t play, int64_t jit) {
+    // pick the first sequence number has the start bit.
     sp<ABuffer> buffer = *(queue->begin());
-    int32_t nextSeqNo = buffer->int32Data();
+    int32_t firstSeqNo = buffer->int32Data();
 
-    Queue::const_iterator it = queue->begin();
-    while (it != queue->end()) {
-        int64_t rtpTime = findRTPTime(first, *it);
-        // if pkt in time exists, that should be the next pivot
+    // This only works for FU-A type & non-start sequence
+    unsigned nalType = buffer->data()[0] & 0x1f;
+    if (nalType != 28 || buffer->data()[2] & 0x80) {
+        return firstSeqNo;
+    }
+
+    for (auto it : *queue) {
+        const uint8_t *data = it->data();
+        int64_t rtpTime = findRTPTime(first, it);
         if (rtpTime + jit >= play) {
-            nextSeqNo = (*it)->int32Data();
             break;
         }
-        it++;
+        if ((data[2] & 0x80)) {
+            const int32_t seqNo = it->int32Data();
+            ALOGE("finding [HEAD] pkt. \t Seq# (%d ~ )[%d", firstSeqNo, seqNo);
+            firstSeqNo = seqNo;
+            break;
+        }
     }
-    return nextSeqNo;
-}
-
-bool AHEVCAssembler::recycleUnit(uint32_t start, uint32_t end,  uint32_t connected,
-         size_t avail, float goodRatio) {
-    float total = end - start;
-    float valid = connected;
-    float exist = avail;
-    bool isRecycle = (valid / total) >= goodRatio;
-
-    ALOGV("checking p-frame losses.. recvBufs %f valid %f diff %f recycle? %d",
-            exist, valid, total, isRecycle);
-
-    return isRecycle;
+    return firstSeqNo;
 }
 
 int32_t AHEVCAssembler::deleteUnitUnderSeq(Queue *queue, uint32_t seq) {
diff --git a/media/libstagefright/rtsp/AHEVCAssembler.h b/media/libstagefright/rtsp/AHEVCAssembler.h
index 68777a7..9575d8c 100644
--- a/media/libstagefright/rtsp/AHEVCAssembler.h
+++ b/media/libstagefright/rtsp/AHEVCAssembler.h
@@ -22,6 +22,7 @@
 
 #include <utils/List.h>
 #include <utils/RefBase.h>
+#include <utils/String8.h>
 
 namespace android {
 
@@ -48,6 +49,7 @@
     uint32_t mNextExpectedSeqNo;
     bool mAccessUnitDamaged;
     bool mFirstIFrameProvided;
+    int32_t mLastCvo;
     uint64_t mLastIFrameProvidedAtMs;
     int64_t mLastRtpTimeJitterDataUs;
     int32_t mWidth;
@@ -65,9 +67,7 @@
 
     void submitAccessUnit();
 
-    int32_t pickProperSeq(const Queue *q, uint32_t first, int64_t play, int64_t jit);
-    bool recycleUnit(uint32_t start, uint32_t end, uint32_t connected,
-             size_t avail, float goodRatio);
+    int32_t pickStartSeq(const Queue *q, uint32_t first, int64_t play, int64_t jit);
     int32_t deleteUnitUnderSeq(Queue *queue, uint32_t seq);
 
     DISALLOW_EVIL_CONSTRUCTORS(AHEVCAssembler);
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index a4da433..ffccbb1 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -18,9 +18,7 @@
 #define LOG_TAG "ARTPConnection"
 #include <utils/Log.h>
 
-#include "ARTPAssembler.h"
 #include "ARTPConnection.h"
-
 #include "ARTPSource.h"
 #include "ASessionDescription.h"
 
@@ -306,6 +304,12 @@
             break;
         }
 
+        case kWhatAlarmStream:
+        {
+            onAlarmStream(msg);
+            break;
+        }
+
         case kWhatInjectPacket:
         {
             onInjectPacket(msg);
@@ -463,14 +467,16 @@
 
             if (err == -ECONNRESET) {
                 // socket failure, this stream is dead, Jim.
-                sp<AMessage> notify = it->mNotifyMsg->dup();
-                notify->setInt32("rtcp-event", 1);
-                notify->setInt32("payload-type", 400);
-                notify->setInt32("feedback-type", 1);
-                notify->setInt32("sender", it->mSources.valueAt(0)->getSelfID());
-                notify->post();
+                for (size_t i = 0; i < it->mSources.size(); ++i) {
+                    sp<AMessage> notify = it->mNotifyMsg->dup();
+                    notify->setInt32("rtcp-event", 1);
+                    notify->setInt32("payload-type", 400);
+                    notify->setInt32("feedback-type", 1);
+                    notify->setInt32("sender", it->mSources.valueAt(i)->getSelfID());
+                    notify->post();
 
-                ALOGW("failed to receive RTP/RTCP datagram.");
+                    ALOGW("failed to receive RTP/RTCP datagram.");
+                }
                 it = mStreams.erase(it);
                 continue;
             }
@@ -571,6 +577,13 @@
     }
 }
 
+void ARTPConnection::onAlarmStream(const sp<AMessage> msg) {
+    sp<ARTPSource> source = nullptr;
+    if (msg->findObject("source", (sp<android::RefBase>*)&source)) {
+        source->processRTPPacket();
+    }
+}
+
 status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
     ALOGV("receiving %s", receiveRTP ? "RTP" : "RTCP");
 
@@ -656,12 +669,6 @@
 }
 
 status_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
-    if (s->mNumRTPPacketsReceived++ == 0) {
-        sp<AMessage> notify = s->mNotifyMsg->dup();
-        notify->setInt32("first-rtp", true);
-        notify->post();
-    }
-
     size_t size = buffer->size();
 
     if (size < 12) {
@@ -743,9 +750,23 @@
         meta->setInt32("cvo", cvoDegrees);
     }
 
-    buffer->setInt32Data(u16at(&data[2]));
+    int32_t seq = u16at(&data[2]);
+    buffer->setInt32Data(seq);
     buffer->setRange(payloadOffset, size - payloadOffset);
 
+    if (s->mNumRTPPacketsReceived++ == 0) {
+        sp<AMessage> notify = s->mNotifyMsg->dup();
+        notify->setInt32("first-rtp", true);
+        notify->setInt32("rtcp-event", 1);
+        notify->setInt32("payload-type", ARTPSource::RTP_FIRST_PACKET);
+        notify->setInt32("rtp-time", (int32_t)rtpTime);
+        notify->setInt32("rtp-seq-num", seq);
+        notify->setInt64("recv-time-us", ALooper::GetNowUs());
+        notify->post();
+
+        ALOGD("send first-rtp event to upper layer");
+    }
+
     source->processRTPPacket(buffer);
 
     return OK;
@@ -802,14 +823,12 @@
     if (s->mNumRTCPPacketsReceived++ == 0) {
         sp<AMessage> notify = s->mNotifyMsg->dup();
         notify->setInt32("first-rtcp", true);
+        notify->setInt32("rtcp-event", 1);
+        notify->setInt32("payload-type", ARTPSource::RTCP_FIRST_PACKET);
+        notify->setInt64("recv-time-us", ALooper::GetNowUs());
         notify->post();
 
-        ALOGI("send first-rtcp event to upper layer as ImsRxNotice");
-        sp<AMessage> imsNotify = s->mNotifyMsg->dup();
-        imsNotify->setInt32("rtcp-event", 1);
-        imsNotify->setInt32("payload-type", 101);
-        imsNotify->setInt32("feedback-type", 0);
-        imsNotify->post();
+        ALOGD("send first-rtcp event to upper layer");
     }
 
     const uint8_t *data = buffer->data();
@@ -906,7 +925,7 @@
     int64_t nowUs = ALooper::GetNowUs();
     int32_t timeDiff = (nowUs - mLastBitrateReportTimeUs) / 1000000ll;
     int32_t bitrate = mCumulativeBytes * 8 / timeDiff;
-    source->notifyPktInfo(bitrate, true /* isRegular */);
+    source->notifyPktInfo(bitrate, nowUs, true /* isRegular */);
 
     source->byeReceived();
 
@@ -1088,11 +1107,14 @@
                 srcId, info->mSessionDesc, info->mIndex, info->mNotifyMsg);
 
         if (mFlags & kViLTEConnection) {
+            setStaticJitterTimeMs(50);
             source->setPeriodicFIR(false);
         }
 
         source->setSelfID(mSelfID);
         source->setStaticJitterTimeMs(mStaticJitterTimeMs);
+        sp<AMessage> timer = new AMessage(kWhatAlarmStream, this);
+        source->setJbTimer(timer);
         info->mSources.add(srcId, source);
     } else {
         source = info->mSources.valueAt(index);
@@ -1140,7 +1162,7 @@
             for (size_t i = 0; i < s->mSources.size(); ++i) {
                 sp<ARTPSource> source = s->mSources.valueAt(i);
                 if (source->isNeedToEarlyNotify()) {
-                    source->notifyPktInfo(bitrate, false /* isRegular */);
+                    source->notifyPktInfo(bitrate, nowUs, false /* isRegular */);
                     mLastEarlyNotifyTimeUs = nowUs + (1000000ll * 3600 * 24); // after 1 day
                 }
             }
@@ -1171,7 +1193,7 @@
             buffer->setRange(0, 0);
             for (size_t i = 0; i < s->mSources.size(); ++i) {
                 sp<ARTPSource> source = s->mSources.valueAt(i);
-                source->notifyPktInfo(bitrate, true /* isRegular */);
+                source->notifyPktInfo(bitrate, nowUs, true /* isRegular */);
             }
             ++it;
         }
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
index adf9670..36cca31 100644
--- a/media/libstagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -73,6 +73,7 @@
         kWhatRemoveStream,
         kWhatPollStreams,
         kWhatInjectPacket,
+        kWhatAlarmStream,
     };
 
     static const int64_t kSelectTimeoutUs;
@@ -98,6 +99,7 @@
     void onSeekStream(const sp<AMessage> &msg);
     void onRemoveStream(const sp<AMessage> &msg);
     void onPollStreams();
+    void onAlarmStream(const sp<AMessage> msg);
     void onInjectPacket(const sp<AMessage> &msg);
     void onSendReceiverReports();
     void checkRxBitrate(int64_t nowUs);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index f960482..38a370b 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -44,10 +44,11 @@
         uint32_t id,
         const sp<ASessionDescription> &sessionDesc, size_t index,
         const sp<AMessage> &notify)
-    : mFirstSeqNumber(0),
-      mFirstRtpTime(0),
+    : mFirstRtpTime(0),
       mFirstSysTime(0),
       mClockRate(0),
+      mSysAnchorTime(0),
+      mLastSysAnchorTimeUpdatedUs(0),
       mFirstSsrc(0),
       mHighestNackNumber(0),
       mID(id),
@@ -58,9 +59,14 @@
       mPrevNumBuffersReceived(0),
       mPrevExpectedForRR(0),
       mPrevNumBuffersReceivedForRR(0),
+      mLatestRtpTime(0),
       mStaticJbTimeMs(kStaticJitterTimeMs),
-      mLastNTPTime(0),
-      mLastNTPTimeUpdateUs(0),
+      mLastSrRtpTime(0),
+      mLastSrNtpTime(0),
+      mLastSrUpdateTimeUs(0),
+      mIsFirstRtpRtcpGap(true),
+      mAvgRtpRtcpGapMs(0),
+      mAvgUnderlineDelayMs(0),
       mIssueFIRRequests(false),
       mIssueFIRByAssembler(false),
       mLastFIRRequestUs(-1),
@@ -106,6 +112,7 @@
     int32_t clockRate, numChannels;
     ASessionDescription::ParseFormatDesc(desc.c_str(), &clockRate, &numChannels);
     mClockRate = clockRate;
+    mLastJbAlarmTimeUs = 0;
     mJitterCalc = new JitterCalc(mClockRate);
 }
 
@@ -119,20 +126,32 @@
     }
 }
 
+void ARTPSource::processRTPPacket() {
+    if (mAssembler != NULL && !mQueue.empty()) {
+        mAssembler->onPacketReceived(this);
+    }
+}
+
 void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
-    mLastNTPTime = ntpTime;
-    mLastNTPTimeUpdateUs = ALooper::GetNowUs();
+    mLastSrRtpTime = rtpTime;
+    mLastSrNtpTime = ntpTime;
+    mLastSrUpdateTimeUs = ALooper::GetNowUs();
 
     sp<AMessage> notify = mNotify->dup();
     notify->setInt32("time-update", true);
     notify->setInt32("rtp-time", rtpTime);
     notify->setInt64("ntp-time", ntpTime);
+    notify->setInt32("rtcp-event", 1);
+    notify->setInt32("payload-type", RTCP_SR);
+    notify->setInt64("recv-time-us", mLastSrUpdateTimeUs);
     notify->post();
 }
 
 void ARTPSource::timeReset() {
     mFirstRtpTime = 0;
     mFirstSysTime = 0;
+    mSysAnchorTime = 0;
+    mLastSysAnchorTimeUpdatedUs = 0;
     mFirstSsrc = 0;
     mHighestNackNumber = 0;
     mHighestSeqNumber = 0;
@@ -142,25 +161,100 @@
     mPrevNumBuffersReceived = 0;
     mPrevExpectedForRR = 0;
     mPrevNumBuffersReceivedForRR = 0;
-    mLastNTPTime = 0;
-    mLastNTPTimeUpdateUs = 0;
+    mLatestRtpTime = 0;
+    mLastSrRtpTime = 0;
+    mLastSrNtpTime = 0;
+    mLastSrUpdateTimeUs = 0;
+    mIsFirstRtpRtcpGap = true;
+    mAvgRtpRtcpGapMs = 0;
+    mAvgUnderlineDelayMs = 0;
     mIssueFIRByAssembler = false;
     mLastFIRRequestUs = -1;
 }
 
-bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
-    uint32_t seqNum = (uint32_t)buffer->int32Data();
+void ARTPSource::calcTimeGapRtpRtcp(const sp<ABuffer> &buffer, int64_t nowUs) {
+    if (mLastSrUpdateTimeUs == 0) {
+        return;
+    }
 
-    int32_t ssrc = 0;
+    int64_t elapsedMs = (nowUs - mLastSrUpdateTimeUs) / 1000;
+    int64_t elapsedRtpTime = (elapsedMs * (mClockRate / 1000));
+    uint32_t rtpTime;
+    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+    int64_t anchorRtpTime = mLastSrRtpTime + elapsedRtpTime;
+    int64_t rtpTimeGap = anchorRtpTime - rtpTime;
+    // rtpTime can not be faster than it's anchor time.
+    // because rtpTime(of rtp packet) represents it's a frame captured time and
+    // anchorRtpTime(of rtcp:sr packet) represents it's a rtp packetized time.
+    if (rtpTimeGap < 0 || rtpTimeGap > (mClockRate * 60)) {
+        // ignore invalid delay gap such as negative delay or later than 1 min.
+        return;
+    }
+
+    int64_t rtpTimeGapMs = (rtpTimeGap * 1000 / mClockRate);
+    if (mIsFirstRtpRtcpGap) {
+        mIsFirstRtpRtcpGap = false;
+        mAvgRtpRtcpGapMs = rtpTimeGapMs;
+    } else {
+        // This is measuring avg rtp timestamp distance between rtp and rtcp:sr packet.
+        // Rtp timestamp of rtp packet represents it's raw frame captured time.
+        // Rtp timestamp of rtcp:sr packet represents it's packetization time.
+        // So that, this value is showing how much time delayed to be a rtp packet
+        // from a raw frame captured time.
+        // This value maybe referred to know a/v sync and sender's own delay of this media stream.
+        mAvgRtpRtcpGapMs = ((mAvgRtpRtcpGapMs * 15) + rtpTimeGapMs) / 16;
+    }
+}
+
+void ARTPSource::calcUnderlineDelay(const sp<ABuffer> &buffer, int64_t nowUs) {
+    int64_t elapsedMs = (nowUs - mSysAnchorTime) / 1000;
+    int64_t elapsedRtpTime = (elapsedMs * (mClockRate / 1000));
+    int64_t expectedRtpTime = mFirstRtpTime + elapsedRtpTime;
+
+    int32_t rtpTime;
+    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+    int32_t delayMs = (expectedRtpTime - rtpTime) / (mClockRate / 1000);
+
+    mAvgUnderlineDelayMs = ((mAvgUnderlineDelayMs * 15) + delayMs) / 16;
+}
+
+void ARTPSource::adjustAnchorTimeIfRequired(int64_t nowUs) {
+    if (nowUs - mLastSysAnchorTimeUpdatedUs < 1000000L) {
+        return;
+    }
+
+    if (mAvgUnderlineDelayMs < -30) {
+        // adjust underline delay a quarter of desired delay like step by step.
+        mSysAnchorTime += (int64_t)(mAvgUnderlineDelayMs * 1000 / 4);
+        ALOGD("anchor time updated: original(%lld), anchor(%lld), diffMs(%lld)",
+                (long long)mFirstSysTime, (long long)mSysAnchorTime,
+                (long long)(mFirstSysTime - mSysAnchorTime) / 1000);
+
+        mAvgUnderlineDelayMs = 0;
+        mLastSysAnchorTimeUpdatedUs = nowUs;
+
+        // reset a jitter stastics since an anchor time adjusted.
+        mJitterCalc->init(mFirstRtpTime, mSysAnchorTime, 0, mStaticJbTimeMs * 1000);
+    }
+}
+
+bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
+    int64_t nowUs = ALooper::GetNowUs();
+    uint32_t seqNum = (uint32_t)buffer->int32Data();
+    int32_t ssrc = 0, rtpTime = 0;
+
     buffer->meta()->findInt32("ssrc", &ssrc);
+    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+    mLatestRtpTime = rtpTime;
 
     if (mNumBuffersReceived++ == 0 && mFirstSysTime == 0) {
-        uint32_t firstRtpTime;
-        CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&firstRtpTime));
-        mFirstSysTime = ALooper::GetNowUs();
+        mFirstSysTime = nowUs;
+        mSysAnchorTime = nowUs;
+        mLastSysAnchorTimeUpdatedUs = nowUs;
         mHighestSeqNumber = seqNum;
         mBaseSeqNumber = seqNum;
-        mFirstRtpTime = firstRtpTime;
+        mFirstRtpTime = rtpTime;
         mFirstSsrc = ssrc;
         ALOGD("first-rtp arrived: first-rtp-time=%u, sys-time=%lld, seq-num=%u, ssrc=%d",
                 mFirstRtpTime, (long long)mFirstSysTime, mHighestSeqNumber, mFirstSsrc);
@@ -179,6 +273,10 @@
         return false;
     }
 
+    calcTimeGapRtpRtcp(buffer, nowUs);
+    calcUnderlineDelay(buffer, nowUs);
+    adjustAnchorTimeIfRequired(nowUs);
+
     // Only the lower 16-bit of the sequence numbers are transmitted,
     // derive the high-order bits by choosing the candidate closest
     // to the highest sequence number (extended to 32 bits) received so far.
@@ -363,11 +461,11 @@
 
     uint32_t LSR = 0;
     uint32_t DLSR = 0;
-    if (mLastNTPTime != 0) {
-        LSR = (mLastNTPTime >> 16) & 0xffffffff;
+    if (mLastSrNtpTime != 0) {
+        LSR = (mLastSrNtpTime >> 16) & 0xffffffff;
 
         DLSR = (uint32_t)
-            ((ALooper::GetNowUs() - mLastNTPTimeUpdateUs) * 65536.0 / 1E6);
+            ((ALooper::GetNowUs() - mLastSrUpdateTimeUs) * 65536.0 / 1E6);
     }
 
     data[24] = LSR >> 24;
@@ -566,6 +664,35 @@
     mJitterCalc->putInterArrivalData(timeStamp, arrivalTime);
 }
 
+void ARTPSource::setJbTimer(const sp<AMessage> timer) {
+    mJbTimer = timer;
+}
+
+void ARTPSource::setJbAlarmTime(int64_t nowTimeUs, int64_t alarmAfterUs) {
+    if (mJbTimer == NULL) {
+        return;
+    }
+    int64_t alarmTimeUs = nowTimeUs + alarmAfterUs;
+    bool alarm = false;
+    if (mLastJbAlarmTimeUs <= nowTimeUs) {
+        // no more alarm in pending.
+        mLastJbAlarmTimeUs = nowTimeUs + alarmAfterUs;
+        alarm = true;
+    } else if (mLastJbAlarmTimeUs > alarmTimeUs + 5000L) {
+        // bring an alarm forward more than 5ms.
+        mLastJbAlarmTimeUs = alarmTimeUs;
+        alarm = true;
+    } else {
+        // would not set alarm if it is close with before one.
+    }
+
+    if (alarm) {
+        sp<AMessage> notify = mJbTimer->dup();
+        notify->setObject("source", this);
+        notify->post(alarmAfterUs);
+    }
+}
+
 bool ARTPSource::isNeedToEarlyNotify() {
     uint32_t expected = mHighestSeqNumber - mBaseSeqNumber + 1;
     int32_t intervalExpectedInNow = expected - mPrevExpected;
@@ -576,7 +703,7 @@
     return false;
 }
 
-void ARTPSource::notifyPktInfo(int32_t bitrate, bool isRegular) {
+void ARTPSource::notifyPktInfo(int32_t bitrate, int64_t nowUs, bool isRegular) {
     int32_t payloadType = isRegular ? RTP_QUALITY : RTP_QUALITY_EMC;
 
     sp<AMessage> notify = mNotify->dup();
@@ -590,6 +717,11 @@
     notify->setInt32("prev-expected", mPrevExpected);
     notify->setInt32("num-buf-recv", mNumBuffersReceived);
     notify->setInt32("prev-num-buf-recv", mPrevNumBuffersReceived);
+    notify->setInt32("latest-rtp-time", mLatestRtpTime);
+    notify->setInt64("recv-time-us", nowUs);
+    notify->setInt32("rtp-jitter-time-ms",
+            std::max(getBaseJitterTimeMs(), getStaticJitterTimeMs()));
+    notify->setInt32("rtp-rtcpsr-time-gap-ms", (int32_t)mAvgRtpRtcpGapMs);
     notify->post();
 
     if (isRegular) {
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 2d804d8..4984e91 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -31,7 +31,7 @@
 
 namespace android {
 
-const uint32_t kStaticJitterTimeMs = 50;   // 50ms
+const uint32_t kStaticJitterTimeMs = 100;   // 100ms
 
 struct ABuffer;
 struct AMessage;
@@ -49,6 +49,8 @@
         RTCP_FIRST_PACKET = 101,
         RTP_QUALITY = 102,
         RTP_QUALITY_EMC = 103,
+        RTCP_SR = 200,
+        RTCP_RR = 201,
         RTCP_TSFB = 205,
         RTCP_PSFB = 206,
         RTP_CVO = 300,
@@ -56,6 +58,7 @@
     };
 
     void processRTPPacket(const sp<ABuffer> &buffer);
+    void processRTPPacket();
     void timeReset();
     void timeUpdate(uint32_t rtpTime, uint64_t ntpTime);
     void byeReceived();
@@ -77,19 +80,23 @@
     void setStaticJitterTimeMs(const uint32_t jbTimeMs);
     void putBaseJitterData(uint32_t timeStamp, int64_t arrivalTime);
     void putInterArrivalJitterData(uint32_t timeStamp, int64_t arrivalTime);
+    void setJbTimer(const sp<AMessage> timer);
+    void setJbAlarmTime(int64_t nowTimeUs, int64_t alarmAfterUs);
 
     bool isNeedToEarlyNotify();
-    void notifyPktInfo(int32_t bitrate, bool isRegular);
+    void notifyPktInfo(int32_t bitrate, int64_t nowUs, bool isRegular);
     // FIR needs to be sent by missing packet or broken video image.
     void onIssueFIRByAssembler();
 
     void noticeAbandonBuffer(int cnt=1);
 
-    int32_t mFirstSeqNumber;
     uint32_t mFirstRtpTime;
     int64_t mFirstSysTime;
     int32_t mClockRate;
 
+    int64_t mSysAnchorTime;
+    int64_t mLastSysAnchorTimeUpdatedUs;
+
     int32_t mFirstSsrc;
     int32_t mHighestNackNumber;
 
@@ -104,11 +111,14 @@
     uint32_t mPrevExpectedForRR;
     int32_t mPrevNumBuffersReceivedForRR;
 
+    uint32_t mLatestRtpTime;
+
     List<sp<ABuffer> > mQueue;
     sp<ARTPAssembler> mAssembler;
 
     int32_t mStaticJbTimeMs;
     sp<JitterCalc> mJitterCalc;
+    sp<AMessage> mJbTimer;
 
     typedef struct infoNACK {
         uint16_t seqNum;
@@ -121,8 +131,14 @@
     std::map<uint16_t, infoNACK> mNACKMap;
     int getSeqNumToNACK(List<int>& list, int size);
 
-    uint64_t mLastNTPTime;
-    int64_t mLastNTPTimeUpdateUs;
+    uint32_t mLastSrRtpTime;
+    uint64_t mLastSrNtpTime;
+    int64_t mLastSrUpdateTimeUs;
+
+    bool mIsFirstRtpRtcpGap;
+    double mAvgRtpRtcpGapMs;
+    double mAvgUnderlineDelayMs;
+    int64_t mLastJbAlarmTimeUs;
 
     bool mIssueFIRRequests;
     bool mIssueFIRByAssembler;
@@ -131,6 +147,10 @@
 
     sp<AMessage> mNotify;
 
+    void calcTimeGapRtpRtcp(const sp<ABuffer> &buffer, int64_t nowUs);
+    void calcUnderlineDelay(const sp<ABuffer> &buffer, int64_t nowUs);
+    void adjustAnchorTimeIfRequired(int64_t nowUs);
+
     bool queuePacket(const sp<ABuffer> &buffer);
 
     DISALLOW_EVIL_CONSTRUCTORS(ARTPSource);
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 29e263d..11c7aeb 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -204,8 +204,6 @@
     mRTPTimeBase = 0;
     mNumRTPSent = 0;
     mNumRTPOctetsSent = 0;
-    mLastRTPTime = 0;
-    mLastNTPTime = 0;
 
     mOpponentID = 0;
     mBitrate = 192000;
@@ -216,6 +214,7 @@
     mRTPSockNetwork = 0;
 
     mMode = INVALID;
+    mClockRate = 16000;
 }
 
 status_t ARTPWriter::addSource(const sp<MediaSource> &source) {
@@ -265,15 +264,28 @@
         updateSocketNetwork(sockNetwork);
 
     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+        // rfc6184: RTP Payload Format for H.264 Video
+        // The clock rate in the "a=rtpmap" line MUST be 90000.
         mMode = H264;
+        mClockRate = 90000;
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
+        // rfc7798: RTP Payload Format for High Efficiency Video Coding (HEVC)
+        // The clock rate in the "a=rtpmap" line MUST be 90000.
         mMode = H265;
+        mClockRate = 90000;
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
         mMode = H263;
+        // rfc4629: RTP Payload Format for ITU-T Rec. H.263 Video
+        // The clock rate in the "a=rtpmap" line MUST be 90000.
+        mClockRate = 90000;
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
         mMode = AMR_NB;
+        // rfc4867: RTP Payload Format ... (AMR) and (AMR-WB)
+        // The RTP clock rate in "a=rtpmap" MUST be 8000 for AMR and 16000 for AMR-WB
+        mClockRate = 8000;
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
         mMode = AMR_WB;
+        mClockRate = 16000;
     } else {
         TRESPASS();
     }
@@ -646,19 +658,27 @@
     data[6] = (mSourceID >> 8) & 0xff;
     data[7] = mSourceID & 0xff;
 
-    data[8] = mLastNTPTime >> (64 - 8);
-    data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
-    data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
-    data[11] = (mLastNTPTime >> 32) & 0xff;
-    data[12] = (mLastNTPTime >> 24) & 0xff;
-    data[13] = (mLastNTPTime >> 16) & 0xff;
-    data[14] = (mLastNTPTime >> 8) & 0xff;
-    data[15] = mLastNTPTime & 0xff;
+    uint64_t ntpTime = GetNowNTP();
+    data[8] = ntpTime >> (64 - 8);
+    data[9] = (ntpTime >> (64 - 16)) & 0xff;
+    data[10] = (ntpTime >> (64 - 24)) & 0xff;
+    data[11] = (ntpTime >> 32) & 0xff;
+    data[12] = (ntpTime >> 24) & 0xff;
+    data[13] = (ntpTime >> 16) & 0xff;
+    data[14] = (ntpTime >> 8) & 0xff;
+    data[15] = ntpTime & 0xff;
 
-    data[16] = (mLastRTPTime >> 24) & 0xff;
-    data[17] = (mLastRTPTime >> 16) & 0xff;
-    data[18] = (mLastRTPTime >> 8) & 0xff;
-    data[19] = mLastRTPTime & 0xff;
+    // A current rtpTime can be calculated from ALooper::GetNowUs().
+    // This is expecting a timestamp of raw frame from a media source is
+    // on the same time context across components in android media framework
+    // which can be queried by ALooper::GetNowUs().
+    // In other words, ALooper::GetNowUs() is on the same timeline as the time
+    // of kKeyTime in a MediaBufferBase
+    uint32_t rtpTime = getRtpTime(ALooper::GetNowUs());
+    data[16] = (rtpTime >> 24) & 0xff;
+    data[17] = (rtpTime >> 16) & 0xff;
+    data[18] = (rtpTime >> 8) & 0xff;
+    data[19] = rtpTime & 0xff;
 
     data[20] = mNumRTPSent >> 24;
     data[21] = (mNumRTPSent >> 16) & 0xff;
@@ -780,6 +800,13 @@
     return (hi << 32) | lo;
 }
 
+uint32_t ARTPWriter::getRtpTime(int64_t timeUs) {
+    int32_t clockPerMs = mClockRate / 1000;
+    int64_t rtpTime = mRTPTimeBase + (timeUs * clockPerMs / 1000LL);
+
+    return (uint32_t)rtpTime;
+}
+
 void ARTPWriter::dumpSessionDesc() {
     AString sdp;
     sdp = "v=0\r\n";
@@ -981,7 +1008,7 @@
 
     sendVPSSPSPPSIfIFrame(mediaBuf, timeUs);
 
-    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+    uint32_t rtpTime = getRtpTime(timeUs);
 
     CHECK(mediaBuf->range_length() > 0);
     const uint8_t *mediaData =
@@ -1156,9 +1183,6 @@
             offset += size;
         }
     }
-
-    mLastRTPTime = rtpTime;
-    mLastNTPTime = GetNowNTP();
 }
 
 void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
@@ -1170,7 +1194,7 @@
 
     sendSPSPPSIfIFrame(mediaBuf, timeUs);
 
-    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
+    uint32_t rtpTime = getRtpTime(timeUs);
 
     CHECK(mediaBuf->range_length() > 0);
     const uint8_t *mediaData =
@@ -1343,9 +1367,6 @@
             offset += size;
         }
     }
-
-    mLastRTPTime = rtpTime;
-    mLastNTPTime = GetNowNTP();
 }
 
 void ARTPWriter::sendH263Data(MediaBufferBase *mediaBuf) {
@@ -1354,7 +1375,7 @@
     int64_t timeUs;
     CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
 
-    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
+    uint32_t rtpTime = getRtpTime(timeUs);
 
     const uint8_t *mediaData =
         (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
@@ -1405,9 +1426,6 @@
         ++mNumRTPSent;
         mNumRTPOctetsSent += buffer->size() - 12;
     }
-
-    mLastRTPTime = rtpTime;
-    mLastNTPTime = GetNowNTP();
 }
 
 void ARTPWriter::updateCVODegrees(int32_t cvoDegrees) {
@@ -1490,7 +1508,7 @@
 
     int64_t timeUs;
     CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
-    uint32_t rtpTime = mRTPTimeBase + (timeUs / (isWide ? 250 : 125));
+    uint32_t rtpTime = getRtpTime(timeUs);
 
     // hexdump(mediaData, mediaLength);
 
@@ -1564,9 +1582,6 @@
     ++mSeqNo;
     ++mNumRTPSent;
     mNumRTPOctetsSent += buffer->size() - 12;
-
-    mLastRTPTime = rtpTime;
-    mLastNTPTime = GetNowNTP();
 }
 
 void ARTPWriter::makeSocketPairAndBind(String8& localIp, int localPort,
diff --git a/media/libstagefright/rtsp/ARTPWriter.h b/media/libstagefright/rtsp/ARTPWriter.h
index 28d6ec5..2982cf6 100644
--- a/media/libstagefright/rtsp/ARTPWriter.h
+++ b/media/libstagefright/rtsp/ARTPWriter.h
@@ -108,14 +108,13 @@
     MediaBufferBase *mSPSBuf;
     MediaBufferBase *mPPSBuf;
 
+    uint32_t mClockRate;
     uint32_t mSourceID;
     uint32_t mPayloadType;
     uint32_t mSeqNo;
     uint32_t mRTPTimeBase;
     uint32_t mNumRTPSent;
     uint32_t mNumRTPOctetsSent;
-    uint32_t mLastRTPTime;
-    uint64_t mLastNTPTime;
 
     uint32_t mOpponentID;
     uint32_t mBitrate;
@@ -136,6 +135,7 @@
     } mMode;
 
     static uint64_t GetNowNTP();
+    uint32_t getRtpTime(int64_t timeUs);
 
     void initState();
     void onRead(const sp<AMessage> &msg);
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 79b192e..e25658f 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -35,7 +35,6 @@
         "android.hardware.media.omx@1.0",
         "libandroidicu",
         "libfmq",
-        "libbase",
         "libbinder",
         "libhidlbase",
         "liblog",
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index dc1b9b8..58e2d2a 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -18,7 +18,6 @@
 #define LOG_TAG "mediaserver"
 //#define LOG_NDEBUG 0
 
-#include <android-base/properties.h>
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
@@ -43,12 +42,6 @@
     ResourceManagerService::instantiate();
     registerExtensions();
     ::android::hardware::configureRpcThreadpool(16, false);
-
-    if (!android::base::GetBoolProperty("ro.config.low_ram", false)) {
-        // Start the media.transcoding service if the device is not low ram
-        // device.
-        android::base::SetProperty("ctl.start", "media.transcoding");
-    }
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
     ::android::hardware::joinRpcThreadpool();
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/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index ca8e96c..c73c17d 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -393,12 +393,14 @@
                 || outputs.isActiveLocally(
                     toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
                     SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
-        // - for STRATEGY_SONIFICATION:
+
+        bool ringActiveLocally = outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_RING), 0);
+        // - for STRATEGY_SONIFICATION and ringtone active:
         // if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
         // - for STRATEGY_SONIFICATION_RESPECTFUL:
         // if no media is playing on the device, check for mandatory use of "safe" speaker
         // when media would have played on speaker, and the safe speaker path is available
-        if (strategy == STRATEGY_SONIFICATION
+        if (strategy == STRATEGY_SONIFICATION || ringActiveLocally
             || (strategy == STRATEGY_SONIFICATION_RESPECTFUL && !mediaActiveLocally)) {
             devices.replaceDevicesByType(
                     AUDIO_DEVICE_OUT_SPEAKER,
@@ -506,7 +508,7 @@
         switch (commDeviceType) {
         case AUDIO_DEVICE_OUT_BLE_HEADSET:
             device = availableDevices.getDevice(
-                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+                    AUDIO_DEVICE_IN_BLE_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
             break;
         case AUDIO_DEVICE_OUT_SPEAKER:
             device = availableDevices.getFirstExistingDevice({
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 83a4a37..cc2d8e8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5849,12 +5849,11 @@
         // With low-latency playing on speaker, music on WFD, when the first low-latency
         // output is stopped, getNewOutputDevices checks for a product strategy
         // from the list, as STRATEGY_SONIFICATION comes prior to STRATEGY_MEDIA.
-        // If an ALARM, RING or ENFORCED_AUDIBLE stream is supported by the product strategy,
+        // If an ALARM or ENFORCED_AUDIBLE stream is supported by the product strategy,
         // devices are returned for STRATEGY_SONIFICATION without checking whether the
         // stream is associated to the output descriptor.
         if (doGetOutputDevicesForVoice() || outputDesc->isStrategyActive(productStrategy) ||
                ((hasStreamActive(AUDIO_STREAM_ALARM) ||
-                hasStreamActive(AUDIO_STREAM_RING) ||
                 hasStreamActive(AUDIO_STREAM_ENFORCED_AUDIBLE)) &&
                 mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc))) {
             // Retrieval of devices for voice DL is done on primary output profile, cannot
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/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.
     }