Merge "C2SoftAomEnc: Fix encoding issues with 10bit av1 clips" into udc-dev
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index 6fff568..4affaed 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -108,7 +108,7 @@
     aaudio_result_t    outputError = AAUDIO_OK;
 
     GlitchAnalyzer     sineAnalyzer;
-    PulseLatencyAnalyzer echoAnalyzer;
+    WhiteNoiseLatencyAnalyzer echoAnalyzer;
     AudioRecording     audioRecording;
     LoopbackProcessor *loopbackProcessor;
 
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index c8461cc..f305e46 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -206,7 +206,7 @@
     return validateChannelMask();
 }
 
-bool AAudioStreamParameters::validateChannelMask() const {
+aaudio_result_t AAudioStreamParameters::validateChannelMask() const {
     if (mChannelMask == AAUDIO_UNSPECIFIED) {
         return AAUDIO_OK;
     }
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.h b/media/libaaudio/src/core/AAudioStreamParameters.h
index 565d54c..7c78f03 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.h
+++ b/media/libaaudio/src/core/AAudioStreamParameters.h
@@ -213,7 +213,7 @@
     void dump() const;
 
 private:
-    bool validateChannelMask() const;
+    aaudio_result_t validateChannelMask() const;
 
     int32_t                         mSamplesPerFrame      = AAUDIO_UNSPECIFIED;
     int32_t                         mSampleRate           = AAUDIO_UNSPECIFIED;
diff --git a/media/libaudioclient/AudioProductStrategy.cpp b/media/libaudioclient/AudioProductStrategy.cpp
index 381faf6..d9fd58c 100644
--- a/media/libaudioclient/AudioProductStrategy.cpp
+++ b/media/libaudioclient/AudioProductStrategy.cpp
@@ -60,25 +60,50 @@
 }
 
 // Keep in sync with android/media/audiopolicy/AudioProductStrategy#attributeMatches
-bool AudioProductStrategy::attributesMatches(const audio_attributes_t refAttributes,
-                                        const audio_attributes_t clientAttritubes)
+int AudioProductStrategy::attributesMatchesScore(const audio_attributes_t refAttributes,
+                                                 const audio_attributes_t clientAttritubes)
 {
+    if (refAttributes == clientAttritubes) {
+        return MATCH_EQUALS;
+    }
     if (refAttributes == AUDIO_ATTRIBUTES_INITIALIZER) {
         // The default product strategy is the strategy that holds default attributes by convention.
         // All attributes that fail to match will follow the default strategy for routing.
-        // Choosing the default must be done as a fallback, the attributes match shall not
-        // select the default.
-        return false;
+        // Choosing the default must be done as a fallback,so return a default (zero) score to
+        // allow identify the fallback.
+        return MATCH_ON_DEFAULT_SCORE;
     }
-    return ((refAttributes.usage == AUDIO_USAGE_UNKNOWN) ||
-            (clientAttritubes.usage == refAttributes.usage)) &&
-            ((refAttributes.content_type == AUDIO_CONTENT_TYPE_UNKNOWN) ||
-             (clientAttritubes.content_type == refAttributes.content_type)) &&
-            ((refAttributes.flags == AUDIO_FLAG_NONE) ||
-             (clientAttritubes.flags != AUDIO_FLAG_NONE &&
-            (clientAttritubes.flags & refAttributes.flags) == refAttributes.flags)) &&
-            ((strlen(refAttributes.tags) == 0) ||
-             (std::strcmp(clientAttritubes.tags, refAttributes.tags) == 0));
+    int score = MATCH_ON_DEFAULT_SCORE;
+    if (refAttributes.usage == AUDIO_USAGE_UNKNOWN) {
+        score |= MATCH_ON_DEFAULT_SCORE;
+    } else if (clientAttritubes.usage == refAttributes.usage) {
+        score |= MATCH_ON_USAGE_SCORE;
+    } else {
+        return NO_MATCH;
+    }
+    if (refAttributes.content_type == AUDIO_CONTENT_TYPE_UNKNOWN) {
+        score |= MATCH_ON_DEFAULT_SCORE;
+    } else if (clientAttritubes.content_type == refAttributes.content_type) {
+        score |= MATCH_ON_CONTENT_TYPE_SCORE;
+    } else {
+        return NO_MATCH;
+    }
+    if (strlen(refAttributes.tags) == 0) {
+        score |= MATCH_ON_DEFAULT_SCORE;
+    } else if (std::strcmp(clientAttritubes.tags, refAttributes.tags) == 0) {
+        score |= MATCH_ON_TAGS_SCORE;
+    } else {
+        return NO_MATCH;
+    }
+    if (refAttributes.flags == AUDIO_FLAG_NONE) {
+        score |= MATCH_ON_DEFAULT_SCORE;
+    } else if ((clientAttritubes.flags != AUDIO_FLAG_NONE)
+            && ((clientAttritubes.flags & refAttributes.flags) == refAttributes.flags)) {
+        score |= MATCH_ON_FLAGS_SCORE;
+    } else {
+        return NO_MATCH;
+    }
+    return score;
 }
 
 } // namespace android
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 706f51f..28d76d7 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2136,8 +2136,7 @@
         if (strategy.getId() == psId) {
             auto attrVect = strategy.getVolumeGroupAttributes();
             auto iter = std::find_if(begin(attrVect), end(attrVect), [&attr](const auto& refAttr) {
-                return AudioProductStrategy::attributesMatches(
-                        refAttr.getAttributes(), attr);
+                return refAttr.matchesScore(attr) > 0;
             });
             if (iter != end(attrVect)) {
                 return iter->getStreamType();
diff --git a/media/libaudioclient/VolumeGroupAttributes.cpp b/media/libaudioclient/VolumeGroupAttributes.cpp
index 2de4667..530e73f 100644
--- a/media/libaudioclient/VolumeGroupAttributes.cpp
+++ b/media/libaudioclient/VolumeGroupAttributes.cpp
@@ -21,11 +21,16 @@
 #include <binder/Parcel.h>
 
 #include <media/AidlConversion.h>
+#include <media/AudioProductStrategy.h>
 #include <media/VolumeGroupAttributes.h>
 #include <media/PolicyAidlConversion.h>
 
 namespace android {
 
+int VolumeGroupAttributes::matchesScore(const audio_attributes_t &attributes) const {
+    return AudioProductStrategy::attributesMatchesScore(mAttributes, attributes);
+}
+
 status_t VolumeGroupAttributes::readFromParcel(const Parcel* parcel) {
     media::AudioAttributesEx aidl;
     RETURN_STATUS_IF_ERROR(aidl.readFromParcel(parcel));
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 3fd438e..ec35e93 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -66,7 +66,7 @@
 #define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK | \
     MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE)
 
-#define MAX_MIXES_PER_POLICY 10
+#define MAX_MIXES_PER_POLICY 50
 #define MAX_CRITERIA_PER_MIX 20
 
 class AudioMixMatchCriterion {
diff --git a/media/libaudioclient/include/media/AudioProductStrategy.h b/media/libaudioclient/include/media/AudioProductStrategy.h
index 7bcb5aa..fcbb019 100644
--- a/media/libaudioclient/include/media/AudioProductStrategy.h
+++ b/media/libaudioclient/include/media/AudioProductStrategy.h
@@ -46,19 +46,35 @@
     status_t writeToParcel(Parcel *parcel) const override;
 
     /**
-     * @brief attributesMatches: checks if client attributes matches with a reference attributes
-     * "matching" means the usage shall match if reference attributes has a defined usage, AND
-     * content type shall match if reference attributes has a defined content type AND
+     * @brief attributesMatchesScore: checks if client attributes matches with a reference
+     * attributes "matching" means the usage shall match if reference attributes has a defined
+     * usage, AND content type shall match if reference attributes has a defined content type AND
      * flags shall match if reference attributes has defined flags AND
      * tags shall match if reference attributes has defined tags.
-     * Reference attributes "default" shall not be considered as a "true" case. This convention
+     * Reference attributes "default" shall be considered as a weak match case. This convention
      * is used to identify the default strategy.
      * @param refAttributes to be considered
      * @param clientAttritubes to be considered
-     * @return true if matching, false otherwise
+     * @return {@code INVALID_SCORE} if not matching, {@code MATCH_ON_DEFAULT_SCORE} if matching
+     * to default strategy, non zero positive score if matching a strategy.
      */
+    static int attributesMatchesScore(const audio_attributes_t refAttributes,
+                                      const audio_attributes_t clientAttritubes);
+
     static bool attributesMatches(const audio_attributes_t refAttributes,
-                                  const audio_attributes_t clientAttritubes);
+                                      const audio_attributes_t clientAttritubes) {
+        return attributesMatchesScore(refAttributes, clientAttritubes) > 0;
+    }
+
+    static const int MATCH_ON_TAGS_SCORE = 1 << 3;
+    static const int MATCH_ON_FLAGS_SCORE = 1 << 2;
+    static const int MATCH_ON_USAGE_SCORE = 1 << 1;
+    static const int MATCH_ON_CONTENT_TYPE_SCORE = 1 << 0;
+    static const int MATCH_ON_DEFAULT_SCORE = 0;
+    static const int MATCH_EQUALS = MATCH_ON_TAGS_SCORE | MATCH_ON_FLAGS_SCORE
+            | MATCH_ON_USAGE_SCORE | MATCH_ON_CONTENT_TYPE_SCORE;
+    static const int NO_MATCH = -1;
+
 private:
     std::string mName;
     std::vector<VolumeGroupAttributes> mVolumeGroupAttributes;
diff --git a/media/libaudioclient/include/media/VolumeGroupAttributes.h b/media/libaudioclient/include/media/VolumeGroupAttributes.h
index 0859995..46b3612 100644
--- a/media/libaudioclient/include/media/VolumeGroupAttributes.h
+++ b/media/libaudioclient/include/media/VolumeGroupAttributes.h
@@ -41,6 +41,8 @@
         mAttributes.source = AUDIO_SOURCE_INVALID;
     }
 
+    int matchesScore(const audio_attributes_t &attributes) const;
+
     audio_attributes_t getAttributes() const { return mAttributes; }
 
     status_t readFromParcel(const Parcel *parcel) override;
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
index 91c3dea..9ec593f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
@@ -82,7 +82,7 @@
     Parameter aidlParam;
     switch (type) {
         case BASSBOOST_PARAM_STRENGTH: {
-            uint32_t value;
+            uint16_t value;
             Parameter::Id id =
                     MAKE_SPECIFIC_PARAMETER_ID(BassBoost, bassBoostTag, BassBoost::strengthPm);
             RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
@@ -92,7 +92,7 @@
         }
         case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
             // an invalid range indicates not setting support for this parameter
-            uint16_t value =
+            uint32_t value =
                     ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::bassBoost>(
                             BassBoost::strengthPm, mDesc.capability);
             return param.writeToValue(&value);
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
index 960273b..0544e3f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
@@ -43,157 +43,208 @@
 using utils::EffectParamReader;
 using utils::EffectParamWriter;
 
-#define MAKE_AIDL_PARAMETER(aidlParam, param, value, tag)                            \
-    {                                                                                \
-        if (OK != param.readFromValue(&value)) {                                     \
-            ALOGE("%s invalid parameter %s %d", __func__, #tag, value);              \
-            return BAD_VALUE;                                                        \
-        }                                                                            \
-        aidlParam = MAKE_SPECIFIC_PARAMETER(                                         \
-                EnvironmentalReverb, environmentalReverb, tag,                       \
-                VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<int>(value))); \
+/**
+ * Macro to get a parameter from effect_param_t wrapper and set it to AIDL effect.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamReader, a reader wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define SET_AIDL_PARAMETER(param, aidlType, valueType, tag)                                \
+    {                                                                                      \
+        Parameter aidlParam;                                                               \
+        valueType value;                                                                   \
+        if (status_t status = param.readFromValue(&value); status != OK) {                 \
+            ALOGE("%s  %s read from parameter failed, ret %d", __func__, #tag, status);    \
+            return status;                                                                 \
+        }                                                                                  \
+        aidlParam = MAKE_SPECIFIC_PARAMETER(                                               \
+                EnvironmentalReverb, environmentalReverb, tag,                             \
+                VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<aidlType>(value)));  \
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); \
     }
 
-#define GET_AIDL_PARAMETER(tag, value, param)                                                      \
+/**
+ * Macro to get a parameter from AIDL effect and write the value to effect_param_t with wrapper.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamWriter, a writer wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType  Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define GET_AIDL_PARAMETER(param, aidltype, valueType, tag)                                        \
     {                                                                                              \
+        aidltype value;                                                                            \
         Parameter aidlParam;                                                                       \
         Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(EnvironmentalReverb, environmentalReverbTag, \
                                                       EnvironmentalReverb::tag);                   \
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));    \
-        value = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(                               \
-                aidlParam, EnvironmentalReverb, environmentalReverb, EnvironmentalReverb::tag,     \
-                std::decay_t<decltype(value)>));                                                   \
-        return param.writeToValue(&value);                                                         \
+        value = VALUE_OR_RETURN_STATUS(                                                            \
+                GET_PARAMETER_SPECIFIC_FIELD(aidlParam, EnvironmentalReverb, environmentalReverb,  \
+                                             EnvironmentalReverb::tag, std::decay_t<aidltype>));   \
+        if (status_t status = param.writeToValue((valueType*)&value); status != OK) {              \
+            param.setStatus(status);                                                               \
+            ALOGE("%s %s write to parameter failed %d, ret %d", __func__, #tag, value, status);    \
+            return status;                                                                         \
+        }                                                                                          \
     }
 
 status_t AidlConversionEnvReverb::setParameter(EffectParamReader& param) {
     uint32_t type = 0;
-    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
-        OK != param.readFromParameter(&type)) {
-        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+    if (status_t status = param.readFromParameter(&type); status != OK) {
+        ALOGE("%s failed to read type from %s, ret %d", __func__, param.toString().c_str(), status);
         return BAD_VALUE;
     }
-    Parameter aidlParam;
-    uint16_t value16;
-    uint32_t value32;
+
     switch (type) {
         case REVERB_PARAM_ROOM_LEVEL: {
-            MAKE_AIDL_PARAMETER(aidlParam, param, value16, roomLevelMb);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
             break;
         }
         case REVERB_PARAM_ROOM_HF_LEVEL: {
-            MAKE_AIDL_PARAMETER(aidlParam, param, value16, roomHfLevelMb);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
             break;
         }
         case REVERB_PARAM_DECAY_TIME: {
-            MAKE_AIDL_PARAMETER(aidlParam, param, value32, decayTimeMs);
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
             break;
         }
         case REVERB_PARAM_DECAY_HF_RATIO: {
-            MAKE_AIDL_PARAMETER(aidlParam, param, value16, decayHfRatioPm);
-            break;
-        }
-        case REVERB_PARAM_REVERB_LEVEL: {
-            MAKE_AIDL_PARAMETER(aidlParam, param, value16, levelMb);
-            break;
-        }
-        case REVERB_PARAM_REVERB_DELAY: {
-            MAKE_AIDL_PARAMETER(aidlParam, param, value32, delayMs);
-            break;
-        }
-        case REVERB_PARAM_DIFFUSION: {
-            MAKE_AIDL_PARAMETER(aidlParam, param, value16, diffusionPm);
-            break;
-        }
-        case REVERB_PARAM_DENSITY: {
-            MAKE_AIDL_PARAMETER(aidlParam, param, value16, densityPm);
-            break;
-        }
-        case REVERB_PARAM_BYPASS: {
-            if (OK != param.readFromValue(&value32)) {
-                ALOGE("%s invalid bypass parameter %d", __func__, value32);
-                return BAD_VALUE;
-            }
-            bool isByPass = VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<bool>(value32));
-            aidlParam = MAKE_SPECIFIC_PARAMETER(EnvironmentalReverb, environmentalReverb, bypass,
-                                                isByPass);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
             break;
         }
         case REVERB_PARAM_REFLECTIONS_LEVEL: {
-            // TODO
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
             break;
         }
         case REVERB_PARAM_REFLECTIONS_DELAY: {
-            // TODO
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+            break;
+        }
+        case REVERB_PARAM_REVERB_LEVEL: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+            break;
+        }
+        case REVERB_PARAM_REVERB_DELAY: {
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+            break;
+        }
+        case REVERB_PARAM_DIFFUSION: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+            break;
+        }
+        case REVERB_PARAM_DENSITY: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+            break;
+        }
+        case REVERB_PARAM_BYPASS: {
+            SET_AIDL_PARAMETER(param, bool, int32_t, bypass);
             break;
         }
         case REVERB_PARAM_PROPERTIES: {
-            // TODO
+            if (sizeof(t_reverb_settings) > param.getValueSize()) {
+                ALOGE("%s vsize %zu less than t_reverb_settings size %zu", __func__,
+                      param.getValueSize(), sizeof(t_reverb_settings));
+                return BAD_VALUE;
+            }
+            // this sequency needs to be aligned with t_reverb_settings
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
             break;
         }
         default: {
             // TODO: handle with vendor extension
         }
     }
-    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+    return OK;
 }
 
 status_t AidlConversionEnvReverb::getParameter(EffectParamWriter& param) {
     uint32_t type = 0;
-    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
-        OK != param.readFromParameter(&type)) {
-        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
-        param.setStatus(BAD_VALUE);
-        return BAD_VALUE;
+    if (status_t status = param.readFromParameter(&type); status != OK) {
+        ALOGE("%s failed to read type from %s", __func__, param.toString().c_str());
+        param.setStatus(status);
+        return status;
     }
-    uint16_t value16;
-    uint32_t value32;
+
     switch (type) {
         case REVERB_PARAM_ROOM_LEVEL: {
-            GET_AIDL_PARAMETER(roomLevelMb, value16, param);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+            break;
         }
         case REVERB_PARAM_ROOM_HF_LEVEL: {
-            GET_AIDL_PARAMETER(roomHfLevelMb, value16, param);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+            break;
         }
         case REVERB_PARAM_DECAY_TIME: {
-            GET_AIDL_PARAMETER(decayTimeMs, value32, param);
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+            break;
         }
         case REVERB_PARAM_DECAY_HF_RATIO: {
-            GET_AIDL_PARAMETER(decayHfRatioPm, value16, param);
-        }
-        case REVERB_PARAM_REVERB_LEVEL: {
-            GET_AIDL_PARAMETER(levelMb, value16, param);
-        }
-        case REVERB_PARAM_REVERB_DELAY: {
-            GET_AIDL_PARAMETER(delayMs, value32, param);
-        }
-        case REVERB_PARAM_DIFFUSION: {
-            GET_AIDL_PARAMETER(diffusionPm, value16, param);
-        }
-        case REVERB_PARAM_DENSITY: {
-            GET_AIDL_PARAMETER(densityPm, value16, param);
-        }
-        case REVERB_PARAM_BYPASS: {
-            bool isByPass;
-            GET_AIDL_PARAMETER(bypass, isByPass, param);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+            break;
         }
         case REVERB_PARAM_REFLECTIONS_LEVEL: {
-            // TODO
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
             break;
         }
         case REVERB_PARAM_REFLECTIONS_DELAY: {
-            // TODO
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+            break;
+        }
+        case REVERB_PARAM_REVERB_LEVEL: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+            break;
+        }
+        case REVERB_PARAM_REVERB_DELAY: {
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+            break;
+        }
+        case REVERB_PARAM_DIFFUSION: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+            break;
+        }
+        case REVERB_PARAM_DENSITY: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+            break;
+        }
+        case REVERB_PARAM_BYPASS: {
+            GET_AIDL_PARAMETER(param, bool, int32_t, bypass);
             break;
         }
         case REVERB_PARAM_PROPERTIES: {
-            // TODO
+            // this sequency needs to be aligned with t_reverb_settings
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
             break;
         }
         default: {
             // TODO: handle with vendor extension
+            return BAD_VALUE;
         }
     }
-    return BAD_VALUE;
+    return OK;
 }
 
 } // namespace effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
index 018f3bc..e9bdf94 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
@@ -184,6 +184,20 @@
                     EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
             return ndk::ScopedAStatus::ok();
         }
+        case EnvironmentalReverb::reflectionsLevelMb: {
+            RETURN_IF(mContext->setReflectionsLevel(
+                              erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::reflectionsDelayMs: {
+            RETURN_IF(mContext->setReflectionsDelay(
+                              erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
+            return ndk::ScopedAStatus::ok();
+        }
         case EnvironmentalReverb::levelMb: {
             RETURN_IF(mContext->setEnvironmentalReverbLevel(
                               erParam.get<EnvironmentalReverb::levelMb>()) != RetCode::SUCCESS,
@@ -292,6 +306,14 @@
                     mContext->getEnvironmentalReverbDecayHfRatio());
             break;
         }
+        case EnvironmentalReverb::reflectionsLevelMb: {
+            erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getReflectionsLevel());
+            break;
+        }
+        case EnvironmentalReverb::reflectionsDelayMs: {
+            erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getReflectionsDelay());
+            break;
+        }
         case EnvironmentalReverb::levelMb: {
             erParam.set<EnvironmentalReverb::levelMb>(mContext->getEnvironmentalReverbLevel());
             break;
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
index af49a25..9bb0b1a 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
@@ -83,6 +83,18 @@
     RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
     Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
 
+    RetCode setReflectionsDelay(int delay) {
+        mReflectionsDelayMs = delay;
+        return RetCode::SUCCESS;
+    }
+    bool getReflectionsDelay() const { return mReflectionsDelayMs; }
+
+    RetCode setReflectionsLevel(int level) {
+        mReflectionsLevelMb = level;
+        return RetCode::SUCCESS;
+    }
+    bool getReflectionsLevel() const { return mReflectionsLevelMb; }
+
     IEffect::Status lvmProcess(float* in, float* out, int samples);
 
   private:
@@ -146,15 +158,17 @@
     bool mEnabled = false;
     LVREV_Handle_t mInstance GUARDED_BY(mMutex);
 
-    int mRoomLevel;
-    int mRoomHfLevel;
-    int mDecayTime;
-    int mDecayHfRatio;
-    int mLevel;
-    int mDelay;
-    int mDiffusion;
-    int mDensity;
-    bool mBypass;
+    int mRoomLevel = 0;
+    int mRoomHfLevel = 0;
+    int mDecayTime = 0;
+    int mDecayHfRatio = 0;
+    int mLevel = 0;
+    int mDelay = 0;
+    int mDiffusion = 0;
+    int mDensity = 0;
+    bool mBypass = 0;
+    int mReflectionsLevelMb = 0;
+    int mReflectionsDelayMs = 0;
 
     PresetReverb::Presets mPreset;
     PresetReverb::Presets mNextPreset;
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 85768bd..5aa9adc 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -898,10 +898,9 @@
         }
     }
 
-    for (size_t cameraId = 0; cameraId < mCameraIds.size(); ++cameraId) {
+    for (size_t refIndex = 0; refIndex < mCameraIds.size(); ++refIndex) {
+        const int cameraId = mCameraIds[refIndex];
         for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
-            int refIndex = getRequiredProfileRefIndex(cameraId);
-            CHECK(refIndex != -1);
             RequiredProfileRefInfo *info =
                     &mRequiredProfileRefs[refIndex].mRefs[j];
 
@@ -931,14 +930,14 @@
 
                 int index = getCamcorderProfileIndex(cameraId, profile->mQuality);
                 if (index != -1) {
-                    ALOGV("Profile quality %d for camera %zu already exists",
+                    ALOGV("Profile quality %d for camera %d already exists",
                         profile->mQuality, cameraId);
                     CHECK(index == refIndex);
                     continue;
                 }
 
                 // Insert the new profile
-                ALOGV("Add a profile: quality %d=>%d for camera %zu",
+                ALOGV("Add a profile: quality %d=>%d for camera %d",
                         mCamcorderProfiles[info->mRefProfileIndex]->mQuality,
                         profile->mQuality, cameraId);
 
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 4b4f65f..5e7a4c4 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -458,6 +458,9 @@
         [[fallthrough]];
 
     case ColorUtils::kColorStandardUnspecified:
+        if (isFullRange) {
+            return is10Bit ? &BT2020_FULL : &BT601_FULL;
+        }
         return is10Bit ? &BT2020_LTD_10BIT : &BT601_LIMITED;
 
     }
diff --git a/media/module/extractors/ogg/OggExtractor.cpp b/media/module/extractors/ogg/OggExtractor.cpp
index 1c6f516..23ad1b1 100644
--- a/media/module/extractors/ogg/OggExtractor.cpp
+++ b/media/module/extractors/ogg/OggExtractor.cpp
@@ -34,6 +34,9 @@
 #include <system/audio.h>
 #include <utils/String8.h>
 
+#include <inttypes.h>
+#include <stdint.h>
+
 extern "C" {
     #include <Tremolo/codec_internal.h>
 
@@ -346,66 +349,118 @@
         off64_t startOffset, off64_t *pageOffset) {
     *pageOffset = startOffset;
 
-    for (;;) {
-        char signature[4];
-        ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
+    // balance between larger reads and reducing how much we over-read.
+    const int FIND_BUF_SIZE = 2048;
+    const int lenOggS = strlen("OggS");
+    while(1) {
 
-        if (n < 4) {
+        // work with big buffers to amortize readAt() costs
+        char signatureBuffer[FIND_BUF_SIZE];
+        ssize_t n = mSource->readAt(*pageOffset, &signatureBuffer, sizeof(signatureBuffer));
+
+        if (n < lenOggS) {
             *pageOffset = 0;
-
             return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
         }
 
-        if (!memcmp(signature, "OggS", 4)) {
-            if (*pageOffset > startOffset) {
-                ALOGV("skipped %lld bytes of junk to reach next frame",
-                     (long long)(*pageOffset - startOffset));
-            }
-
-            return OK;
-        }
-
-        // see how far ahead to skip; avoid some fruitless comparisons
-        unsigned int i;
-        for (i = 1; i < 4 ; i++) {
-            if (signature[i] == 'O')
+        for(int i = 0; i < n - (lenOggS - 1) ; i++) {
+            // fast scan for 1st character in a signature
+            char *p = (char *)memchr(&signatureBuffer[i], 'O', n - (lenOggS - 1) - i);
+            if (p == NULL) {
+                // no signature start in the rest of this buffer.
                 break;
+            }
+            int jump = (p-&signatureBuffer[i]);
+            i += jump;
+            if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+                *pageOffset += i;
+                if (*pageOffset > startOffset) {
+                    ALOGD("skipped %" PRIu64 " bytes of junk to reach next frame",
+                         (*pageOffset - startOffset));
+                }
+                return OK;
+            }
         }
-        *pageOffset += i;
+
+        // on to next block. buffer didn't end with "OggS", but could end with "Ogg".
+        // overlap enough to detect this. n >= lenOggS, so this always advances.
+        *pageOffset += n - (lenOggS - 1);
     }
+    return (status_t)ERROR_END_OF_STREAM;
 }
 
 // Given the offset of the "current" page, find the page immediately preceding
 // it (if any) and return its granule position.
 // To do this we back up from the "current" page's offset until we find any
 // page preceding it and then scan forward to just before the current page.
+//
 status_t MyOggExtractor::findPrevGranulePosition(
         off64_t pageOffset, uint64_t *granulePos) {
     *granulePos = 0;
 
-    off64_t prevPageOffset = 0;
-    off64_t prevGuess = pageOffset;
-    for (;;) {
-        if (prevGuess >= 5000) {
-            prevGuess -= 5000;
+    const int FIND_BUF_SIZE = 2048;
+    const int lenOggS = strlen("OggS");
+
+    if (pageOffset == 0) {
+        ALOGV("no page before the first page");
+        return UNKNOWN_ERROR;
+    }
+
+    off64_t prevPageOffset = pageOffset;
+
+    // we start our search on the byte immediately in front of pageOffset
+    // which could mean "O" immediately before and "ggS" starting at pageOffset
+    //
+    // if there was an "OggS" at pageOffset, we'll have scanned a few extra bytes
+    // but if pageOffset was chosen by a seek operation, we don't know that it
+    // reflects the beginning of a page. By choosing to scan 3 possibly unneeded
+    // bytes at the start we cover both cases.
+    //
+    off64_t firstAfter = pageOffset + lenOggS - 1;    // NOT within our buffer
+    off64_t nextOffset = pageOffset;
+
+    while(prevPageOffset == pageOffset) {
+        // work with big buffers to amortize readAt() costs
+        char signatureBuffer[FIND_BUF_SIZE];
+
+        ssize_t desired = sizeof(signatureBuffer);
+        if (firstAfter >= desired) {
+            nextOffset = firstAfter - desired;
         } else {
-            prevGuess = 0;
+            nextOffset = 0;
+            desired = firstAfter;
         }
+        ssize_t n = mSource->readAt(nextOffset, &signatureBuffer, desired);
 
-        ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess));
-
-        status_t err = findNextPage(prevGuess, &prevPageOffset);
-        if (err == ERROR_END_OF_STREAM) {
-            // We are at the last page and didn't back off enough;
-            // back off 5000 bytes more and try again.
-            continue;
-        } else if (err != OK) {
-            return err;
-        }
-
-        if (prevPageOffset < pageOffset || prevGuess == 0) {
+        if (n < lenOggS) {
+            ALOGD("short read, get out");
             break;
         }
+
+        // work backwards
+        // loop control ok for n >= 0
+        for(int i = n - lenOggS; i >= 0 ; i--) {
+            // fast scan for 1st character in the signature
+            char *p = (char *)memrchr(&signatureBuffer[0], 'O', i);
+            if (p == NULL) {
+                // no signature start in the rest of this buffer.
+                break;
+            }
+            i = (p-&signatureBuffer[0]);
+            // loop start chosen to ensure we will always have lenOggS bytes
+            if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+                prevPageOffset = nextOffset + i;
+                break;
+            }
+        }
+
+        // back up for next read; make sure we catch overlaps
+        if (nextOffset == 0) {
+            // can't back up any further
+            break;
+        }
+        // current buffer might start with "ggS", include those bytes in the next iteration
+        firstAfter = nextOffset + lenOggS - 1;
     }
 
     if (prevPageOffset == pageOffset) {
@@ -413,8 +468,8 @@
         return UNKNOWN_ERROR;
     }
 
-    ALOGV("prevPageOffset at %lld, pageOffset at %lld",
-            (long long)prevPageOffset, (long long)pageOffset);
+    ALOGV("prevPageOffset at %" PRIu64 ", pageOffset at %" PRIu64,
+          prevPageOffset, pageOffset);
     uint8_t flag = 0;
     for (;;) {
         Page prevPage;
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index e8251e3..1593be0 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -56,6 +56,7 @@
     AttributesVector getAudioAttributes() const;
     product_strategy_t getId() const { return mId; }
     StreamTypeVector getSupportedStreams() const;
+    VolumeGroupAttributesVector getVolumeGroupAttributes() const { return mAttributesVector; }
 
     /**
      * @brief matches checks if the given audio attributes shall follow the strategy.
@@ -63,9 +64,9 @@
      *        If only the usage is available, the check is performed on the usages of the given
      *        attributes, otherwise all fields must match.
      * @param attributes to consider
-     * @return true if attributes matches with the strategy, false otherwise.
+     * @return matching score, negative value if no match.
      */
-    bool matches(const audio_attributes_t attributes) const;
+    int matchesScore(const audio_attributes_t attributes) const;
 
     bool supportStreamType(const audio_stream_type_t &streamType) const;
 
@@ -84,9 +85,6 @@
     DeviceTypeSet getDeviceTypes() const { return mApplicableDevices; }
 
     audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
-    audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
-
-    volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
 
     volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
 
@@ -161,6 +159,9 @@
     void dump(String8 *dst, int spaces = 0) const;
 
 private:
+    VolumeGroupAttributes getVolumeGroupAttributesForAttributes(
+            const audio_attributes_t &attr, bool fallbackOnDefault = true) const;
+
     product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
 };
 
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index c104c97..1d3ad1c 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -62,29 +62,17 @@
     return { AUDIO_ATTRIBUTES_INITIALIZER };
 }
 
-bool ProductStrategy::matches(const audio_attributes_t attr) const
+int ProductStrategy::matchesScore(const audio_attributes_t attr) const
 {
-    return std::find_if(begin(mAttributesVector), end(mAttributesVector),
-                        [&attr](const auto &supportedAttr) {
-        return AudioProductStrategy::attributesMatches(supportedAttr.getAttributes(), attr);
-    }) != end(mAttributesVector);
-}
-
-audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
-        const audio_attributes_t &attr) const
-{
-    const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
-                                   [&attr](const auto &supportedAttr) {
-        return AudioProductStrategy::attributesMatches(supportedAttr.getAttributes(), attr); });
-    if (iter == end(mAttributesVector)) {
-        return AUDIO_STREAM_DEFAULT;
+    int strategyScore = AudioProductStrategy::NO_MATCH;
+    for (const auto &attrGroup : mAttributesVector) {
+        int score = AudioProductStrategy::attributesMatchesScore(attrGroup.getAttributes(), attr);
+        if (score == AudioProductStrategy::MATCH_EQUALS) {
+            return score;
+        }
+        strategyScore = std::max(score, strategyScore);
     }
-    audio_stream_type_t streamType = iter->getStreamType();
-    ALOGW_IF(streamType == AUDIO_STREAM_DEFAULT,
-             "%s: Strategy %s supporting attributes %s has not stream type associated"
-             "fallback on MUSIC. Do not use stream volume API", __func__, mName.c_str(),
-             toString(attr).c_str());
-    return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
+    return strategyScore;
 }
 
 audio_attributes_t ProductStrategy::getAttributesForStreamType(audio_stream_type_t streamType) const
@@ -120,16 +108,6 @@
         return supportedAttr.getStreamType() == streamType; }) != end(mAttributesVector);
 }
 
