Merge "Camera: Release online and offline resources" into rvc-dev
diff --git a/apex/Android.bp b/apex/Android.bp
index 3098001..c1ef3d8 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -45,7 +45,14 @@
     // Use a custom AndroidManifest.xml used for API targeting.
     androidManifest: ":com.android.media-androidManifest",
 
-    legacy_android10_support: true,
+    // IMPORTANT: For the APEX to be installed on Android 10 (API 29),
+    // min_sdk_version should be 29. This enables the build system to make
+    // sure the package compatible to Android 10 in two ways:
+    // - build the APEX package compatible to Android 10
+    //   so that the package can be installed.
+    // - build artifacts (lib/javalib/bin) against Android 10 SDK
+    //   so that the artifacts can run.
+    min_sdk_version: "29",
 }
 
 apex {
@@ -85,7 +92,14 @@
     // Use a custom AndroidManifest.xml used for API targeting.
     androidManifest: ":com.android.media.swcodec-androidManifest",
 
-    legacy_android10_support: true,
+    // IMPORTANT: For the APEX to be installed on Android 10 (API 29),
+    // min_sdk_version should be 29. This enables the build system to make
+    // sure the package compatible to Android 10 in two ways:
+    // - build the APEX package compatible to Android 10
+    //   so that the package can be installed.
+    // - build artifacts (lib/javalib/bin) against Android 10 SDK
+    //   so that the artifacts can run.
+    min_sdk_version: "29",
 }
 
 prebuilt_etc {
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 833893e..ac7a35b 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -119,7 +119,7 @@
      * Get a list of combinations of camera ids which support concurrent streaming.
      *
      */
-    ConcurrentCameraIdCombination[] getConcurrentStreamingCameraIds();
+    ConcurrentCameraIdCombination[] getConcurrentCameraIds();
 
     /**
       * Check whether a particular set of session configurations are concurrently supported by the
@@ -129,7 +129,7 @@
       * @return true  - the set of concurrent camera id and stream combinations is supported.
       *         false - the set of concurrent camera id and stream combinations is not supported
       *                 OR the method was called with a set of camera ids not returned by
-      *                 getConcurrentMultiStreamingCameraIds().
+      *                 getConcurrentCameraIds().
       */
     boolean isConcurrentSessionConfigurationSupported(
             in CameraIdAndSessionConfiguration[] sessions);
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 1bbb9c2..2aeffa2 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -139,12 +139,20 @@
     const int STREAM_WIDTH_OFFSET = 1;
     const int STREAM_HEIGHT_OFFSET = 2;
     const int STREAM_DURATION_OFFSET = 3;
+
     camera_metadata_entry entry = mData->find(tag);
-    if (entry.count == 0 || entry.count % 4 || entry.type != TYPE_INT64) {
+
+    if (entry.count == 0) {
+        // Duration keys can be missing when corresponding capture feature is not supported
+        return;
+    }
+
+    if (entry.count % 4 || entry.type != TYPE_INT64) {
         ALOGE("%s: malformed duration key %d! count %zu, type %d",
                 __FUNCTION__, tag, entry.count, entry.type);
         return;
     }
+
     Vector<int64_t> filteredDurations;
     filteredDurations.setCapacity(entry.count * 2);
 
@@ -519,7 +527,6 @@
         case ACAMERA_LENS_OPTICAL_STABILIZATION_MODE:
         case ACAMERA_NOISE_REDUCTION_MODE:
         case ACAMERA_SCALER_CROP_REGION:
-        case ACAMERA_SCALER_ROTATE_AND_CROP:
         case ACAMERA_SENSOR_EXPOSURE_TIME:
         case ACAMERA_SENSOR_FRAME_DURATION:
         case ACAMERA_SENSOR_SENSITIVITY:
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index bd259eb..8b371db 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -3690,108 +3690,6 @@
     ACAMERA_SCALER_AVAILABLE_RECOMMENDED_INPUT_OUTPUT_FORMATS_MAP = 
                                                                 // int32
             ACAMERA_SCALER_START + 15,
-    /**
-     * <p>List of rotate-and-crop modes for ACAMERA_SCALER_ROTATE_AND_CROP that are supported by this camera device.</p>
-     *
-     * @see ACAMERA_SCALER_ROTATE_AND_CROP
-     *
-     * <p>Type: byte[n]</p>
-     *
-     * <p>This tag may appear in:
-     * <ul>
-     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
-     * </ul></p>
-     *
-     * <p>This entry lists the valid modes for ACAMERA_SCALER_ROTATE_AND_CROP for this camera device.</p>
-     * <p>Starting with API level 30, all devices will list at least <code>ROTATE_AND_CROP_NONE</code>.
-     * Devices with support for rotate-and-crop will additionally list at least
-     * <code>ROTATE_AND_CROP_AUTO</code> and <code>ROTATE_AND_CROP_90</code>.</p>
-     *
-     * @see ACAMERA_SCALER_ROTATE_AND_CROP
-     */
-    ACAMERA_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES =            // byte[n]
-            ACAMERA_SCALER_START + 16,
-    /**
-     * <p>Whether a rotation-and-crop operation is applied to processed
-     * outputs from the camera.</p>
-     *
-     * <p>Type: byte (acamera_metadata_enum_android_scaler_rotate_and_crop_t)</p>
-     *
-     * <p>This tag may appear in:
-     * <ul>
-     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
-     *   <li>ACaptureRequest</li>
-     * </ul></p>
-     *
-     * <p>This control is primarily intended to help camera applications with no support for
-     * multi-window modes to work correctly on devices where multi-window scenarios are
-     * unavoidable, such as foldables or other devices with variable display geometry or more
-     * free-form window placement (such as laptops, which often place portrait-orientation apps
-     * in landscape with pillarboxing).</p>
-     * <p>If supported, the default value is <code>ROTATE_AND_CROP_AUTO</code>, which allows the camera API
-     * to enable backwards-compatibility support for applications that do not support resizing
-     * / multi-window modes, when the device is in fact in a multi-window mode (such as inset
-     * portrait on laptops, or on a foldable device in some fold states).  In addition,
-     * <code>ROTATE_AND_CROP_NONE</code> and <code>ROTATE_AND_CROP_90</code> will always be available if this control
-     * is supported by the device.  If not supported, devices API level 30 or higher will always
-     * list only <code>ROTATE_AND_CROP_NONE</code>.</p>
-     * <p>When <code>CROP_AUTO</code> is in use, and the camera API activates backward-compatibility mode,
-     * several metadata fields will also be parsed differently to ensure that coordinates are
-     * correctly handled for features like drawing face detection boxes or passing in
-     * tap-to-focus coordinates.  The camera API will convert positions in the active array
-     * coordinate system to/from the cropped-and-rotated coordinate system to make the
-     * operation transparent for applications.  The following controls are affected:</p>
-     * <ul>
-     * <li>ACAMERA_CONTROL_AE_REGIONS</li>
-     * <li>ACAMERA_CONTROL_AF_REGIONS</li>
-     * <li>ACAMERA_CONTROL_AWB_REGIONS</li>
-     * <li>android.statistics.faces</li>
-     * </ul>
-     * <p>Capture results will contain the actual value selected by the API;
-     * <code>ROTATE_AND_CROP_AUTO</code> will never be seen in a capture result.</p>
-     * <p>Applications can also select their preferred cropping mode, either to opt out of the
-     * backwards-compatibility treatment, or to use the cropping feature themselves as needed.
-     * In this case, no coordinate translation will be done automatically, and all controls
-     * will continue to use the normal active array coordinates.</p>
-     * <p>Cropping and rotating is done after the application of digital zoom (via either
-     * ACAMERA_SCALER_CROP_REGION or ACAMERA_CONTROL_ZOOM_RATIO), but before each individual
-     * output is further cropped and scaled. It only affects processed outputs such as
-     * YUV, PRIVATE, and JPEG.  It has no effect on RAW outputs.</p>
-     * <p>When <code>CROP_90</code> or <code>CROP_270</code> are selected, there is a significant loss to the field of
-     * view. For example, with a 4:3 aspect ratio output of 1600x1200, <code>CROP_90</code> will still
-     * produce 1600x1200 output, but these buffers are cropped from a vertical 3:4 slice at the
-     * center of the 4:3 area, then rotated to be 4:3, and then upscaled to 1600x1200.  Only
-     * 56.25% of the original FOV is still visible.  In general, for an aspect ratio of <code>w:h</code>,
-     * the crop and rotate operation leaves <code>(h/w)^2</code> of the field of view visible. For 16:9,
-     * this is ~31.6%.</p>
-     * <p>As a visual example, the figure below shows the effect of <code>ROTATE_AND_CROP_90</code> on the
-     * outputs for the following parameters:</p>
-     * <ul>
-     * <li>Sensor active array: <code>2000x1500</code></li>
-     * <li>Crop region: top-left: <code>(500, 375)</code>, size: <code>(1000, 750)</code> (4:3 aspect ratio)</li>
-     * <li>Output streams: YUV <code>640x480</code> and YUV <code>1280x720</code></li>
-     * <li><code>ROTATE_AND_CROP_90</code></li>
-     * </ul>
-     * <p><img alt="Effect of ROTATE_AND_CROP_90" src="../images/camera2/metadata/android.scaler.rotateAndCrop/crop-region-rotate-90-43-ratio.png" /></p>
-     * <p>With these settings, the regions of the active array covered by the output streams are:</p>
-     * <ul>
-     * <li>640x480 stream crop: top-left: <code>(219, 375)</code>, size: <code>(562, 750)</code></li>
-     * <li>1280x720 stream crop: top-left: <code>(289, 375)</code>, size: <code>(422, 750)</code></li>
-     * </ul>
-     * <p>Since the buffers are rotated, the buffers as seen by the application are:</p>
-     * <ul>
-     * <li>640x480 stream: top-left: <code>(781, 375)</code> on active array, size: <code>(640, 480)</code>, downscaled 1.17x from sensor pixels</li>
-     * <li>1280x720 stream: top-left: <code>(711, 375)</code> on active array, size: <code>(1280, 720)</code>, upscaled 1.71x from sensor pixels</li>
-     * </ul>
-     *
-     * @see ACAMERA_CONTROL_AE_REGIONS
-     * @see ACAMERA_CONTROL_AF_REGIONS
-     * @see ACAMERA_CONTROL_AWB_REGIONS
-     * @see ACAMERA_CONTROL_ZOOM_RATIO
-     * @see ACAMERA_SCALER_CROP_REGION
-     */
-    ACAMERA_SCALER_ROTATE_AND_CROP =                            // byte (acamera_metadata_enum_android_scaler_rotate_and_crop_t)
-            ACAMERA_SCALER_START + 17,
     ACAMERA_SCALER_END,
 
     /**
@@ -8314,51 +8212,6 @@
 
 } acamera_metadata_enum_android_scaler_available_recommended_stream_configurations_t;
 
-// ACAMERA_SCALER_ROTATE_AND_CROP
-typedef enum acamera_metadata_enum_acamera_scaler_rotate_and_crop {
-    /**
-     * <p>No rotate and crop is applied. Processed outputs are in the sensor orientation.</p>
-     */
-    ACAMERA_SCALER_ROTATE_AND_CROP_NONE                              = 0,
-
-    /**
-     * <p>Processed images are rotated by 90 degrees clockwise, and then cropped
-     * to the original aspect ratio.</p>
-     */
-    ACAMERA_SCALER_ROTATE_AND_CROP_90                                = 1,
-
-    /**
-     * <p>Processed images are rotated by 180 degrees.  Since the aspect ratio does not
-     * change, no cropping is performed.</p>
-     */
-    ACAMERA_SCALER_ROTATE_AND_CROP_180                               = 2,
-
-    /**
-     * <p>Processed images are rotated by 270 degrees clockwise, and then cropped
-     * to the original aspect ratio.</p>
-     */
-    ACAMERA_SCALER_ROTATE_AND_CROP_270                               = 3,
-
-    /**
-     * <p>The camera API automatically selects the best concrete value for
-     * rotate-and-crop based on the application's support for resizability and the current
-     * multi-window mode.</p>
-     * <p>If the application does not support resizing but the display mode for its main
-     * Activity is not in a typical orientation, the camera API will set <code>ROTATE_AND_CROP_90</code>
-     * or some other supported rotation value, depending on device configuration,
-     * to ensure preview and captured images are correctly shown to the user. Otherwise,
-     * <code>ROTATE_AND_CROP_NONE</code> will be selected.</p>
-     * <p>When a value other than NONE is selected, several metadata fields will also be parsed
-     * differently to ensure that coordinates are correctly handled for features like drawing
-     * face detection boxes or passing in tap-to-focus coordinates.  The camera API will
-     * convert positions in the active array coordinate system to/from the cropped-and-rotated
-     * coordinate system to make the operation transparent for applications.</p>
-     * <p>No coordinate mapping will be done when the application selects a non-AUTO mode.</p>
-     */
-    ACAMERA_SCALER_ROTATE_AND_CROP_AUTO                              = 4,
-
-} acamera_metadata_enum_android_scaler_rotate_and_crop_t;
-
 
 // ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
 typedef enum acamera_metadata_enum_acamera_sensor_reference_illuminant1 {
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index a95fe2a..e2097b5 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -735,9 +735,8 @@
 
     if (!serviceRet.isOk() || status != Status::NO_ERROR) {
         ALOGE("%s: connect camera device failed", __FUNCTION__);
-        // TODO: Convert serviceRet to camera_status_t
         delete device;
-        return ACAMERA_ERROR_UNKNOWN;
+        return utils::convertFromHidl(status);
     }
     if (deviceRemote == nullptr) {
         ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 7a4e1ae..5292705 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -89,7 +89,7 @@
 }
 
 sp<DrmSessionManager> DrmSessionManager::Instance() {
-    auto drmSessionManager = new DrmSessionManager();
+    static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
     drmSessionManager->init();
     return drmSessionManager;
 }
@@ -163,7 +163,8 @@
     }
 
     auto info = it->second;
-    mService->removeResource(info.pid, info.clientId, toResourceVec(sessionId, INT64_MAX));
+    // removeClient instead of removeSession because each client has only one session
+    mService->removeClient(info.pid, info.clientId);
     mSessionMap.erase(it);
 }
 
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 74fdc8b..9fc0e17 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -59,7 +59,6 @@
     enum drc_compression_mode_t : int32_t;  ///< DRC compression mode
     enum drc_effect_type_t : int32_t;       ///< DRC effect type
     enum drc_album_mode_t : int32_t;        ///< DRC album mode
