APM: support product strategy routing

  Audio policy engine supports receiving a preferred device to use
for a given strategy (Engine superclass). Use of the preferred
device intervenes at the level of the each engine implementation,
here in the default engine in getDevicesForProductStrategy() method
so it is saved in the routing cache, and respects existing routing
priorities.
  Refactor the loops for call and output rerouting into a new
updateCallAndOutputRouting() method.

Bug: 144440677
Test: atest AudioServiceHostTest#testPreferredDeviceRouting

Change-Id: Ic4c690e1b0d8020c4335979e40e14e6df5887879
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 2a5cd49..3aa3db5 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -611,7 +611,7 @@
 void Engine::updateDeviceSelectionCache()
 {
     for (const auto &iter : getProductStrategies()) {
-        const auto &strategy = iter.second;
+        const auto& strategy = iter.second;
         auto devices = getDevicesForProductStrategy(strategy->getId());
         mDevicesForStrategies[strategy->getId()] = devices;
         strategy->setDeviceTypes(devices.types());
@@ -619,14 +619,30 @@
     }
 }
 
-DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const
-{
+DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
     DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
-    DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
-    const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
 
+    // check if this strategy has a preferred device that is available,
+    // if yes, give priority to it
+    AudioDeviceTypeAddr preferredStrategyDevice;
+    const status_t status = getPreferredDeviceForStrategy(strategy, preferredStrategyDevice);
+    if (status == NO_ERROR) {
+        // there is a preferred device, is it available?
+        sp<DeviceDescriptor> preferredAvailableDevDescr = availableOutputDevices.getDevice(
+                preferredStrategyDevice.mType,
+                String8(preferredStrategyDevice.mAddress.c_str()),
+                AUDIO_FORMAT_DEFAULT);
+        if (preferredAvailableDevDescr != nullptr) {
+            ALOGVV("%s using pref device 0x%08x/%s for strategy %u", __FUNCTION__,
+                   preferredStrategyDevice.mType, preferredStrategyDevice.mAddress, strategy);
+            return DeviceVector(preferredAvailableDevDescr);
+        }
+    }
+
+    DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
+    const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
     auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
-                mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+                          mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
     return getDevicesForStrategyInt(legacyStrategy,
                                     availableOutputDevices,
                                     availableInputDevices, outputs);