Merge "audiopolicy: More XML deserializer refactorings"
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index d73f744..94b5713 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -430,6 +430,7 @@
     ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT,
     ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE,
     ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
+    ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION,
     ANDROID_DEPTH_MAX_DEPTH_SAMPLES,
 });
 
diff --git a/include/media/MediaExtractorPluginHelper.h b/include/media/MediaExtractorPluginHelper.h
index c817b30..a659660 100644
--- a/include/media/MediaExtractorPluginHelper.h
+++ b/include/media/MediaExtractorPluginHelper.h
@@ -129,11 +129,13 @@
         mSource = source->mSource;
     }
 
-    ssize_t readAt(off64_t offset, void *data, size_t size) {
+    virtual ~DataSourceHelper() {}
+
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
         return mSource->readAt(mSource->handle, offset, data, size);
     }
 
-    status_t getSize(off64_t *size) {
+    virtual status_t getSize(off64_t *size) {
         return mSource->getSize(mSource->handle, size);
     }
 
@@ -141,7 +143,7 @@
         return mSource->getUri(mSource->handle, uriString, bufferSize);
     }
 
-    uint32_t flags() {
+    virtual uint32_t flags() {
         return mSource->flags(mSource->handle);
     }
 
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index f52d451..9d2f5d2 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -198,13 +198,14 @@
 // possibly wrapping multiple times to cover all tracks, i.e.
 // Each CachedRangedDataSource caches the sampletable metadata for a single track.
 
-struct CachedRangedDataSource : public DataSourceHelper {
+class CachedRangedDataSource : public DataSourceHelper {
+public:
     explicit CachedRangedDataSource(DataSourceHelper *source);
     virtual ~CachedRangedDataSource();
 
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-    virtual status_t getSize(off64_t *size);
-    virtual uint32_t flags();
+    ssize_t readAt(off64_t offset, void *data, size_t size) override;
+    status_t getSize(off64_t *size) override;
+    uint32_t flags() override;
 
     status_t setCachedRange(off64_t offset, size_t size, bool assumeSourceOwnershipOnSuccess);
 
@@ -236,7 +237,7 @@
 CachedRangedDataSource::~CachedRangedDataSource() {
     clearCache();
     if (mOwnsDataSource) {
-        delete (CachedRangedDataSource*)mSource;
+        delete mSource;
     }
 }
 
@@ -366,7 +367,6 @@
       mMoofFound(false),
       mMdatFound(false),
       mDataSource(source),
-      mCachedSource(NULL),
       mInitCheck(NO_INIT),
       mHeaderTimescale(0),
       mIsQT(false),
@@ -393,9 +393,6 @@
     }
     mPssh.clear();
 
-    if (mCachedSource != mDataSource) {
-        delete mCachedSource;
-    }
     delete mDataSource;
 }
 
@@ -909,8 +906,8 @@
 
                     if (cachedSource->setCachedRange(
                             *offset, chunk_size,
-                            mCachedSource != NULL /* assume ownership on success */) == OK) {
-                        mDataSource = mCachedSource = cachedSource;
+                            true /* assume ownership on success */) == OK) {
+                        mDataSource = cachedSource;
                     } else {
                         delete cachedSource;
                     }
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index ca273e0..b1e04c7 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -33,7 +33,6 @@
 struct AMessage;
 struct CDataSource;
 class DataSourceHelper;
-struct CachedRangedDataSource;
 class SampleTable;
 class String8;
 namespace heif {
@@ -99,7 +98,6 @@
     Vector<Trex> mTrex;
 
     DataSourceHelper *mDataSource;
-    CachedRangedDataSource *mCachedSource;
     status_t mInitCheck;
     uint32_t mHeaderTimescale;
     bool mIsQT;
diff --git a/media/libheif/include/HeifDecoderAPI.h b/media/libheif/include/HeifDecoderAPI.h
index 5183c39..aa10f33 100644
--- a/media/libheif/include/HeifDecoderAPI.h
+++ b/media/libheif/include/HeifDecoderAPI.h
@@ -74,7 +74,7 @@
     int32_t  mRotationAngle;           // Rotation angle, clockwise, should be multiple of 90
     uint32_t mBytesPerPixel;           // Number of bytes for one pixel
     uint32_t mIccSize;                 // Number of bytes in mIccData
-    std::unique_ptr<uint8_t> mIccData; // Actual ICC data, memory is owned by this structure
+    std::unique_ptr<uint8_t[]> mIccData; // Actual ICC data, memory is owned by this structure
 };
 
 /*
diff --git a/media/libmediaextractor/include/media/DataSourceBase.h b/media/libmediaextractor/include/media/DataSourceBase.h
index 51993da..fc620fd 100644
--- a/media/libmediaextractor/include/media/DataSourceBase.h
+++ b/media/libmediaextractor/include/media/DataSourceBase.h
@@ -66,6 +66,12 @@
 
     virtual void close() {};
 
+    virtual void disconnect() {}
+
+    virtual ssize_t getAvailableSize(status_t * /*err*/) {
+        return -1;
+    }
+
 protected:
     virtual ~DataSourceBase() {}
 
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
index 1fe2efa..10e07ea 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
@@ -154,8 +154,8 @@
 enum mediaplayer2_states {
     MEDIAPLAYER2_STATE_IDLE         = 1001,
     MEDIAPLAYER2_STATE_PREPARED     = 1002,
-    MEDIAPLAYER2_STATE_PLAYING      = 1003,
-    MEDIAPLAYER2_STATE_PAUSED       = 1004,
+    MEDIAPLAYER2_STATE_PAUSED       = 1003,
+    MEDIAPLAYER2_STATE_PLAYING      = 1004,
     MEDIAPLAYER2_STATE_ERROR        = 1005,
 };
 
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index bafd32c..d9c9826 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -660,7 +660,7 @@
     Mutex::Autolock _l(mLock);
     if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
         return NO_ERROR;