-    enum drc_output_loudness : int32_t;     ///< DRC output loudness
     enum intra_refresh_mode_t : uint32_t;   ///< intra refresh modes
     enum level_t : uint32_t;                ///< coding level
     enum ordinal_key_t : uint32_t;          ///< work ordering keys
@@ -248,7 +247,7 @@
 
     kParamIndexSurfaceAllocator, // u32
 
-    // low latency mode for decoders
+    // low latency mode
     kParamIndexLowLatencyMode, // bool
 };
 
@@ -812,9 +811,10 @@
 constexpr char C2_PARAMKEY_PIPELINE_DELAY[] = "algo.delay";
 
 /**
- * Enable/disable low latency decoding mode.
- * If true, low latency decoding mode is enabled, and the decoder doesn't hold input and output
- * data more than required by the codec standards.
+ * Enable/disable low latency mode.
+ * If true, low latency is preferred over low power. Disable power optimizations that
+ * may result in increased latency. For decoders, this means that the decoder does not
+ * hold input and output data more than required by the codec standards.
  */
 typedef C2GlobalParam<C2Tuning, C2EasyBoolValue, kParamIndexLowLatencyMode>
         C2GlobalLowLatencyModeTuning;
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 49b49a4..0acab49 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -678,8 +678,13 @@
                    << ") -- transaction failed.";
         return C2_TRANSACTION_FAILED;
     } else if (status != C2_OK) {
-        LOG(ERROR) << "createComponent(" << name.c_str()
-                   << ") -- call failed: " << status << ".";
+        if (status == C2_NOT_FOUND) {
+            LOG(VERBOSE) << "createComponent(" << name.c_str()
+                         << ") -- component not found.";
+        } else {
+            LOG(ERROR) << "createComponent(" << name.c_str()
+                       << ") -- call failed: " << status << ".";
+        }
         return status;
     } else if (!*component) {
         LOG(ERROR) << "createComponent(" << name.c_str()
@@ -718,8 +723,13 @@
                    << ") -- transaction failed.";
         return C2_TRANSACTION_FAILED;
     } else if (status != C2_OK) {
-        LOG(ERROR) << "createComponent(" << name.c_str()
-                   << ") -- call failed: " << status << ".";
+        if (status == C2_NOT_FOUND) {
+            LOG(VERBOSE) << "createInterface(" << name.c_str()
+                         << ") -- component not found.";
+        } else {
+            LOG(ERROR) << "createInterface(" << name.c_str()
+                       << ") -- call failed: " << status << ".";
+        }
         return status;
     }
 
