audio policy service: Add introspection API to retrieve AudioProductStrategies

This CL adds required introspection APIs to deal with product strategies:

-getter of the collection of product strategies
-helper function to return the strategy associated to a given attributes.
This API is mandatory to avoid duplicating the logic that compiles the strategy
for a given Audio Attributes structure.

Test: make

Change-Id: I0e107570a44227bb52a4f359954c93215d4f8bae
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 243020d..5476497 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -53,7 +53,7 @@
     libcutils \
     libutils \
     liblog \
-    libaudioclient \
+    libaudiopolicy \
     libsoundtrigger
 
 ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index cf2ce99..d7030f9 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -240,6 +240,10 @@
                 std::vector<audio_format_t> *formats) = 0;
 
     virtual void     setAppState(uid_t uid, app_state_t state);
+
+    virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
+
+    virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa) = 0;
 };
 
 
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 04f1eb2..b90a08d 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -163,9 +163,3 @@
     }
     return format1 == format2;
 }
-
-constexpr bool operator==(const audio_attributes_t &lhs, const audio_attributes_t &rhs)
-{
-    return lhs.usage == rhs.usage && lhs.content_type == rhs.content_type &&
-            lhs.flags == rhs.flags && (std::strcmp(lhs.tags, rhs.tags) == 0);
-}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 32898b1..5c33fb3 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -65,6 +65,8 @@
 
     StrategyVector getOrderedProductStrategies() const override;
 
+    status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) const override;
+
     void dump(String8 *dst) const override;
 
 
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 66ae86e..72505b2 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -49,6 +49,8 @@
 
     void addAttributes(const AudioAttributes &audioAttributes);
 
+    std::vector<android::AudioAttributes> listAudioAttributes() const;
+
     std::string getName() const { return mName; }
     AttributesVector getAudioAttributes() const;
     product_strategy_t getId() const { return mId; }
@@ -87,20 +89,6 @@
 
     void dump(String8 *dst, int spaces = 0) const;
 
-    /**
-     * @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
-     * 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
-     * is used to identify the default strategy.
-     * @param refAttributes to be considered
-     * @param clientAttritubes to be considered
-     * @return true if matching, false otherwise
-     */
-    static bool attributesMatches(const audio_attributes_t refAttributes,
-                                  const audio_attributes_t clientAttritubes);
 private:
     std::string mName;
 
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 0f4d5a5..755f2a8 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -162,6 +162,17 @@
                 mProductStrategies.at(ps)->getAudioAttributes() : AttributesVector();
 }
 
+status_t EngineBase::listAudioProductStrategies(AudioProductStrategyVector &strategies) const
+{
+    for (const auto &iter : mProductStrategies) {
+        const auto &productStrategy = iter.second;
+        strategies.push_back(
+        {productStrategy->getName(), productStrategy->listAudioAttributes(),
+         productStrategy->getId()});
+    }
+    return NO_ERROR;
+}
+
 void EngineBase::dump(String8 *dst) const
 {
     mProductStrategies.dump(dst, 2);
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index a3edb39..71607d1 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -40,6 +40,15 @@
     mAttributesVector.push_back(audioAttributes);
 }
 
+std::vector<android::AudioAttributes> ProductStrategy::listAudioAttributes() const
+{
+    std::vector<android::AudioAttributes> androidAa;
+    for (const auto &attr : mAttributesVector) {
+        androidAa.push_back({attr.mGroupId, attr.mStream, attr.mAttributes});
+    }
+    return androidAa;
+}
+
 AttributesVector ProductStrategy::getAudioAttributes() const
 {
     AttributesVector attrVector;
@@ -52,42 +61,19 @@
     return { AUDIO_ATTRIBUTES_INITIALIZER };
 }
 