-volume_group_t ProductStrategy::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
-{
-    for (const auto &supportedAttr : mAttributesVector) {
-        if (AudioProductStrategy::attributesMatches(supportedAttr.getAttributes(), attr)) {
-            return supportedAttr.getGroupId();
-        }
-    }
-    return VOLUME_GROUP_NONE;
-}
-
 volume_group_t ProductStrategy::getVolumeGroupForStreamType(audio_stream_type_t stream) const
 {
     for (const auto &supportedAttr : mAttributesVector) {
@@ -167,16 +145,22 @@
 }
 
 product_strategy_t ProductStrategyMap::getProductStrategyForAttributes(
-        const audio_attributes_t &attr, bool fallbackOnDefault) const
+        const audio_attributes_t &attributes, bool fallbackOnDefault) const
 {
+    product_strategy_t bestStrategyOrdefault = PRODUCT_STRATEGY_NONE;
+    int matchScore = AudioProductStrategy::NO_MATCH;
     for (const auto &iter : *this) {
-        if (iter.second->matches(attr)) {
+        int score = iter.second->matchesScore(attributes);
+        if (score == AudioProductStrategy::MATCH_EQUALS) {
             return iter.second->getId();
         }
+        if (score > matchScore) {
+            bestStrategyOrdefault = iter.second->getId();;
+            matchScore = score;
+        }
     }
-    ALOGV("%s: No matching product strategy for attributes %s, return default", __FUNCTION__,
-          toString(attr).c_str());
-    return fallbackOnDefault? getDefault() : PRODUCT_STRATEGY_NONE;
+    return (matchScore != AudioProductStrategy::MATCH_ON_DEFAULT_SCORE || fallbackOnDefault) ?
+            bestStrategyOrdefault : PRODUCT_STRATEGY_NONE;
 }
 
 audio_attributes_t ProductStrategyMap::getAttributesForStreamType(audio_stream_type_t stream) const
@@ -192,20 +176,6 @@
     return {};
 }
 