@@ -946,11 +956,11 @@
 
 std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
     std::string const& name = GetServiceNames()[index];
-    LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
+    LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
     sp<Base> baseStore = Base::getService(name);
     CHECK(baseStore) << "Codec2 service \"" << name << "\""
                         " inaccessible for unknown reasons.";
-    LOG(INFO) << "Client to Codec2 service \"" << name << "\" created";
+    LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
     return std::make_shared<Codec2Client>(baseStore, index);
 }
 
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index e85e73a..6b389d5 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -604,7 +604,12 @@
 
     ssize_t result = -1;
     ssize_t codecDataOffset = 0;
-    if (mCrypto != nullptr) {
+    if (numSubSamples == 1
+            && subSamples[0].mNumBytesOfClearData == 0
+            && subSamples[0].mNumBytesOfEncryptedData == 0) {
+        // We don't need to go through crypto or descrambler if the input is empty.
+        result = 0;
+    } else if (mCrypto != nullptr) {
         hardware::drm::V1_0::DestinationBuffer destination;
         if (secure) {
             destination.type = DrmBufferType::NATIVE_HANDLE;
@@ -620,6 +625,7 @@
                 key, iv, mode, pattern, source, buffer->offset(),
                 subSamples, numSubSamples, destination, errorDetailMsg);
         if (result < 0) {
+            ALOGI("[%s] decrypt failed: result=%zd", mName, result);
             return result;
         }
         if (destination.type == DrmBufferType::SHARED_MEMORY) {
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index 5990116..b112249 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -319,10 +319,11 @@
     // Obtain Codec2Client
     std::vector<Traits> traits = Codec2Client::ListComponents();
 
-    // parse APEX XML first, followed by vendor XML
+    // parse APEX XML first, followed by vendor XML.
+    // Note: APEX XML names do not depend on ro.media.xml_variant.* properties.
     MediaCodecsXmlParser parser;
     parser.parseXmlFilesInSearchDirs(
-            parser.getDefaultXmlNames(),
+            { "media_codecs.xml", "media_codecs_performance.xml" },
             { "/apex/com.android.media.swcodec/etc" });
 
     // TODO: remove these c2-specific files once product moved to default file names
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 51d6ffa..f3e37e0 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -95,6 +95,10 @@
     name: "libcodec2-internal-defaults",
     defaults: ["libcodec2-impl-defaults"],
 
+    header_libs: [
+        "libcodec2_internal",
+    ],
+
     shared_libs: [
         "libcutils", // for properties
     ],
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index ca721df..bdb724b 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -13,6 +13,9 @@
         "libsonivox",
         "libstagefright_foundation",
         "libwatchdog",
+    ],
+
+    shared_libs: [
         "libbase",
-    ]
+    ],
 }
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index d7c4b5c..bc8632c 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -10,6 +10,7 @@
     ],
 
     shared_libs: [
+        "libbase",
         "libcgrouprc#29",
         "libvndksupport#29",
     ],
@@ -28,7 +29,6 @@
         "android.hidl.memory@1.0",
         "android.hidl.token@1.0",
         "android.hidl.token@1.0-utils",
-        "libbase",
         "libcutils",
         "libhidlbase",
         "libhidlmemory",
diff --git a/media/libaaudio/src/utility/FixedBlockAdapter.cpp b/media/libaaudio/src/utility/FixedBlockAdapter.cpp
index 63495f0..b55f827 100644
--- a/media/libaaudio/src/utility/FixedBlockAdapter.cpp
+++ b/media/libaaudio/src/utility/FixedBlockAdapter.cpp
@@ -18,22 +18,17 @@
 
 #include "FixedBlockAdapter.h"
 