-// @todo: all flags required to match?
-//        all tags required to match?
-/* static */
-bool ProductStrategy::attributesMatches(const audio_attributes_t refAttributes,
-                                        const audio_attributes_t clientAttritubes)
-{
-    if (refAttributes == defaultAttr) {
-        // 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
-        // selects the default.
-        return false;
-    }
-    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_OUTPUT_FLAG_NONE) ||
-             (clientAttritubes.flags != AUDIO_OUTPUT_FLAG_NONE &&
-            (clientAttritubes.flags & refAttributes.flags) == clientAttritubes.flags)) &&
-            ((strlen(refAttributes.tags) == 0) ||
-             (std::strcmp(clientAttritubes.tags, refAttributes.tags) == 0));
-}
-
 bool ProductStrategy::matches(const audio_attributes_t attr) const
 {
     return std::find_if(begin(mAttributesVector), end(mAttributesVector),
                         [&attr](const auto &supportedAttr) {
-        return attributesMatches(supportedAttr.mAttributes, attr); }) != end(mAttributesVector);
+        return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, 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 attributesMatches(supportedAttr.mAttributes, attr); });
+        return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr); });
     return iter != end(mAttributesVector) ? iter->mStream : AUDIO_STREAM_DEFAULT;
 }
 
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
index 9f5fb0c2..18ba2c8 100644
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
@@ -18,7 +18,7 @@
 
 #include <AudioPolicyManagerObserver.h>
 #include <RoutingStrategy.h>
-#include <media/AudioCommonTypes.h>
+#include <media/AudioProductStrategy.h>
 #include <policy.h>
 #include <Volume.h>
 #include <HwModule.h>
@@ -270,6 +270,16 @@
      */
     virtual void updateDeviceSelectionCache() = 0;
 
+    /**
+     * @brief listAudioProductStrategies. Introspection API to retrieve a collection of
+     * AudioProductStrategyVector that allows to build AudioAttributes according to a
+     * product_strategy which is just an index. It has also a human readable name to help the
+     * Car/Oem/AudioManager identiying the use case.
+     * @param strategies collection.
+     * @return OK if the list has been retrieved, error code otherwise
+     */
+    virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) const = 0;
+
     virtual void dump(String8 *dst) const = 0;
 
 protected:
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index df813cb..13d874a 100644
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -57,6 +57,7 @@
     libaudioutils \
     libparameter \
     libmedia_helper \
+    libaudiopolicy \
     libxml2
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index f9212f9..95eac1c 100644
--- a/services/audiopolicy/enginedefault/Android.mk
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -44,7 +44,8 @@
     libcutils \
     libutils \
     libmedia_helper \
-    libaudiopolicyengineconfig
+    libaudiopolicyengineconfig \
+    libaudiopolicy
 
 LOCAL_HEADER_LIBRARIES := \
     libaudiopolicycommon \
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 80e92de..5672c07 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -80,7 +80,6 @@
 
     void updateDeviceSelectionCache() override;
 
-
 private:
     /* Copy facilities are put private to disable copy. */
     Engine(const Engine &object);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index de6d489..e715fd4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -251,6 +251,16 @@
 
         virtual bool isHapticPlaybackSupported();
 
+        virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies)
+        {
+            return mEngine->listAudioProductStrategies(strategies);
+        }
+
+        virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa)
+        {
+            return mEngine->getProductStrategyForAttributes(aa.getAttributes());
+        }
+
 protected:
         // A constructor that allows more fine-grained control over initialization process,
         // used in automatic tests.
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 45fb174..d9fbdaa 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1186,4 +1186,22 @@
     return mAudioPolicyManager->isHapticPlaybackSupported();
 }
 
+status_t AudioPolicyService::listAudioProductStrategies(AudioProductStrategyVector &strategies)
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mAudioPolicyManager->listAudioProductStrategies(strategies);
+}
+
+product_strategy_t AudioPolicyService::getProductStrategyFromAudioAttributes(
+        const AudioAttributes &aa)
+{
+    if (mAudioPolicyManager == NULL) {
+        return PRODUCT_STRATEGY_NONE;
+    }
+    Mutex::Autolock _l(mLock);
+    return mAudioPolicyManager->getProductStrategyFromAudioAttributes(aa);
+}
 } // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c073b7c..ee293a7 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -229,6 +229,9 @@
 
     virtual bool     isHapticPlaybackSupported();
 
+    virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
+    virtual product_strategy_t getProductStrategyFromAudioAttributes(const AudioAttributes &aa);
+
             status_t doStopOutput(audio_port_handle_t portId);
             void doReleaseOutput(audio_port_handle_t portId);