-    if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_STARTED)) {
+    if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) {
         status_t ret = mPlayer->pause();
         if (ret != NO_ERROR) {
             mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index e51727b..5bd1674 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -969,7 +969,7 @@
                     onResume();
                 }
             } else {
-                onStart();
+                onStart(true /* play */);
             }
             mPausedByClient = false;
             notifyListener(mSrcId, MEDIA2_STARTED, 0, 0);
@@ -1502,6 +1502,9 @@
 
         case kWhatPause:
         {
+            if (!mStarted) {
+                onStart(false /* play */);
+            }
             onPause();
             notifyListener(mSrcId, MEDIA2_PAUSED, 0, 0);
             mPausedByClient = true;
@@ -1575,7 +1578,7 @@
     startPlaybackTimer("onresume");
 }
 
-void NuPlayer2::onStart() {
+void NuPlayer2::onStart(bool play) {
     ALOGV("onStart: mCrypto: %p", mCrypto.get());
 
     if (!mSourceStarted) {
@@ -1649,6 +1652,11 @@
         mRenderer->setVideoFrameRate(rate);
     }
 
+    // Renderer is created in paused state.
+    if (play) {
+        mRenderer->resume();
+    }
+
     if (mVideoDecoder != NULL) {
         mVideoDecoder->setRenderer(mRenderer);
     }
@@ -2472,7 +2480,7 @@
         mRenderer->resume();
     }
 
-    onStart();
+    onStart(true /* play */);
     mPausedByClient = false;
     notifyListener(mSrcId, MEDIA2_STARTED, 0, 0);
 }
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index 77845ac..e55cdbe 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -301,7 +301,7 @@
     void handleFlushComplete(bool audio, bool isDecoder);
     void finishFlushIfPossible();
 
-    void onStart();
+    void onStart(bool play);
     void onResume();
     void onPause();
 
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index b02e3f6..cb4b06d 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -327,9 +327,9 @@
 
     switch (mState) {
         case STATE_PAUSED:
-        case STATE_PREPARED:
             return OK;
 
+        case STATE_PREPARED:
         case STATE_RUNNING:
             mState = STATE_PAUSED;
             mPlayer->pause();
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index 021ddde..c5ce15a 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -115,7 +115,7 @@
       mNotifyCompleteAudio(false),
       mNotifyCompleteVideo(false),
       mSyncQueues(false),
-      mPaused(false),
+      mPaused(true),
       mPauseDrainAudioAllowedUs(0),
       mVideoSampleReceived(false),
       mVideoRenderingStarted(false),
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index c0e65e8..c62c05a 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -501,10 +501,15 @@
         return ERROR_MALFORMED;
     }
 
-    int32_t width, height, stride;
-    CHECK(outputFormat->findInt32("width", &width));
-    CHECK(outputFormat->findInt32("height", &height));
-    CHECK(outputFormat->findInt32("stride", &stride));
+    int32_t width, height, stride, srcFormat;
+    if (!outputFormat->findInt32("width", &width) ||
+            !outputFormat->findInt32("height", &height) ||
+            !outputFormat->findInt32("stride", &stride) ||
+            !outputFormat->findInt32("color-format", &srcFormat)) {
+        ALOGE("format missing dimension or color: %s",
+                outputFormat->debugString().c_str());
+        return ERROR_MALFORMED;
+    }
 
     int32_t crop_left, crop_top, crop_right, crop_bottom;
     if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
@@ -523,9 +528,6 @@
     addFrame(frameMem);
     VideoFrame* frame = static_cast<VideoFrame*>(frameMem->pointer());
 