-FixedBlockAdapter::~FixedBlockAdapter() {
-    close();
-}
-
 int32_t FixedBlockAdapter::open(int32_t bytesPerFixedBlock)
 {
     mSize = bytesPerFixedBlock;
-    mStorage = new uint8_t[bytesPerFixedBlock];
+    mStorage = std::make_unique<uint8_t[]>(bytesPerFixedBlock);
     mPosition = 0;
     return 0;
 }
 
 int32_t FixedBlockAdapter::close()
 {
-    delete[] mStorage;
-    mStorage = nullptr;
+    mStorage.reset();
     mSize = 0;
     mPosition = 0;
     return 0;
diff --git a/media/libaaudio/src/utility/FixedBlockAdapter.h b/media/libaaudio/src/utility/FixedBlockAdapter.h
index 7008b25..4dc7e68 100644
--- a/media/libaaudio/src/utility/FixedBlockAdapter.h
+++ b/media/libaaudio/src/utility/FixedBlockAdapter.h
@@ -17,6 +17,7 @@
 #ifndef AAUDIO_FIXED_BLOCK_ADAPTER_H
 #define AAUDIO_FIXED_BLOCK_ADAPTER_H
 
+#include <memory>
 #include <stdio.h>
 
 /**
@@ -37,7 +38,7 @@
     FixedBlockAdapter(FixedBlockProcessor &fixedBlockProcessor)
     : mFixedBlockProcessor(fixedBlockProcessor) {}
 
-    virtual ~FixedBlockAdapter();
+    virtual ~FixedBlockAdapter() = default;
 
     /**
      * Allocate internal resources needed for buffering data.
@@ -63,7 +64,7 @@
 
 protected:
     FixedBlockProcessor  &mFixedBlockProcessor;
-    uint8_t              *mStorage = nullptr;    // Store data here while assembling buffers.
+    std::unique_ptr<uint8_t[]> mStorage;         // Store data here while assembling buffers.
     int32_t               mSize = 0;             // Size in bytes of the fixed size buffer.
     int32_t               mPosition = 0;         // Offset of the last byte read or written.
 };
diff --git a/media/libaaudio/src/utility/FixedBlockReader.cpp b/media/libaaudio/src/utility/FixedBlockReader.cpp
index 21ea70e..7931fa0 100644
--- a/media/libaaudio/src/utility/FixedBlockReader.cpp
+++ b/media/libaaudio/src/utility/FixedBlockReader.cpp
@@ -39,7 +39,7 @@
     if (bytesToRead > dataAvailable) {
         bytesToRead = dataAvailable;
     }
-    memcpy(buffer, mStorage + mPosition, bytesToRead);
+    memcpy(buffer, &mStorage[mPosition], bytesToRead);
     mPosition += bytesToRead;
     return bytesToRead;
 }
@@ -60,7 +60,7 @@
             bytesLeft -= mSize;
         } else {
             // Just need a partial block so we have to use storage.
-            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage, mSize);
+            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage.get(), mSize);
             mPosition = 0;
         }
     }
diff --git a/media/libaaudio/src/utility/FixedBlockWriter.cpp b/media/libaaudio/src/utility/FixedBlockWriter.cpp
index 2ce8046..afb83c1 100644
--- a/media/libaaudio/src/utility/FixedBlockWriter.cpp
+++ b/media/libaaudio/src/utility/FixedBlockWriter.cpp
@@ -30,7 +30,7 @@
     if (bytesToStore > roomAvailable) {
         bytesToStore = roomAvailable;
     }
-    memcpy(mStorage + mPosition, buffer, bytesToStore);
+    memcpy(&mStorage[mPosition], buffer, bytesToStore);
     mPosition += bytesToStore;
     return bytesToStore;
 }
@@ -46,7 +46,7 @@
         bytesLeft -= bytesWritten;
         // If storage full then flush it out
         if (mPosition == mSize) {
-            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage, mSize);
+            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage.get(), mSize);
             mPosition = 0;
         }
     }
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index a1b141b..c183ab0 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -36,7 +36,7 @@
 // ---------------------------------------------------------------------------
 
 AudioEffect::AudioEffect(const String16& opPackageName)
-    : mStatus(NO_INIT), mOpPackageName(opPackageName)
+    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
 {
 }
 
@@ -49,12 +49,13 @@
                 void* user,
                 audio_session_t sessionId,
                 audio_io_handle_t io,
-                const AudioDeviceTypeAddr& device
+                const AudioDeviceTypeAddr& device,
+                bool probe
                 )
-    : mStatus(NO_INIT), mOpPackageName(opPackageName)
+    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
 {
     AutoMutex lock(mConstructLock);
-    mStatus = set(type, uuid, priority, cbf, user, sessionId, io, device);
+    mStatus = set(type, uuid, priority, cbf, user, sessionId, io, device, probe);
 }
 
 AudioEffect::AudioEffect(const char *typeStr,
@@ -65,9 +66,10 @@
                 void* user,
                 audio_session_t sessionId,
                 audio_io_handle_t io,
-                const AudioDeviceTypeAddr& device
+                const AudioDeviceTypeAddr& device,
+                bool probe
                 )
-    : mStatus(NO_INIT), mOpPackageName(opPackageName)
+    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
 {
     effect_uuid_t type;
     effect_uuid_t *pType = NULL;
@@ -89,7 +91,7 @@
     }
 
     AutoMutex lock(mConstructLock);
-    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io, device);
+    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io, device, probe);
 }
 
 status_t AudioEffect::set(const effect_uuid_t *type,
@@ -99,7 +101,8 @@
                 void* user,
                 audio_session_t sessionId,
                 audio_io_handle_t io,
-                const AudioDeviceTypeAddr& device)
+                const AudioDeviceTypeAddr& device,
+                bool probe)
 {
     sp<IEffect> iEffect;
     sp<IMemory> cblk;
@@ -126,7 +129,7 @@
         ALOGW("Must specify at least type or uuid");
         return BAD_VALUE;
     }
-
+    mProbe = probe;
     mPriority = priority;
     mCbf = cbf;
     mUserData = user;
@@ -142,15 +145,18 @@
 
     iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
             mIEffectClient, priority, io, mSessionId, device, mOpPackageName, mClientPid,
-            &mStatus, &mId, &enabled);
+            probe, &mStatus, &mId, &enabled);
 
-    if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
+    // In probe mode, we stop here and return the status: the IEffect interface to
+    // audio flinger will not be retained. initCheck() will return the creation status
+    // but all other APIs will return invalid operation.
+    if (probe || iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
         char typeBuffer[64], uuidBuffer[64];
         guidToString(type, typeBuffer, sizeof(typeBuffer));
         guidToString(uuid, uuidBuffer, sizeof(uuidBuffer));
-        ALOGE("set(): AudioFlinger could not create effect %s / %s, status: %d",
+        ALOGE_IF(!probe, "set(): AudioFlinger could not create effect %s / %s, status: %d",
                 typeBuffer, uuidBuffer, mStatus);
-        if (iEffect == 0) {
+        if (!probe && iEffect == 0) {
             mStatus = NO_INIT;
         }
         return mStatus;
@@ -191,7 +197,7 @@
 {
     ALOGV("Destructor %p", this);
 
-    if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
+    if (!mProbe && (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS)) {
         if (!audio_is_global_session(mSessionId)) {
             AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
         }
@@ -201,9 +207,9 @@
         }
         mIEffect.clear();
         mCblkMemory.clear();
-        mIEffectClient.clear();
-        IPCThreadState::self()->flushCommands();
     }
+    mIEffectClient.clear();
+    IPCThreadState::self()->flushCommands();
 }
 
 
@@ -226,6 +232,9 @@
 
 status_t AudioEffect::setEnabled(bool enabled)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
@@ -254,6 +263,9 @@
                               uint32_t *replySize,
                               void *replyData)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
         ALOGV("command() bad status %d", mStatus);
         return mStatus;
@@ -287,6 +299,9 @@
 
 status_t AudioEffect::setParameter(effect_param_t *param)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
@@ -307,6 +322,9 @@
 
 status_t AudioEffect::setParameterDeferred(effect_param_t *param)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
@@ -333,6 +351,9 @@
 
 status_t AudioEffect::setParameterCommit()
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
@@ -347,6 +368,9 @@
 
 status_t AudioEffect::getParameter(effect_param_t *param)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
         return mStatus;
     }
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 513da2b..16d2232 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -662,6 +662,7 @@
                                     const AudioDeviceTypeAddr& device,
                                     const String16& opPackageName,
                                     pid_t pid,
+                                    bool probe,
                                     status_t *status,
                                     int *id,
                                     int *enabled)
@@ -689,6 +690,7 @@
         }
         data.writeString16(opPackageName);
         data.writeInt32((int32_t) pid);
+        data.writeInt32(probe ? 1 : 0);
 
         status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply);
         if (lStatus != NO_ERROR) {
@@ -1395,12 +1397,13 @@
             }
             const String16 opPackageName = data.readString16();
             pid_t pid = (pid_t)data.readInt32();
+            bool probe = data.readInt32() == 1;
 
             int id = 0;
             int enabled = 0;
 
             sp<IEffect> effect = createEffect(&desc, client, priority, output, sessionId, device,
-                    opPackageName, pid, &status, &id, &enabled);
+                    opPackageName, pid, probe, &status, &id, &enabled);
             reply->writeInt32(status);
             reply->writeInt32(id);
             reply->writeInt32(enabled);
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index eec9dfc..cb76252 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -365,6 +365,10 @@
      * device: An audio device descriptor. Only used when "sessionID" is AUDIO_SESSION_DEVICE.
      *         Specifies the audio device type and address the effect must be attached to.
      *         If "sessionID" is AUDIO_SESSION_DEVICE then "io" must be AUDIO_IO_HANDLE_NONE.
+     * probe: true if created in a degraded mode to only verify if effect creation is possible.
+     *        In this mode, no IEffect interface to AudioFlinger is created and all actions
+     *        besides getters implemented in client AudioEffect object are no ops
+     *        after effect creation.
      */
 
     AudioEffect(const effect_uuid_t *type,
@@ -375,8 +379,8 @@
                 void* user = NULL,
                 audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
                 audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
-                const AudioDeviceTypeAddr& device = {}
-                );
+                const AudioDeviceTypeAddr& device = {},
+                bool probe = false);
 
     /* Constructor.
      *      Same as above but with type and uuid specified by character strings
@@ -389,8 +393,8 @@
                     void* user = NULL,
                     audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
                     audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
-                    const AudioDeviceTypeAddr& device = {}
-                    );
+                    const AudioDeviceTypeAddr& device = {},
+                    bool probe = false);
 
     /* Terminates the AudioEffect and unregisters it from AudioFlinger.
      * The effect engine is also destroyed if this AudioEffect was the last controlling
@@ -412,8 +416,8 @@
                             void* user = NULL,
                             audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
                             audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
-                            const AudioDeviceTypeAddr& device = {}
-                            );
+                            const AudioDeviceTypeAddr& device = {},
+                            bool probe = false);
 
     /* Result of constructing the AudioEffect. This must be checked
      * before using any AudioEffect API.
@@ -547,6 +551,8 @@
      audio_session_t         mSessionId;         // audio session ID
      int32_t                 mPriority;          // priority for effect control
      status_t                mStatus;            // effect status
+     bool                    mProbe;             // effect created in probe mode: all commands
+                                                 // are no ops because mIEffect is NULL
      effect_callback_t       mCbf;               // callback function for status, control and
                                                  // parameter changes notifications
      void*                   mUserData;          // client context for callback function
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index f4ce5d7..c9d9716 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -476,6 +476,7 @@
                                     const AudioDeviceTypeAddr& device,
                                     const String16& callingPackage,
                                     pid_t pid,
+                                    bool probe,
                                     status_t *status,
                                     int *id,
                                     int *enabled) = 0;
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 98c5497..637322f 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -29,9 +29,55 @@
 #include <OMX_Video.h>
 #include <sys/stat.h>
 
+#include <array>
+#include <string>
+#include <vector>
+
 namespace android {
 
-constexpr char const * const MediaProfiles::xmlFiles[];
+namespace /* unnamed */ {
+
+// Returns a list of possible paths for the media_profiles XML file.
+std::array<char const*, 5> const& getXmlPaths() {
+    static std::array<std::string const, 5> const paths =
+        []() -> decltype(paths) {
+            // Directories for XML file that will be searched (in this order).
+            constexpr std::array<char const*, 4> searchDirs = {
+                "product/etc/",
+                "odm/etc/",
+                "vendor/etc/",
+                "system/etc/",
+            };
+
+            // The file name may contain a variant if the vendor property
+            // ro.vendor.media_profiles_xml_variant is set.
+            char variant[PROPERTY_VALUE_MAX];
+            property_get("ro.media.xml_variant.profiles",
+                         variant,
+                         "_V1_0");
+
+            std::string fileName =
+                std::string("media_profiles") + variant + ".xml";
+
+            return { searchDirs[0] + fileName,
+                     searchDirs[1] + fileName,
+                     searchDirs[2] + fileName,
+                     searchDirs[3] + fileName,
+                     "system/etc/media_profiles_V1_0.xml" // System fallback
+                   };
+        }();
+    static std::array<char const*, 5> const cPaths = {
+            paths[0].data(),
+            paths[1].data(),
+            paths[2].data(),
+            paths[3].data(),
+            paths[4].data()
+        };
+    return cPaths;
+}
+
+} // unnamed namespace
+
 Mutex MediaProfiles::sLock;
 bool MediaProfiles::sIsInitialized = false;
 MediaProfiles *MediaProfiles::sInstance = NULL;