-audio_stream_type_t ProductStrategyMap::getStreamTypeForAttributes(
-        const audio_attributes_t &attr) const
-{
-    for (const auto &iter : *this) {
-        audio_stream_type_t stream = iter.second->getStreamTypeForAttributes(attr);
-        if (stream != AUDIO_STREAM_DEFAULT) {
-            return stream;
-        }
-    }
-    ALOGV("%s: No product strategy for attributes %s, using default (aka MUSIC)", __FUNCTION__,
-          toString(attr).c_str());
-    return  AUDIO_STREAM_MUSIC;
-}
-
 product_strategy_t ProductStrategyMap::getDefault() const
 {
     if (mDefaultStrategy != PRODUCT_STRATEGY_NONE) {
@@ -270,16 +240,39 @@
     return at(psId)->getDeviceAddress();
 }
 
+VolumeGroupAttributes ProductStrategyMap::getVolumeGroupAttributesForAttributes(
+        const audio_attributes_t &attr, bool fallbackOnDefault) const
+{
+    int matchScore = AudioProductStrategy::NO_MATCH;
+    VolumeGroupAttributes bestVolumeGroupAttributes = {};
+    for (const auto &iter : *this) {
+        for (const auto &volGroupAttr : iter.second->getVolumeGroupAttributes()) {
+            int score = volGroupAttr.matchesScore(attr);
+            if (score == AudioProductStrategy::MATCH_EQUALS) {
+                return volGroupAttr;
+            }
+            if (score > matchScore) {
+                matchScore = score;
+                bestVolumeGroupAttributes = volGroupAttr;
+            }
+        }
+    }
+    return (matchScore != AudioProductStrategy::MATCH_ON_DEFAULT_SCORE || fallbackOnDefault) ?
+            bestVolumeGroupAttributes : VolumeGroupAttributes();
+}
+
+audio_stream_type_t ProductStrategyMap::getStreamTypeForAttributes(
+        const audio_attributes_t &attr) const
+{
+    audio_stream_type_t streamType = getVolumeGroupAttributesForAttributes(
+            attr, /* fallbackOnDefault= */ true).getStreamType();
+    return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
+}
+
 volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(
         const audio_attributes_t &attr, bool fallbackOnDefault) const
 {
-    for (const auto &iter : *this) {
-        volume_group_t group = iter.second->getVolumeGroupForAttributes(attr);
-        if (group != VOLUME_GROUP_NONE) {
-            return group;
-        }
-    }
-    return fallbackOnDefault ? getDefaultVolumeGroup() : VOLUME_GROUP_NONE;
+    return getVolumeGroupAttributesForAttributes(attr, fallbackOnDefault).getGroupId();
 }
 
 volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index 948cee1..59d1ae4 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -241,6 +241,7 @@
     "format_hardware",
     "channel_count_hardware",
     "sample_rate_hardware",
+    "uid",
 };
 
 static constexpr const char * HeadTrackerDeviceEnabledFields[] {
@@ -1376,6 +1377,8 @@
     mAudioAnalytics.mAnalyticsState->timeMachine().get(
             key, AMEDIAMETRICS_PROP_SAMPLERATEHARDWARE, &sampleRateHardware);
 
+    const auto uid = item->getUid();
+
     LOG(LOG_LEVEL) << "key:" << key
             << " path:" << path
             << " direction:" << direction << "(" << directionStr << ")"
@@ -1398,7 +1401,8 @@
                     << "(" << sharingModeRequestedStr << ")"
             << " format_hardware:" << formatHardware << "(" << formatHardwareStr << ")"
             << " channel_count_hardware:" << channelCountHardware
-            << " sample_rate_hardware: " << sampleRateHardware;
+            << " sample_rate_hardware: " << sampleRateHardware
+            << " uid: " << uid;
 
     if (mAudioAnalytics.mDeliverStatistics) {
         const stats::media_metrics::BytesField bf_serialized(
@@ -1426,6 +1430,7 @@
                 , formatHardware
                 , channelCountHardware
                 , sampleRateHardware
+                , uid
                 );
         std::stringstream ss;
         ss << "result:" << result;
@@ -1452,6 +1457,7 @@
                 , formatHardware
                 , channelCountHardware
                 , sampleRateHardware
+                , uid
                 );
         ss << " " << fieldsStr;
         std::string str = ss.str();