-    int32_t srcFormat;
-    CHECK(outputFormat->findInt32("color-format", &srcFormat));
-
     ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
 
     uint32_t standard, range, transfer;
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index a0a3a75..f1c6acd 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -271,6 +271,9 @@
     if (libDir) {
         struct dirent* libEntry;
         while ((libEntry = readdir(libDir))) {
+            if (libEntry->d_name[0] == '.') {
+                continue;
+            }
             String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
             void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
             if (libHandle) {
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 8e8c77c..e42d8d0 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -21,7 +21,6 @@
 #include <media/stagefright/NuMediaExtractor.h>
 
 #include "include/ESDS.h"
-#include "include/NuCachedSource2.h"
 
 #include <media/DataSource.h>
 #include <media/MediaSource.h>
@@ -207,10 +206,7 @@
 
 void NuMediaExtractor::disconnect() {
     if (mDataSource != NULL) {
-        // disconnect data source
-        if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
-            static_cast<NuCachedSource2 *>(mDataSource.get())->disconnect();
-        }
+        mDataSource->disconnect();
     }
 }
 
@@ -790,16 +786,13 @@
         int64_t *durationUs, bool *eos) const {
     Mutex::Autolock autoLock(mLock);
 
+    status_t finalStatus;
+    ssize_t cachedDataRemaining =
+        mDataSource->getAvailableSize(&finalStatus);
+
     int64_t bitrate;
-    if ((mDataSource->flags() & DataSource::kIsCachingDataSource)
+    if (cachedDataRemaining >= 0
             && getTotalBitrate(&bitrate)) {
-        sp<NuCachedSource2> cachedSource =
-            static_cast<NuCachedSource2 *>(mDataSource.get());
-
-        status_t finalStatus;
-        size_t cachedDataRemaining =
-            cachedSource->approxDataRemaining(&finalStatus);
-
         *durationUs = cachedDataRemaining * 8000000ll / bitrate;
         *eos = (finalStatus != OK);
         return true;
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index 06b15b3..f352fba 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -79,7 +79,7 @@
 
 static const OMX_U32 kSupportedProfiles[] = {
     OMX_AUDIO_AACObjectLC, OMX_AUDIO_AACObjectHE,  OMX_AUDIO_AACObjectHE_PS,
-    OMX_AUDIO_AACObjectLD, OMX_AUDIO_AACObjectELD,
+    OMX_AUDIO_AACObjectLD, OMX_AUDIO_AACObjectELD, OMX_AUDIO_AACObjectXHE
 };
 
 SoftXAAC::SoftXAAC(const char* name, const OMX_CALLBACKTYPE* callbacks, OMX_PTR appData,
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index c6ef75f..a8adff5 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -125,12 +125,10 @@
 }
 
 void AString::clear() {
-    if (mData && mData != kEmptyString) {
+    if (mData != kEmptyString) {
         free(mData);
-        mData = NULL;
+        mData = (char *)kEmptyString;
     }
-
-    mData = (char *)kEmptyString;
     mSize = 0;
     mAllocSize = 1;
 }
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h b/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
index bac8fa9..a8b88fd 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
@@ -63,38 +63,21 @@
             __FILE__ ":" LITERAL_TO_STRING(__LINE__)    \
             " CHECK(" #condition ") failed.")
 
-#define MAKE_COMPARATOR(suffix,op)                          \
-    template<class A, class B>                              \
-    AString Compare_##suffix(const A &a, const B &b) {      \
-        AString res;                                        \
-        if (!(a op b)) {                                    \
-            res.append(a);                                  \
-            res.append(" vs. ");                            \
-            res.append(b);                                  \
-        }                                                   \
-        return res;                                         \
-    }
-
-MAKE_COMPARATOR(EQ,==)
-MAKE_COMPARATOR(NE,!=)
-MAKE_COMPARATOR(LE,<=)
-MAKE_COMPARATOR(GE,>=)
-MAKE_COMPARATOR(LT,<)
-MAKE_COMPARATOR(GT,>)
-
 #ifdef CHECK_OP
 #undef CHECK_OP
 #endif
 
 #define CHECK_OP(x,y,suffix,op)                                         \
     do {                                                                \
-        AString ___res = Compare_##suffix(x, y);                        \
-        if (!___res.empty()) {                                          \
+        const auto &a = x;                                              \
+        const auto &b = y;                                              \
+        if (!(a op b)) {                                                \
             AString ___full =                                           \
                 __FILE__ ":" LITERAL_TO_STRING(__LINE__)                \
                     " CHECK_" #suffix "( " #x "," #y ") failed: ";      \
-            ___full.append(___res);                                     \
-                                                                        \
+            ___full.append(a);                                          \
+            ___full.append(" vs. ");                                    \
+            ___full.append(b);                                          \
             LOG_ALWAYS_FATAL("%s", ___full.c_str());                    \
         }                                                               \
     } while (false)
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 7eff8eb..86872c5 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -445,7 +445,7 @@
                return -EAGAIN;
             };
             (*accessUnit)->meta()->setInt32(
-                    "trackIndex", mPlaylist->getSelectedIndex());
+                    "track-index", mPlaylist->getSelectedIndex());
             (*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
         } else if (stream == STREAMTYPE_METADATA) {
             HLSTime mdTime((*accessUnit)->meta());
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index f439a1c..f4aab25 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -51,6 +51,10 @@
         return mName;
     }
 
+    ssize_t getAvailableSize(status_t *finalStatus) {
+        return approxDataRemaining(finalStatus);
+    }
+
     ////////////////////////////////////////////////////////////////////////////
 
     size_t cachedSize();
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index f25fc71..ad3c068 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -212,7 +212,6 @@
     uint16_t value = setup->wValue;
     std::vector<char> buf;
     buf.resize(length);
-    int ret = 0;
 
     if (!(type & USB_DIR_IN)) {
         if (::read(mControl, buf.data(), length) != length) {
@@ -225,8 +224,8 @@
         case MTP_REQ_RESET:
         case MTP_REQ_CANCEL:
             errno = ECANCELED;
-            ret = -1;
-            break;
+            return -1;
+        //    break;
         case MTP_REQ_GET_DEVICE_STATUS:
         {
             if (length < sizeof(struct mtp_device_status) + 4) {
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 2f298cf..417f1df 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -83,6 +83,7 @@
         "libgui",
         "libui",
         "libmedia2_jni_core",
+        "libmediandk_utils",
     ],
 
     export_include_dirs: ["include"],
@@ -99,3 +100,44 @@
     symbol_file: "libmediandk.map.txt",
     export_include_dirs: ["include"],
 }
+
+cc_library {
+    name: "libmediandk_utils",
+
+    srcs: [
+        "NdkMediaDataSourceCallbacks.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libstagefright/include",
+        "frameworks/av/media/ndk/include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    shared_libs: [
+        "libstagefright_foundation",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+        diag: {
+            cfi: true,
+        },
+    },
+}
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index ec2aed6..9ea734b 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -32,12 +32,14 @@
 #include <media/IMediaHTTPService.h>
 #include <media/NdkMediaError.h>
 #include <media/NdkMediaDataSource.h>
+#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <mediaplayer2/JavaVMHelper.h>
 #include <mediaplayer2/JMedia2HTTPService.h>
 
 #include "../../libstagefright/include/HTTPBase.h"
 #include "../../libstagefright/include/NuCachedSource2.h"
+#include "NdkMediaDataSourceCallbacksPriv.h"
 
 using namespace android;
 
@@ -188,6 +190,24 @@
 }
 
 EXPORT
+AMediaDataSource* AMediaDataSource_newUri(
+        const char *uri,
+        int numheaders,
+        const char * const *key_values) {
+
+    sp<MediaHTTPService> service = createMediaHttpService(uri, /* version = */ 1);
+    KeyedVector<String8, String8> headers;
+    for (int i = 0; i < numheaders; ++i) {
+        String8 key8(key_values[i * 2]);
+        String8 value8(key_values[i * 2 + 1]);
+        headers.add(key8, value8);
+    }
+
+    sp<DataSource> source = DataSourceFactory::CreateFromURI(service, uri, &headers);
+    return convertDataSourceToAMediaDataSource(source);
+}
+
+EXPORT
 void AMediaDataSource_delete(AMediaDataSource *mSource) {
     ALOGV("dtor");
     if (mSource != NULL) {
diff --git a/media/ndk/NdkMediaDataSourceCallbacks.cpp b/media/ndk/NdkMediaDataSourceCallbacks.cpp
new file mode 100644
index 0000000..4338048
--- /dev/null
+++ b/media/ndk/NdkMediaDataSourceCallbacks.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NdkMediaDataSourceCallbacks"
+
+#include "NdkMediaDataSourceCallbacksPriv.h"
+#include <media/DataSource.h>
+
+namespace android {
+
+ssize_t DataSource_getSize(void *userdata) {
+    DataSource *source = static_cast<DataSource *>(userdata);
+    off64_t size = -1;
+    source->getSize(&size);
+    return size;
+}
+
+ssize_t DataSource_readAt(void *userdata, off64_t offset, void * buf, size_t size) {
+    DataSource *source = static_cast<DataSource *>(userdata);
+    return source->readAt(offset, buf, size);
+}
+
+void DataSource_close(void *userdata) {
+    DataSource *source = static_cast<DataSource *>(userdata);
+    source->close();
+}
+
+}  // namespace android
diff --git a/media/ndk/NdkMediaDataSourceCallbacksPriv.h b/media/ndk/NdkMediaDataSourceCallbacksPriv.h
new file mode 100644
index 0000000..65fb0aa
--- /dev/null
+++ b/media/ndk/NdkMediaDataSourceCallbacksPriv.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_MEDIA_DATA_SOURCE_CALLBACKS_H
+
+#define A_MEDIA_DATA_SOURCE_CALLBACKS_H
+
+#include <media/DataSource.h>
+#include <media/NdkMediaDataSource.h>
+#include <media/NdkMediaError.h>
+#include <sys/types.h>
+
+namespace android {
+
+ssize_t DataSource_getSize(void *userdata);
+
+ssize_t DataSource_readAt(void *userdata, off64_t offset, void * buf, size_t size);
+
+void DataSource_close(void *userdata);
+
+static inline AMediaDataSource* convertDataSourceToAMediaDataSource(const sp<DataSource> &source) {
+    if (source == NULL) {
+        return NULL;
+    }
+    AMediaDataSource *mSource = AMediaDataSource_new();
+    AMediaDataSource_setUserdata(mSource, source.get());
+    AMediaDataSource_setReadAt(mSource, DataSource_readAt);
+    AMediaDataSource_setGetSize(mSource, DataSource_getSize);
+    AMediaDataSource_setClose(mSource, DataSource_close);
+    return mSource;
+}
+
+}  // namespace android
+
+#endif  // A_MEDIA_DATA_SOURCE_CALLBACKS_H
diff --git a/media/ndk/include/media/NdkMediaDataSource.h b/media/ndk/include/media/NdkMediaDataSource.h
index ea5ba0c..021029b 100644
--- a/media/ndk/include/media/NdkMediaDataSource.h
+++ b/media/ndk/include/media/NdkMediaDataSource.h
@@ -86,6 +86,30 @@
  */
 AMediaDataSource* AMediaDataSource_new() __INTRODUCED_IN(28);
 
+#if __ANDROID_API__ >= 29
+
+/**
+ * Create new media data source. Returns NULL if memory allocation
+ * for the new data source object fails.
+ *
+ * Set the |uri| from which the data source will read,
+ * plus additional http headers when initiating the request.
+ *
+ * Headers will contain corresponding items from |key_values|
+ * in the following fashion:
+ *
+ * key_values[0]:key_values[1]
+ * key_values[2]:key_values[3]
+ * ...
+ * key_values[(numheaders - 1) * 2]:key_values[(numheaders - 1) * 2 + 1]
+ *
+ */
+AMediaDataSource* AMediaDataSource_newUri(const char *uri,
+        int numheaders,
+        const char * const *key_values) __INTRODUCED_IN(29);
+
+#endif  /*__ANDROID_API__ >= 29 */
+
 /**
  * Delete a previously created media data source.
  */
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 1fd69a2..a805e87 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -141,6 +141,7 @@
     AMediaDataSource_setGetSize;  # introduced=28
     AMediaDataSource_setReadAt;   # introduced=28
     AMediaDataSource_setUserdata; # introduced=28
+    AMediaDataSource_newUri;      # introduced=29
     AMediaDrm_closeSession;
     AMediaDrm_createByUUID;
     AMediaDrm_decrypt;
diff --git a/packages/MediaComponents/Android.mk b/packages/MediaComponents/Android.mk
index 55a5424..fff3a62 100644
--- a/packages/MediaComponents/Android.mk
+++ b/packages/MediaComponents/Android.mk
@@ -14,59 +14,57 @@
 # limitations under the License.
 #
 
-# This package is excluded from build for now since APIs using this apk became hidden.
-#
-#LOCAL_PATH := $(call my-dir)
-#ifneq ($(TARGET_BUILD_PDK),true) # Build MediaComponents only if this is not a PDK build.  MediaComponents won't
-## build in PDK builds because frameworks/base/core/java is not available but
-## IMediaSession2.aidl and IMediaController2.aidl are using classes from
-## frameworks/base/core/java.
-#
-#include $(CLEAR_VARS)
-#
-#LOCAL_PACKAGE_NAME := MediaComponents
-#LOCAL_MODULE_OWNER := google
-#
-## TODO: create a separate key for this package.
-#LOCAL_CERTIFICATE := platform
-#
-## TODO: Use System SDK once public APIs are approved
-## LOCAL_SDK_VERSION := system_current
-#LOCAL_PRIVATE_PLATFORM_APIS := true
-#
-#LOCAL_SRC_FILES := \
-#    $(call all-java-files-under, src) \
-#    $(call all-Iaidl-files-under, src)
-#
-#LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
-#
-#LOCAL_MULTILIB := first
-#
-#LOCAL_JAVA_LIBRARIES += androidx.annotation_annotation
-#
-## To embed native libraries in package, uncomment the lines below.
-##LOCAL_MODULE_TAGS := samples
-##LOCAL_JNI_SHARED_LIBRARIES := \
-##    libaacextractor \
-##    libamrextractor \
-##    libflacextractor \
-##    libmidiextractor \
-##    libmkvextractor \
-##    libmp3extractor \
-##    libmp4extractor \
-##    libmpeg2extractor \
-##    liboggextractor \
-##    libwavextractor \
-#
-## TODO: Remove dependency with other support libraries.
-#LOCAL_STATIC_ANDROID_LIBRARIES += \
-#    androidx.legacy_legacy-support-v4 \
-#    androidx.appcompat_appcompat \
-#    androidx.palette_palette
-#LOCAL_USE_AAPT2 := true
-#
-#include $(BUILD_PACKAGE)
-#
-#endif  # ifneq ($(TARGET_BUILD_PDK),true)
-#
-#include $(call all-makefiles-under,$(LOCAL_PATH))
+LOCAL_PATH := $(call my-dir)
+ifneq ($(TARGET_BUILD_PDK),true) # Build MediaComponents only if this is not a PDK build.  MediaComponents won't
+# build in PDK builds because frameworks/base/core/java is not available but
+# IMediaSession2.aidl and IMediaController2.aidl are using classes from
+# frameworks/base/core/java.
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := MediaComponents
+LOCAL_MODULE_OWNER := google
+
+# TODO: create a separate key for this package.
+LOCAL_CERTIFICATE := platform
+
+# TODO: Use System SDK once public APIs are approved
+# LOCAL_SDK_VERSION := system_current
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    $(call all-Iaidl-files-under, src)
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
+
+LOCAL_MULTILIB := first
+
+LOCAL_JAVA_LIBRARIES += androidx.annotation_annotation
+
+# To embed native libraries in package, uncomment the lines below.
+#LOCAL_MODULE_TAGS := samples
+#LOCAL_JNI_SHARED_LIBRARIES := \
+#    libaacextractor \
+#    libamrextractor \
+#    libflacextractor \
+#    libmidiextractor \
+#    libmkvextractor \
+#    libmp3extractor \
+#    libmp4extractor \
+#    libmpeg2extractor \
+#    liboggextractor \
+#    libwavextractor \
+
+# TODO: Remove dependency with other support libraries.
+LOCAL_STATIC_ANDROID_LIBRARIES += \
+    androidx.legacy_legacy-support-v4 \
+    androidx.appcompat_appcompat \
+    androidx.palette_palette
+LOCAL_USE_AAPT2 := true
+
+include $(BUILD_PACKAGE)
+
+endif  # ifneq ($(TARGET_BUILD_PDK),true)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index ffb145a..54ef719 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -33,8 +33,7 @@
 import android.media.MediaMetadata2;
 import android.media.MediaMetadataRetriever;
 import android.media.MediaPlayer2;
-import android.media.MediaPlayer2.MediaPlayer2EventCallback;
-import android.media.MediaPlayer2.OnSubtitleDataListener;
+import android.media.MediaPlayer2.EventCallback;
 import android.media.MediaPlayer2Impl;
 import android.media.Metadata;
 import android.media.PlaybackParams;
@@ -733,12 +732,11 @@
                     runnable.run();
                 }
             };
-            mMediaPlayer.setMediaPlayer2EventCallback(executor, mMediaPlayer2Callback);
+            mMediaPlayer.registerEventCallback(executor, mMediaPlayer2Callback);
 
             mCurrentBufferPercentage = -1;
             mMediaPlayer.setDataSource(dsd);
             mMediaPlayer.setAudioAttributes(mAudioAttributes);
-            mMediaPlayer.setOnSubtitleDataListener(mSubtitleListener);
             // we don't set the target state here either, but preserve the
             // target state that was there before.
             mCurrentState = STATE_PREPARING;
@@ -1106,10 +1104,10 @@
         mInstance.addView(mMusicView, 0);
     }
 
-    OnSubtitleDataListener mSubtitleListener =
-            new OnSubtitleDataListener() {
+    EventCallback mMediaPlayer2Callback =
+            new EventCallback() {
                 @Override
-                public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+                public void onSubtitleData(MediaPlayer2 mp, DataSourceDesc dsd, SubtitleData data) {
                     if (DEBUG) {
                         Log.d(TAG, "onSubtitleData(): getTrackIndex: " + data.getTrackIndex()
                                 + ", getCurrentPosition: " + mp.getCurrentPosition()
@@ -1133,10 +1131,7 @@
                         }
                     }
                 }
-            };
 
-    MediaPlayer2EventCallback mMediaPlayer2Callback =
-            new MediaPlayer2EventCallback() {
                 @Override
                 public void onVideoSizeChanged(
                         MediaPlayer2 mp, DataSourceDesc dsd, int width, int height) {
@@ -1169,7 +1164,7 @@
                         extractTracks();
                     } else if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
                         this.onPrepared(mp, dsd);
-                    } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+                    } else if (what == MediaPlayer2.MEDIA_INFO_DATA_SOURCE_END) {
                         this.onCompletion(mp, dsd);
                     } else if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) {
                         this.onBufferingUpdate(mp, dsd, extra);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 06975ac..62fd5f7 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2500,7 +2500,9 @@
         if (recordThread != 0) {
             ALOGV("closeInput() %d", input);
 
+#if 0
             dumpToThreadLog_l(recordThread);
+#endif
 
             // If we still have effect chains, it means that a client still holds a handle
             // on at least one effect. We must either move the chain to an existing thread with the
@@ -2544,7 +2546,9 @@
             if (mmapThread == 0) {
                 return BAD_VALUE;
             }
+#if 0
             dumpToThreadLog_l(mmapThread);
+#endif
             mMmapThreads.removeItem(input);
         }
         const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d7a4451..13ca912 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6963,7 +6963,7 @@
                                 framesIn, mSampleRate, activeTrack->mSampleRate));
 
                 if (activeTrack->isDirect()) {
-                    // No RecordBufferConverter used for compressed formats. Pass
+                    // No RecordBufferConverter used for direct streams. Pass
                     // straight from RecordThread buffer to RecordTrack buffer.
                     AudioBufferProvider::Buffer buffer;
                     buffer.frameCount = framesOut;
@@ -6973,7 +6973,7 @@
                                 "%s() read less than expected (%zu vs %zu)",
                                 __func__, buffer.frameCount, framesOut);
                         framesOut = buffer.frameCount;
-                        memcpy(activeTrack->mSink.raw, buffer.raw, buffer.frameCount);
+                        memcpy(activeTrack->mSink.raw, buffer.raw, buffer.frameCount * mFrameSize);
                         activeTrack->mResamplerBufferProvider->releaseBuffer(&buffer);
                     } else {
                         framesOut = 0;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 600f968..380f0fb 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2697,7 +2697,7 @@
     mAudioSources.dump(fd);
 
     if (!mSurroundFormats.empty()) {
-        result = String8("\nManually Enabled Surround Formats:\n");
+        result = String8("\nEnabled Surround Formats:\n");
         size_t i = 0;
         for (const auto& fmt : mSurroundFormats) {
             result.append(i++ == 0 ? "  " : ", ");
@@ -3554,50 +3554,6 @@
     return computeVolume(stream, index, device);
 }
 
-status_t AudioPolicyManager::getSupportedFormats(audio_io_handle_t ioHandle,
-                                                 FormatVector& formats) {
-    if (ioHandle == AUDIO_IO_HANDLE_NONE) {
-        return BAD_VALUE;
-    }
-    String8 reply;
-    reply = mpClientInterface->getParameters(
-            ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
-    ALOGV("%s: supported formats %s", __FUNCTION__, reply.string());
-    AudioParameter repliedParameters(reply);
-    if (repliedParameters.get(
-            String8(AudioParameter::keyStreamSupportedFormats), reply) != NO_ERROR) {
-        ALOGE("%s: failed to retrieve format, bailing out", __FUNCTION__);
-        return BAD_VALUE;
-    }
-    for (auto format : formatsFromString(reply.string())) {
-        // Only AUDIO_FORMAT_AAC_LC will be used in Settings UI for all AAC formats.
-        for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
-            if (format == AAC_FORMATS[i]) {
-                format = AUDIO_FORMAT_AAC_LC;
-                break;
-            }
-        }
-        bool exist = false;
-        for (size_t i = 0; i < formats.size(); i++) {
-            if (format == formats[i]) {
-                exist = true;
-                break;
-            }
-        }
-        bool isSurroundFormat = false;
-        for (size_t i = 0; i < ARRAY_SIZE(SURROUND_FORMATS); i++) {
-            if (SURROUND_FORMATS[i] == format) {
-                isSurroundFormat = true;
-                break;
-            }
-        }
-        if (!exist && isSurroundFormat) {
-            formats.add(format);
-        }
-    }
-    return NO_ERROR;
-}
-
 status_t AudioPolicyManager::getSurroundFormats(unsigned int *numSurroundFormats,
                                                 audio_format_t *surroundFormats,
                                                 bool *surroundFormatsEnabled,
@@ -3618,89 +3574,45 @@
     size_t formatsWritten = 0;
     size_t formatsMax = *numSurroundFormats;
     *numSurroundFormats = 0;
-    FormatVector formats;
+    std::unordered_set<audio_format_t> formats;
     if (reported) {
-        // Only get surround formats which are reported by device.
-        // First list already open outputs that can be routed to this device
-        audio_devices_t device = AUDIO_DEVICE_OUT_HDMI;
-        SortedVector<audio_io_handle_t> outputs;
-        bool reportedFormatFound = false;
-        status_t status;
-        sp<SwAudioOutputDescriptor> desc;
-        for (size_t i = 0; i < mOutputs.size(); i++) {
-            desc = mOutputs.valueAt(i);
-            if (!desc->isDuplicated() && (desc->supportedDevices() & device)) {
-                outputs.add(mOutputs.keyAt(i));
-            }
-        }
-        // Open an output to query dynamic parameters.
-        DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(
-                AUDIO_DEVICE_OUT_HDMI);
-        for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
-            String8 address = hdmiOutputDevices[i]->mAddress;
-            for (const auto& hwModule : mHwModules) {
-                for (size_t i = 0; i < hwModule->getOutputProfiles().size(); i++) {
-                    sp<IOProfile> profile = hwModule->getOutputProfiles()[i];
-                    if (profile->supportDevice(AUDIO_DEVICE_OUT_HDMI) &&
-                            profile->supportDeviceAddress(address)) {
-                        size_t j;
-                        for (j = 0; j < outputs.size(); j++) {
-                            desc = mOutputs.valueFor(outputs.itemAt(j));
-                            if (!desc->isDuplicated() && desc->mProfile == profile) {
-                                break;
-                            }
-                        }
-                        if (j != outputs.size()) {
-                            status = getSupportedFormats(outputs.itemAt(j), formats);
-                            reportedFormatFound |= (status == NO_ERROR);
-                            continue;
-                        }
-
-                        if (!profile->canOpenNewIo()) {
-                            ALOGW("Max Output number %u already opened for this profile %s",
-                                  profile->maxOpenCount, profile->getTagName().c_str());
-                            continue;
-                        }
-
-                        ALOGV("opening output for device %08x with params %s profile %p name %s",
-                              device, address.string(), profile.get(), profile->getName().string());
-                        desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
-                        audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-                        status_t status = desc->open(nullptr, device, address,
-                                                     AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE,
-                                                     &output);
-
-                        if (status == NO_ERROR) {
-                            status = getSupportedFormats(output, formats);
-                            reportedFormatFound |= (status == NO_ERROR);
-                            desc->close();
-                            output = AUDIO_IO_HANDLE_NONE;
-                        }
-                    }
-                }
-            }
-        }
-
-        if (!reportedFormatFound) {
-            return UNKNOWN_ERROR;
+        // Return formats from HDMI profiles, that have already been resolved by
+        // checkOutputsForDevice().
+        DeviceVector hdmiOutputDevs = mAvailableOutputDevices.getDevicesFromTypeMask(
+              AUDIO_DEVICE_OUT_HDMI);
+        for (size_t i = 0; i < hdmiOutputDevs.size(); i++) {
+             FormatVector supportedFormats =
+                 hdmiOutputDevs[i]->getAudioPort()->getAudioProfiles().getSupportedFormats();
+             for (size_t j = 0; j < supportedFormats.size(); j++) {
+                 if (std::find(std::begin(SURROUND_FORMATS),
+                                 std::end(SURROUND_FORMATS),
+                                 supportedFormats[j]) != std::end(SURROUND_FORMATS)) {
+                     formats.insert(supportedFormats[j]);
+                 } else if (std::find(std::begin(AAC_FORMATS),
+                                 std::end(AAC_FORMATS),
+                                 supportedFormats[j]) != std::end(AAC_FORMATS)) {
+                     // if any format in AAC_FORMATS is reported, insert AUDIO_FORMAT_AAC_LC as this
+                     // is the only AAC format used in the TvSettings UI for all AAC formats.
+                     formats.insert(AUDIO_FORMAT_AAC_LC);
+                 }
+             }
         }
     } else {
         for (size_t i = 0; i < ARRAY_SIZE(SURROUND_FORMATS); i++) {
-            formats.add(SURROUND_FORMATS[i]);
+            formats.insert(SURROUND_FORMATS[i]);
         }
     }
-    for (size_t i = 0; i < formats.size(); i++) {
+    for (const auto& format: formats) {
         if (formatsWritten < formatsMax) {
-            surroundFormats[formatsWritten] = formats[i];
+            surroundFormats[formatsWritten] = format;
             bool formatEnabled = false;
-            if (formats[i] == AUDIO_FORMAT_AAC_LC) {
-                for (size_t j = 0; j < ARRAY_SIZE(AAC_FORMATS); j++) {
+            if (format == AUDIO_FORMAT_AAC_LC) {
+                for (size_t j = 0; j < ARRAY_SIZE(AAC_FORMATS) && !formatEnabled; j++) {
                     formatEnabled =
-                            mSurroundFormats.find(AAC_FORMATS[i]) != mSurroundFormats.end();
-                    break;
+                            mSurroundFormats.find(AAC_FORMATS[j]) != mSurroundFormats.end();
                 }
             } else {
-                formatEnabled = mSurroundFormats.find(formats[i]) != mSurroundFormats.end();
+                formatEnabled = mSurroundFormats.find(format) != mSurroundFormats.end();
             }
             surroundFormatsEnabled[formatsWritten++] = formatEnabled;
         }
@@ -3744,6 +3656,7 @@
         return INVALID_OPERATION;
     }
 
+    std::unordered_set<audio_format_t> surroundFormatsBackup(mSurroundFormats);
     if (enabled) {
         if (audioFormat == AUDIO_FORMAT_AAC_LC) {
             for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
@@ -3806,23 +3719,7 @@
     // Undo the surround formats change due to no audio profiles updated.
     if (!profileUpdated) {
         ALOGW("%s() no audio profiles updated, undoing surround formats change", __func__);
-        if (enabled) {
-            if (audioFormat == AUDIO_FORMAT_AAC_LC) {
-                for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
-                    mSurroundFormats.erase(AAC_FORMATS[i]);
-                }
-            } else {
-                mSurroundFormats.erase(audioFormat);
-            }
-        } else {
-            if (audioFormat == AUDIO_FORMAT_AAC_LC) {
-                for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
-                    mSurroundFormats.insert(AAC_FORMATS[i]);
-                }
-            } else {
-                mSurroundFormats.insert(audioFormat);
-            }
-        }
+        mSurroundFormats = std::move(surroundFormatsBackup);
     }
 
     return profileUpdated ? NO_ERROR : INVALID_OPERATION;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 6f4cce1..fcb9d25 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -613,8 +613,6 @@
         void filterSurroundFormats(FormatVector *formatsPtr);
         void filterSurroundChannelMasks(ChannelsVector *channelMasksPtr);
 
-        status_t getSupportedFormats(audio_io_handle_t ioHandle, FormatVector& formats);
-
         // Support for Multi-Stream Decoder (MSD) module
         sp<DeviceDescriptor> getMsdAudioInDevice() const;
         audio_devices_t getMsdAudioOutDeviceTypes() const;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 1bc5d33..48e38bb 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -281,7 +281,6 @@
 status_t Camera3Device::disconnectImpl() {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
-    Mutex::Autolock stLock(mTrackerLock);
 
     ALOGI("%s: E", __FUNCTION__);
 
@@ -346,6 +345,7 @@
     {
         Mutex::Autolock l(mLock);
         mRequestThread.clear();
+        Mutex::Autolock stLock(mTrackerLock);
         mStatusTracker.clear();
         interface = mInterface.get();
     }
@@ -2014,6 +2014,13 @@
 
     {
         Mutex::Autolock l(mLock);
+
+        // b/116514106 "disconnect()" can get called twice for the same device. The
+        // camera device will not be initialized during the second run.
+        if (mStatus == STATUS_UNINITIALIZED) {
+            return OK;
+        }
+
         mRequestThread->clear(/*out*/frameNumber);
     }
 
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index 45da56a..ae832ba 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -26,6 +26,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <dirent.h>
+#include <pthread.h>
 #include <unistd.h>
 
 #include <string.h>
@@ -80,11 +81,18 @@
     using namespace android::content::pm;
 
 // individual records kept in memory: age or count
-// age: <= 36 hours (1.5 days)
+// age: <= 28 hours (1 1/6 days)
 // count: hard limit of # records
 // (0 for either of these disables that threshold)
-static const nsecs_t kMaxRecordAgeNs =  36 * 3600 * (1000*1000*1000ll);
-static const int kMaxRecords    = 0;
+//
+static constexpr nsecs_t kMaxRecordAgeNs =  28 * 3600 * (1000*1000*1000ll);
+static constexpr int kMaxRecords    = 0;
+
+// max we expire in a single call, to constrain how long we hold the
+// mutex, which also constrains how long a client might wait.
+static constexpr int kMaxExpiredAtOnce = 50;
+
+// TODO: need to look at tuning kMaxRecords and friends for low-memory devices
 
 static const char *kServiceName = "media.metrics";
 
@@ -96,6 +104,7 @@
 MediaAnalyticsService::MediaAnalyticsService()
         : mMaxRecords(kMaxRecords),
           mMaxRecordAgeNs(kMaxRecordAgeNs),
+          mMaxRecordsExpiredAtOnce(kMaxExpiredAtOnce),
           mDumpProto(MediaAnalyticsItem::PROTO_V1),
           mDumpProtoDefault(MediaAnalyticsItem::PROTO_V1) {
 
@@ -432,23 +441,29 @@
 //
 // Our Cheap in-core, non-persistent records management.
 
-// insert appropriately into queue
-void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item)
+
+// we hold mLock when we get here
+// if item != NULL, it's the item we just inserted
+// true == more items eligible to be recovered
+bool MediaAnalyticsService::expirations_l(MediaAnalyticsItem *item)
 {
-
-    Mutex::Autolock _l(mLock);
-    // mutex between insertion and dumping the contents
-
-    // we want to dump 'in FIFO order', so insert at the end
-    mItems.push_back(item);
+    bool more = false;
+    int handled = 0;
 
     // keep removing old records the front until we're in-bounds (count)
+    // since we invoke this with each insertion, it should be 0/1 iterations.
     if (mMaxRecords > 0) {
         while (mItems.size() > (size_t) mMaxRecords) {
             MediaAnalyticsItem * oitem = *(mItems.begin());
             if (oitem == item) {
                 break;
             }
+            if (handled >= mMaxRecordsExpiredAtOnce) {
+                // unlikely in this loop
+                more = true;
+                break;
+            }
+            handled++;
             mItems.erase(mItems.begin());
             delete oitem;
             mItemsDiscarded++;
@@ -456,8 +471,8 @@
         }
     }
 
-    // keep removing old records the front until we're in-bounds (count)
-    // NB: expired entries aren't removed until the next insertion, which could be a while
+    // keep removing old records the front until we're in-bounds (age)
+    // limited to mMaxRecordsExpiredAtOnce items per invocation.
     if (mMaxRecordAgeNs > 0) {
         nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
         while (mItems.size() > 0) {
@@ -471,12 +486,65 @@
                 // this (and the rest) are recent enough to keep
                 break;
             }
+            if (handled >= mMaxRecordsExpiredAtOnce) {
+                // this represents "one too many"; tell caller there are
+                // more to be reclaimed.
+                more = true;
+                break;
+            }
+            handled++;
             mItems.erase(mItems.begin());
             delete oitem;
             mItemsDiscarded++;
             mItemsDiscardedExpire++;
         }
     }
+
+    // we only indicate whether there's more to clean;
+    // caller chooses whether to schedule further cleanup.
+    return more;
+}
+
+// process expirations in bite sized chunks, allowing new insertions through
+// runs in a pthread specifically started for this (which then exits)
+bool MediaAnalyticsService::processExpirations()
+{
+    bool more;
+    do {
+        sleep(1);
+        {
+            Mutex::Autolock _l(mLock);
+            more = expirations_l(NULL);
+            if (!more) {
+                break;
+            }
+        }
+    } while (more);
+    return true;        // value is for std::future thread synchronization
+}
+
+// insert appropriately into queue
+void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item)
+{
+
+    Mutex::Autolock _l(mLock);
+    // mutex between insertion and dumping the contents
+
+    // we want to dump 'in FIFO order', so insert at the end
+    mItems.push_back(item);
+
+    // clean old stuff from the queue
+    bool more = expirations_l(item);
+
+    // consider scheduling some asynchronous cleaning, if not running
+    if (more) {
+        if (!mExpireFuture.valid()
+            || mExpireFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
+
+            mExpireFuture = std::async(std::launch::async, [this]()
+                                       {return this->processExpirations();});
+        }
+    }
 }
 
 static std::string allowedKeys[] =
diff --git a/services/mediaanalytics/MediaAnalyticsService.h b/services/mediaanalytics/MediaAnalyticsService.h
index b3c902a..632c692 100644
--- a/services/mediaanalytics/MediaAnalyticsService.h
+++ b/services/mediaanalytics/MediaAnalyticsService.h
@@ -26,6 +26,8 @@
 #include <utils/String8.h>
 #include <utils/List.h>
 
+#include <future>
+
 #include <media/IMediaAnalyticsService.h>
 
 namespace android {
@@ -44,6 +46,8 @@
                             MediaAnalyticsService();
     virtual                 ~MediaAnalyticsService();
 
+    bool processExpirations();
+
  private:
     MediaAnalyticsItem::SessionID_t generateUniqueSessionID();
 
@@ -65,6 +69,8 @@
     int32_t mMaxRecords;
     // by time (none older than this long agan
     nsecs_t mMaxRecordAgeNs;
+    // max to expire per expirations_l() invocation
+    int32_t mMaxRecordsExpiredAtOnce;
     //
     // # of sets of summaries
     int32_t mMaxRecordSets;
@@ -79,6 +85,9 @@
     List<MediaAnalyticsItem *> mItems;
     void saveItem(MediaAnalyticsItem *);
 
+    bool expirations_l(MediaAnalyticsItem *);
+    std::future<bool> mExpireFuture;
+
     // support for generating output
     int mDumpProto;
     int mDumpProtoDefault;