@@ -48,7 +94,7 @@
     {"amrwb",  AUDIO_ENCODER_AMR_WB},
     {"aac",    AUDIO_ENCODER_AAC},
     {"heaac",  AUDIO_ENCODER_HE_AAC},
-    {"aaceld", AUDIO_ENCODER_AAC_ELD}, 
+    {"aaceld", AUDIO_ENCODER_AAC_ELD},
     {"opus",   AUDIO_ENCODER_OPUS}
 };
 
@@ -610,7 +656,7 @@
         char value[PROPERTY_VALUE_MAX];
         if (property_get("media.settings.xml", value, NULL) <= 0) {
             const char* xmlFile = nullptr;
-            for (auto const& f : xmlFiles) {
+            for (auto const& f : getXmlPaths()) {
                 if (checkXmlFile(f)) {
                     xmlFile = f;
                     break;
diff --git a/media/libmedia/include/media/MediaProfiles.h b/media/libmedia/include/media/MediaProfiles.h
index 3e8e7c8..4cc5b95 100644
--- a/media/libmedia/include/media/MediaProfiles.h
+++ b/media/libmedia/include/media/MediaProfiles.h
@@ -1,18 +1,18 @@
 /*
- **
- ** Copyright 2010, 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.
+ *
+ * Copyright 2010, 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 ANDROID_MEDIAPROFILES_H
@@ -82,29 +82,12 @@
 {
 public:
 
-    /*
-     * If property media.settings.xml is not set:
-     *
-     * getInstance() will search through paths listed in xmlFiles.
-     * The search goes through members of xmlFiles in the order that they are
-     * defined, so files at lower indices have higher priority than those at
-     * higher indices.
-     *
-     * TODO: Add runtime validation of xml files. A search should be considered
-     * successful only when validation is successful.
-     */
-    static constexpr char const * const xmlFiles[] = {
-            "odm/etc/media_profiles_V1_0.xml",
-            "vendor/etc/media_profiles_V1_0.xml",
-            "system/etc/media_profiles.xml"
-            };
-
     /**
      * Returns the singleton instance for subsequence queries or NULL if error.
      *
      * If property media.settings.xml is set, getInstance() will attempt to read
      * from file path in media.settings.xml. Otherwise, getInstance() will
-     * search through the list xmlFiles as described above.
+     * search through the list of preset XML file paths.
      *
      * If the search is unsuccessful, the default instance will be created
      * instead.
diff --git a/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp b/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
index 7729d52..4f3951a 100644
--- a/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
+++ b/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
@@ -14,23 +14,68 @@
  * limitations under the License.
  */
 
+#include <fstream>
 #include <string>
 
 #include <android-base/file.h>
 #include <android-base/properties.h>
 #include "utility/ValidateXml.h"
 
+bool isFileReadable(std::string const& path) {
+  std::ifstream f(path);
+  return f.good();
+}
+
 TEST(CheckConfig, mediaProfilesValidation) {
     RecordProperty("description",
                    "Verify that the media profiles file "
                    "is valid according to the schema");
 
+    // Schema path.
+    constexpr char const* xsdPath = "/data/local/tmp/media_profiles.xsd";
+
+    // If "media.settings.xml" is set, it will be used as an absolute path.
     std::string mediaSettingsPath = android::base::GetProperty("media.settings.xml", "");
     if (mediaSettingsPath.empty()) {
-        mediaSettingsPath.assign("/vendor/etc/media_profiles_V1_0.xml");
-    }
+        // If "media.settings.xml" is not set, we will search through a list of
+        // file paths.
 
-    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(android::base::Basename(mediaSettingsPath).c_str(),
-                                            {android::base::Dirname(mediaSettingsPath).c_str()},
-                                            "/data/local/tmp/media_profiles.xsd");
+        constexpr char const* xmlSearchDirs[] = {
+                "/product/etc/",
+                "/odm/etc/",
+                "/vendor/etc/",
+            };
+
+        // The vendor may provide a vendor variant for the file name.
+        std::string variant = android::base::GetProperty(
+                "ro.media.xml_variant.profiles", "_V1_0");
+        std::string fileName = "media_profiles" + variant + ".xml";
+
+        // Fallback path does not depend on the property defined from the vendor
+        // partition.
+        constexpr char const* fallbackXmlPath =
+                "/system/etc/media_profiles_V1_0.xml";
+
+        std::vector<std::string> xmlPaths = {
+                xmlSearchDirs[0] + fileName,
+                xmlSearchDirs[1] + fileName,
+                xmlSearchDirs[2] + fileName,
+                fallbackXmlPath
+            };
+
+        auto findXmlPath =
+            std::find_if(xmlPaths.begin(), xmlPaths.end(), isFileReadable);
+        ASSERT_TRUE(findXmlPath != xmlPaths.end())
+                << "Cannot read from " << fileName
+                << " in any search directories ("
+                << xmlSearchDirs[0] << ", "
+                << xmlSearchDirs[1] << ", "
+                << xmlSearchDirs[2] << ") and from "
+                << fallbackXmlPath << ".";
+
+        char const* xmlPath = findXmlPath->c_str();
+        EXPECT_VALID_XML(xmlPath, xsdPath);
+    } else {
+        EXPECT_VALID_XML(mediaSettingsPath.c_str(), xsdPath);
+    }
 }
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index cb6798e..af8096d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3148,11 +3148,17 @@
             if (buffer->meta_data().findInt32(kKeyIsEndOfStream, &isEOS) && isEOS) {
                 int64_t eosSampleTimestampUs = -1;
                 CHECK(buffer->meta_data().findInt64(kKeyTime, &eosSampleTimestampUs));
-                ALOGV("eosSampleTimestampUs:%" PRId64, eosSampleTimestampUs);
-                lastSampleDurationUs = eosSampleTimestampUs - previousSampleTimestampWithoutFudgeUs
-                                       - previousPausedDurationUs;
-                CHECK(lastSampleDurationUs >= 0);
-                lastSampleDurationTicks = (lastSampleDurationUs * mTimeScale + 500000LL)/1000000LL;
+                if (eosSampleTimestampUs > 0) {
+                    lastSampleDurationUs = eosSampleTimestampUs -
+                                           previousSampleTimestampWithoutFudgeUs -
+                                           previousPausedDurationUs;
+                    if (lastSampleDurationUs >= 0) {
+                        lastSampleDurationTicks = (lastSampleDurationUs * mTimeScale + 500000LL) /
+                                                  1000000LL;
+                    } else {
+                        ALOGW("lastSampleDurationUs %" PRId64 " is negative", lastSampleDurationUs);
+                    }
+                }
                 buffer->release();
                 buffer = nullptr;
                 mSource->stop();
diff --git a/media/libstagefright/codecs/amrwb/Android.bp b/media/libstagefright/codecs/amrwb/Android.bp
index 88cf7f2..d8cb568 100644
--- a/media/libstagefright/codecs/amrwb/Android.bp
+++ b/media/libstagefright/codecs/amrwb/Android.bp
@@ -1,6 +1,7 @@
 cc_library_static {
     name: "libstagefright_amrwbdec",
     vendor_available: true,
+    host_supported: true,
 
     srcs: [
         "src/agc2_amr_wb.cpp",
@@ -44,8 +45,6 @@
         "src/weight_amrwb_lpc.cpp",
     ],
 
-    header_libs: ["libstagefright_headers"],
-
     export_include_dirs: [
         "src",
         "include",
@@ -63,12 +62,19 @@
             "signed-integer-overflow",
         ],
     },
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 //###############################################################################
 cc_test {
     name: "libstagefright_amrwbdec_test",
     gtest: false,
+    host_supported: true,
 
     srcs: ["test/amrwbdec_test.cpp"],
 
@@ -88,4 +94,10 @@
             "signed-integer-overflow",
         ],
     },
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/Android.bp b/media/libstagefright/codecs/amrwb/fuzzer/Android.bp
new file mode 100644
index 0000000..46f77e3
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/fuzzer/Android.bp
@@ -0,0 +1,35 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+    name: "amrwb_dec_fuzzer",
+    host_supported: true,
+    srcs: [
+        "amrwb_dec_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libstagefright_amrwbdec",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/README.md b/media/libstagefright/codecs/amrwb/fuzzer/README.md
new file mode 100644
index 0000000..de45784
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/fuzzer/README.md
@@ -0,0 +1,61 @@
+# Fuzzer for libstagefright_amrwbdec decoder
+
+## Plugin Design Considerations
+The fuzzer plugin for AMR-WB is designed based on the understanding of the
+codec and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+AMR-WB supports the following parameters:
+1. Quality (parameter name: `quality`)
+2. Mode (parameter name: `mode`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `quality` | 0. `Bad Quality` 1. `Good quality` | Bit 0 (LSB) of 1st byte of data. |
+| `mode`   | 0. `MODE_7k` 1. `MODE_9k` 2. `MODE_12k` 3. `MODE_14k`  4. `MODE_16k ` 5. `MODE_18k` 6. `MODE_20k` 7. `MODE_23k` 8. `MODE_24k` 9. `MRDTX`  | Bits 3, 4, 5 and 6 of 1st byte of data. |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the codec using a loop.
+If the decode operation was successful, the input is advanced by the frame size
+which is based on `mode` and `quality` selected.
+If the decode operation was un-successful, the input is still advanced by frame size so
+that the fuzzer can proceed to feed the next frame.
+
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build amrwb_dec_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) amrwb_dec_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some amrwb files to that folder
+Push this directory to device.
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/amrwb_dec_fuzzer/amrwb_dec_fuzzer CORPUS_DIR
+```
+To run on host
+```
+  $ $ANDROID_HOST_OUT/fuzz/x86_64/amrwb_dec_fuzzer/amrwb_dec_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp b/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp
new file mode 100644
index 0000000..6dc0270
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp
@@ -0,0 +1,110 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <malloc.h>
+#include <string.h>
+#include <algorithm>
+#include "pvamrwbdecoder.h"
+#include "pvamrwbdecoder_api.h"
+
+// Constants for AMR-WB.
+constexpr int32_t kSamplesPerFrame = 320;
+constexpr int32_t kBitsPerSample = 16;
+constexpr int32_t kMaxSourceDataUnitSize = KAMRWB_NB_BITS_MAX * sizeof(int16_t);
+constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
+constexpr int32_t kFrameSizes[16] = {17, 23, 32, 36, 40, 46, 50, 58,
+                                     60, 17, 23, 32, 36, 40, 46, 50};
+
+class Codec {
+ public:
+  Codec() = default;
+  ~Codec() { deInitDecoder(); }
+  bool initDecoder();
+  void decodeFrames(const uint8_t *data, size_t size);
+  void deInitDecoder();
+
+ private:
+  void *mAmrHandle = nullptr;
+  int16_t *mDecoderCookie = nullptr;
+  void *mDecoderBuffer = nullptr;
+};
+
+bool Codec::initDecoder() {
+  mDecoderBuffer = malloc(pvDecoder_AmrWbMemRequirements());
+  if (mDecoderBuffer) {
+    pvDecoder_AmrWb_Init(&mAmrHandle, mDecoderBuffer, &mDecoderCookie);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+void Codec::deInitDecoder() {
+  if (mDecoderBuffer) {
+    free(mDecoderBuffer);
+    mDecoderBuffer = nullptr;
+  }
+  mAmrHandle = nullptr;
+  mDecoderCookie = nullptr;
+}
+
+void Codec::decodeFrames(const uint8_t *data, size_t size) {
+  while (size > 0) {
+    uint8_t modeByte = *data;
+    bool quality = modeByte & 0x01;
+    int16 mode = ((modeByte >> 3) & 0x0f);
+    ++data;
+    --size;
+    int32_t frameSize = kFrameSizes[mode];
+    int16_t inputSampleBuf[kMaxSourceDataUnitSize];
+    uint8_t *inputBuf = new uint8_t[frameSize];
+    if (!inputBuf) {
+      return;
+    }
+    int32_t minSize = std::min((int32_t)size, frameSize);
+    memcpy(inputBuf, data, minSize);
+    int16 frameMode = mode;
+    int16 frameType;
+    RX_State_wb rx_state;
+    mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, quality, &rx_state);
+
+    int16_t numSamplesOutput;
+    int16_t outputBuf[kOutputBufferSize];
+    pvDecoder_AmrWb(frameMode, inputSampleBuf, outputBuf, &numSamplesOutput, mDecoderBuffer,
+                    frameType, mDecoderCookie);
+    data += minSize;
+    size -= minSize;
+    delete[] inputBuf;
+  }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size < 2) {
+    return 0;
+  }
+  Codec *codec = new Codec();
+  if (!codec) {
+    return 0;
+  }
+  if (codec->initDecoder()) {
+    codec->decodeFrames(data, size);
+  }
+  delete codec;
+  return 0;
+}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 2f69f45..5b2f6de 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -47,6 +47,8 @@
 
 #include <hidlmemory/mapping.h>
 
+#include <vector>
+
 static const OMX_U32 kPortIndexInput = 0;
 static const OMX_U32 kPortIndexOutput = 1;
 
@@ -493,9 +495,7 @@
 
         case OMX_StateLoaded:
         {
-            if (mActiveBuffers.size() > 0) {
-                freeActiveBuffers();
-            }
+            freeActiveBuffers();
             FALLTHROUGH_INTENDED;
         }
         case OMX_StateInvalid:
@@ -2430,11 +2430,19 @@
 }
 
 void OMXNodeInstance::freeActiveBuffers() {
-    // Make sure to count down here, as freeBuffer will in turn remove
-    // the active buffer from the vector...
-    for (size_t i = mActiveBuffers.size(); i > 0;) {
-        i--;
-        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
+    std::vector<OMX_U32> portIndices;
+    std::vector<IOMX::buffer_id> bufferIds;
+    {
+        // Access to mActiveBuffers must be protected by mLock.
+        Mutex::Autolock _l(mLock);
+        for (const ActiveBuffer& activeBuffer : mActiveBuffers) {
+            portIndices.emplace_back(activeBuffer.mPortIndex);
+            bufferIds.emplace_back(activeBuffer.mID);
+        }
+    }
+    for (size_t i = bufferIds.size(); i > 0; ) {
+        --i;
+        freeBuffer(portIndices[i], bufferIds[i]);
     }
 }
 
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index d905b8d..a232150 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -21,6 +21,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/properties.h>
 #include <utils/Log.h>
 
 #include <media/stagefright/MediaErrors.h>
@@ -38,8 +39,6 @@
 
 namespace android {
 
-using MCXP = MediaCodecsXmlParser;
-
 namespace {
 
 bool fileExists(const std::string &path) {
@@ -118,8 +117,8 @@
     }
 }
 
-MCXP::StringSet parseCommaSeparatedStringSet(const char *s) {
-    MCXP::StringSet result;
+MediaCodecsXmlParser::StringSet parseCommaSeparatedStringSet(const char *s) {
+    MediaCodecsXmlParser::StringSet result;
     for (const char *ptr = s ? : ""; *ptr; ) {
         const char *end = strchrnul(ptr, ',');
         if (ptr != end) { // skip empty values
@@ -136,6 +135,23 @@
 
 }  // unnamed namespace
 
+std::vector<std::string> MediaCodecsXmlParser::getDefaultXmlNames() {
+    static constexpr char const* prefixes[] = {
+            "media_codecs",
+            "media_codecs_performance"
+        };
+    static std::vector<std::string> variants = {
+            android::base::GetProperty("ro.media.xml_variant.codecs", ""),
+            android::base::GetProperty("ro.media.xml_variant.codecs_performance", "")
+        };
+    static std::vector<std::string> names = {
+            prefixes[0] + variants[0] + ".xml",
+            prefixes[1] + variants[1] + ".xml"
+        };
+    return names;
+}
+
+
 struct MediaCodecsXmlParser::Impl {
     // status + error message
     struct Result {
diff --git a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
index b666de4..e224452 100644
--- a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
+++ b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
@@ -33,13 +33,17 @@
 class MediaCodecsXmlParser {
 public:
 
-    // Treblized media codec list will be located in /odm/etc or /vendor/etc.
+    // Treblized media codec list will be located in /product/etc, /odm/etc or
+    // /vendor/etc.
     static std::vector<std::string> getDefaultSearchDirs() {
-            return { "/odm/etc", "/vendor/etc", "/etc" };
+        return { "/product/etc",
+                 "/odm/etc",
+                 "/vendor/etc",
+                 "/system/etc" };
     }
-    static std::vector<std::string> getDefaultXmlNames() {
-            return { "media_codecs.xml", "media_codecs_performance.xml" };
-    }
+
+    static std::vector<std::string> getDefaultXmlNames();
+
     static constexpr char const* defaultProfilingResultsXmlPath =
             "/data/misc/media/media_codecs_profiling_results.xml";
 
diff --git a/media/libwatchdog/Android.bp b/media/libwatchdog/Android.bp
index 849623a..2aefa7d 100644
--- a/media/libwatchdog/Android.bp
+++ b/media/libwatchdog/Android.bp
@@ -19,10 +19,8 @@
     ],
     export_include_dirs: ["include"],
     shared_libs: [
-        "liblog",
-    ],
-    static_libs: [
         "libbase",
+        "liblog",
     ],
     target: {
         windows: {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 74a09d1..ecda56b 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3375,6 +3375,7 @@
         const AudioDeviceTypeAddr& device,
         const String16& opPackageName,
         pid_t pid,
+        bool probe,
         status_t *status,
         int *id,
         int *enabled)
@@ -3490,10 +3491,10 @@
 
         if (sessionId == AUDIO_SESSION_DEVICE) {
             sp<Client> client = registerPid(pid);
-            ALOGV("%s device type %d address %s", __func__, device.mType, device.getAddress());
+            ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress());
             handle = mDeviceEffectManager.createEffect_l(
                     &desc, device, client, effectClient, mPatchPanel.patches_l(),
-                    enabled, &lStatus);
+                    enabled, &lStatus, probe);
             if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
                 // remove local strong reference to Client with mClientLock held
                 Mutex::Autolock _cl(mClientLock);
@@ -3588,7 +3589,7 @@
         // create effect on selected output thread
         bool pinned = !audio_is_global_session(sessionId) && isSessionAcquired_l(sessionId);
         handle = thread->createEffect_l(client, effectClient, priority, sessionId,
-                &desc, enabled, &lStatus, pinned);
+                &desc, enabled, &lStatus, pinned, probe);
         if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
             // remove local strong reference to Client with mClientLock held
             Mutex::Autolock _cl(mClientLock);
@@ -3600,7 +3601,7 @@
     }
 
 Register:
-    if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
+    if (!probe && (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS)) {
         // Check CPU and memory usage
         sp<EffectBase> effect = handle->effect().promote();
         if (effect != nullptr) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 6d7bf3c..40519b0 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -238,6 +238,7 @@
                         const AudioDeviceTypeAddr& device,
                         const String16& opPackageName,
                         pid_t pid,
+                        bool probe,
                         status_t *status /*non-NULL*/,
                         int *id,
                         int *enabled);
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 87a4c6e..a3c3b84 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -74,13 +74,14 @@
         const sp<IEffectClient>& effectClient,
         const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
         int *enabled,
-        status_t *status) {
+        status_t *status,
+        bool probe) {
     sp<DeviceEffectProxy> effect;
     sp<EffectHandle> handle;
     status_t lStatus;
 
     lStatus = checkEffectCompatibility(descriptor);
-    if (lStatus != NO_ERROR) {
+    if (probe || lStatus != NO_ERROR) {
        *status = lStatus;
        return handle;
     }
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index 14ff14d..81e6065 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -36,7 +36,8 @@
                 const sp<IEffectClient>& effectClient,
                 const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
                 int *enabled,
-                status_t *status);
+                status_t *status,
+                bool probe);
     void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
     void releaseAudioPatch(audio_patch_handle_t handle);
 
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 82b9c96..8a65122 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -3047,7 +3047,7 @@
         int enabled;
         *handle = thread->createEffect_l(nullptr, nullptr, 0, AUDIO_SESSION_DEVICE,
                                          const_cast<effect_descriptor_t *>(&mDescriptor),
-                                         &enabled, &status, false);
+                                         &enabled, &status, false, false /*probe*/);
         ALOGV("%s thread->createEffect_l status %d", __func__, status);
     } else {
         status = BAD_VALUE;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index f24dcd7..dc39b62 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1365,7 +1365,8 @@
         effect_descriptor_t *desc,
         int *enabled,
         status_t *status,
-        bool pinned)
+        bool pinned,
+        bool probe)
 {
     sp<EffectModule> effect;
     sp<EffectHandle> handle;
@@ -1387,7 +1388,7 @@
         Mutex::Autolock _l(mLock);
 
         lStatus = checkEffectCompatibility_l(desc, sessionId);
-        if (lStatus != NO_ERROR) {
+        if (probe || lStatus != NO_ERROR) {
             goto Exit;
         }
 
@@ -1433,7 +1434,7 @@
     }
 
 Exit:
-    if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+    if (!probe && lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
         Mutex::Autolock _l(mLock);
         if (effectCreated) {
             chain->removeEffect_l(effect);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 153cf7c..8149e95 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -342,7 +342,8 @@
                                     effect_descriptor_t *desc,
                                     int *enabled,
                                     status_t *status /*non-NULL*/,
-                                    bool pinned);
+                                    bool pinned,
+                                    bool probe);
 
                 // return values for hasAudioSession (bit field)
                 enum effect_state {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index dd51658..aaa28bc 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -33,7 +33,10 @@
 
 namespace android {
 
-DeviceTypeSet APM_AUDIO_OUT_DEVICE_REMOTE_ALL = {AUDIO_DEVICE_OUT_REMOTE_SUBMIX};
+static const DeviceTypeSet& getAllOutRemoteDevices() {
+    static const DeviceTypeSet allOutRemoteDevices = {AUDIO_DEVICE_OUT_REMOTE_SUBMIX};
+    return allOutRemoteDevices;
+}
 
 AudioOutputDescriptor::AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
                                              AudioPolicyClientInterface *clientInterface)
@@ -681,7 +684,7 @@
         const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
         if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
                 && (!(outputDesc->devices()
-                        .containsDeviceAmongTypes(APM_AUDIO_OUT_DEVICE_REMOTE_ALL)))) {
+                        .containsDeviceAmongTypes(getAllOutRemoteDevices())))) {
             return true;
         }
     }
@@ -693,7 +696,7 @@
     nsecs_t sysTime = systemTime();
     for (size_t i = 0; i < size(); i++) {
         const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
-        if (outputDesc->devices().containsDeviceAmongTypes(APM_AUDIO_OUT_DEVICE_REMOTE_ALL) &&
+        if (outputDesc->devices().containsDeviceAmongTypes(getAllOutRemoteDevices()) &&
                 outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
             // do not consider re routing (when the output is going to a dynamic policy)
             // as "remote playback"
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index a7d7cf6..b14d2bb 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -41,20 +41,23 @@
 {
 
 struct legacy_strategy_map { const char *name; legacy_strategy id; };
-static const std::vector<legacy_strategy_map> gLegacyStrategy = {
-    { "STRATEGY_NONE", STRATEGY_NONE },
-    { "STRATEGY_MEDIA", STRATEGY_MEDIA },
-    { "STRATEGY_PHONE", STRATEGY_PHONE },
-    { "STRATEGY_SONIFICATION", STRATEGY_SONIFICATION },
-    { "STRATEGY_SONIFICATION_RESPECTFUL", STRATEGY_SONIFICATION_RESPECTFUL },
-    { "STRATEGY_DTMF", STRATEGY_DTMF },
-    { "STRATEGY_ENFORCED_AUDIBLE", STRATEGY_ENFORCED_AUDIBLE },
-    { "STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER },
-    { "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
-    { "STRATEGY_REROUTING", STRATEGY_REROUTING },
-    { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
-    { "STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT },
-};
+static const std::vector<legacy_strategy_map>& getLegacyStrategy() {
+    static const std::vector<legacy_strategy_map> legacyStrategy = {
+        { "STRATEGY_NONE", STRATEGY_NONE },
+        { "STRATEGY_MEDIA", STRATEGY_MEDIA },
+        { "STRATEGY_PHONE", STRATEGY_PHONE },
+        { "STRATEGY_SONIFICATION", STRATEGY_SONIFICATION },
+        { "STRATEGY_SONIFICATION_RESPECTFUL", STRATEGY_SONIFICATION_RESPECTFUL },
+        { "STRATEGY_DTMF", STRATEGY_DTMF },
+        { "STRATEGY_ENFORCED_AUDIBLE", STRATEGY_ENFORCED_AUDIBLE },
+        { "STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER },
+        { "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
+        { "STRATEGY_REROUTING", STRATEGY_REROUTING },
+        { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
+        { "STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT },
+    };
+    return legacyStrategy;
+}
 
 Engine::Engine()
 {
@@ -63,7 +66,8 @@
              "Policy Engine configuration is partially invalid, skipped %zu elements",
              result.nbSkippedElement);
 
-    for (const auto &strategy : gLegacyStrategy) {
+    auto legacyStrategy = getLegacyStrategy();
+    for (const auto &strategy : legacyStrategy) {
         mLegacyStrategyMap[getProductStrategyByName(strategy.name)] = strategy.id;
     }
 }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 5a012bf..ffc3a0f 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5710,7 +5710,10 @@
             patchBuilder.addSink(filteredDevice);
         }
 
-        installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
+        // Add half reported latency to delayMs when muteWaitMs is null in order
+        // to avoid disordered sequence of muting volume and changing devices.
+        installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(),
+                muteWaitMs == 0 ? (delayMs + (outputDesc->latency() / 2)) : delayMs);
     }
 
     // update stream volumes according to new device
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index e0884f4..9bc79e0 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2049,7 +2049,7 @@
     return Status::ok();
 }
 
- Status CameraService::getConcurrentStreamingCameraIds(
+ Status CameraService::getConcurrentCameraIds(
         std::vector<ConcurrentCameraIdCombination>* concurrentCameraIds) {
     ATRACE_CALL();
     if (!concurrentCameraIds) {
@@ -2065,7 +2065,7 @@
     // First call into the provider and get the set of concurrent camera
     // combinations
     std::vector<std::unordered_set<std::string>> concurrentCameraCombinations =
-            mCameraProviderManager->getConcurrentStreamingCameraIds();
+            mCameraProviderManager->getConcurrentCameraIds();
     for (auto &combination : concurrentCameraCombinations) {
         std::vector<std::string> validCombination;
         for (auto &cameraId : combination) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index f12b4cc..1adf15a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -152,7 +152,7 @@
     virtual binder::Status    removeListener(
             const sp<hardware::ICameraServiceListener>& listener);
 
-    virtual binder::Status getConcurrentStreamingCameraIds(
+    virtual binder::Status getConcurrentCameraIds(
         /*out*/
         std::vector<hardware::camera2::utils::ConcurrentCameraIdCombination>* concurrentCameraIds);
 
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 1d794a1..cc369fa 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1362,7 +1362,7 @@
 
     // Get list of concurrent streaming camera device combinations
     if (mMinorVersion >= 6) {
-        res = getConcurrentStreamingCameraIdsInternalLocked(interface2_6);
+        res = getConcurrentCameraIdsInternalLocked(interface2_6);
         if (res != OK) {
             return res;
         }
@@ -1616,7 +1616,7 @@
     return OK;
 }
 
-status_t CameraProviderManager::ProviderInfo::getConcurrentStreamingCameraIdsInternalLocked(
+status_t CameraProviderManager::ProviderInfo::getConcurrentCameraIdsInternalLocked(
         sp<provider::V2_6::ICameraProvider> &interface2_6) {
     if (interface2_6 == nullptr) {
         ALOGE("%s: null interface provided", __FUNCTION__);
@@ -1669,7 +1669,7 @@
     if (castResult.isOk()) {
         sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
         if (interface2_6 != nullptr) {
-            return getConcurrentStreamingCameraIdsInternalLocked(interface2_6);
+            return getConcurrentCameraIdsInternalLocked(interface2_6);
         } else {
             // This should not happen since mMinorVersion >= 6
             ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
@@ -2809,7 +2809,7 @@
 
 // Expects to have mInterfaceMutex locked
 std::vector<std::unordered_set<std::string>>
-CameraProviderManager::getConcurrentStreamingCameraIds() const {
+CameraProviderManager::getConcurrentCameraIds() const {
     std::vector<std::unordered_set<std::string>> deviceIdCombinations;
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     for (auto &provider : mProviders) {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 5359c39..50044d8 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -221,7 +221,7 @@
                     &cameraIdsAndSessionConfigs,
             bool *isSupported);
 
-    std::vector<std::unordered_set<std::string>> getConcurrentStreamingCameraIds() const;
+    std::vector<std::unordered_set<std::string>> getConcurrentCameraIds() const;
     /**
      * Check for device support of specific stream combination.
      */
@@ -630,7 +630,7 @@
         // Expects to have mLock locked
         status_t reCacheConcurrentStreamingCameraIdsLocked();
         // Expects to have mLock locked
-        status_t getConcurrentStreamingCameraIdsInternalLocked(
+        status_t getConcurrentCameraIdsInternalLocked(
                 sp<hardware::camera::provider::V2_6::ICameraProvider> &interface2_6);
     };
 
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
index 07536fc..e1f7fe7 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
@@ -48,6 +48,14 @@
 # for dynamically loading extractors
 pread64: 1
 
+# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
+# parser support for '<' is in this needs to be modified to also prevent
+# |old_address| and |new_address| from touching the exception vector page, which
+# on ARM is statically loaded at 0xffff 0000. See
+# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
+# for more details.
+mremap: arg3 == 3 || arg3 == MREMAP_MAYMOVE
+
 # for FileSource
 readlinkat: 1
 _llseek: 1