APM: fix log spam from getDevicesForStrategyInt when booting devices.

1. Add initialization function for device selection cache in engine
   and call the initialization function before audio module creation.
   There is no device available before the audio module is available. In
   that case, there is no need to call getDevicesForStrategyInt to
   update the device selection cache.
2. Add speaker as the last selection for STRATEGY_PHONE so that there
   can still be something picked if there is no external device
   connected and no earpiece on the Android device.

Bug: 276781745
Test: make, boot device, check log
Change-Id: If976830dbb6cce192f8b15cd2937ff9824534cc7
Merged-In: If976830dbb6cce192f8b15cd2937ff9824534cc7
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 7d21ae0..de501ee 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -162,6 +162,10 @@
 
     DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const override;
 
+    void initializeDeviceSelectionCache() override;
+
+    void updateDeviceSelectionCache() override;
+
 private:
     /**
      * Get media devices as the given role
@@ -190,6 +194,28 @@
 
     /** current forced use configuration. */
     audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT] = {};
+
+protected:
+    /**
+     * Set the device information for a given strategy.
+     *
+     * @param strategy the strategy to set devices information
+     * @param devices the devices selected for the strategy
+     */
+    virtual void setStrategyDevices(const sp<ProductStrategy>& /*strategy*/,
+                                    const DeviceVector& /*devices*/) {
+        // In EngineBase, do nothing. It is up to the actual engine to decide if it is needed to
+        // set devices information for the given strategy.
+    }
+
+    /**
+     * Get devices that will be used for the given product strategy.
+     *
+     * @param strategy the strategy to query
+     */
+    virtual DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const = 0;
+
+    DeviceStrategyMap mDevicesForStrategies;
 };
 
 } // namespace audio_policy
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 99507ee..83a8e4d 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -627,6 +627,26 @@
     return activeDevices;
 }
 
+void EngineBase::initializeDeviceSelectionCache() {
+    // Initializing the device selection cache with default device won't be harmful, it will be
+    // updated after the audio modules are initialized.
+    auto defaultDevices = DeviceVector(getApmObserver()->getDefaultOutputDevice());
+    for (const auto &iter : getProductStrategies()) {
+        const auto &strategy = iter.second;
+        mDevicesForStrategies[strategy->getId()] = defaultDevices;
+        setStrategyDevices(strategy, defaultDevices);
+    }
+}
+
+void EngineBase::updateDeviceSelectionCache() {
+    for (const auto &iter : getProductStrategies()) {
+        const auto& strategy = iter.second;
+        auto devices = getDevicesForProductStrategy(strategy->getId());
+        mDevicesForStrategies[strategy->getId()] = devices;
+        setStrategyDevices(strategy, devices);
+    }
+}
+
 void EngineBase::dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const
 {
     dst->appendFormat("\n%*sDevice role per capture preset dump:", spaces, "");
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index 518f86e..57174c7 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -421,6 +421,16 @@
      */
     virtual DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const = 0;
 
+    /**
+     * @brief initializeDeviceSelectionCache. Device selection for AudioAttribute / Streams is
+     * cached in the engine in order to speed up process when the audio system is stable. When the
+     * audio system is initializing, not all audio devices information will be available. In that
+     * case, calling this function can allow the engine to initialize the device selection cache
+     * with default values.
+     * This must only be called when audio policy manager is initializing.
+     */
+    virtual void initializeDeviceSelectionCache() = 0;
+
     virtual void dump(String8 *dst) const = 0;
 
 protected:
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 2831a9b..a802646 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -354,14 +354,6 @@
     return availableInputDevices.getDevice(deviceType, String8(address.c_str()), AUDIO_FORMAT_DEFAULT);
 }
 
-void Engine::updateDeviceSelectionCache()
-{
-    for (const auto &iter : getProductStrategies()) {
-        const auto &strategy = iter.second;
-        mDevicesForStrategies[strategy->getId()] = getDevicesForProductStrategy(strategy->getId());
-    }
-}
-
 void Engine::setDeviceAddressForProductStrategy(product_strategy_t strategy,
                                                 const std::string &address)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4b559f0..001dde9 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -66,8 +66,6 @@
                                                      sp<AudioPolicyMix> *mix = nullptr)
                                                      const override;
 
-    void updateDeviceSelectionCache() override;
-
     ///
     /// from AudioPolicyPluginInterface
     ///
@@ -122,15 +120,17 @@
 
     status_t loadAudioPolicyEngineConfig();
 
-    DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
     DeviceVector getCachedDevices(product_strategy_t ps) const;
 
+    ///
+    /// from EngineBase
+    ///
+    DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
+
     /**
      * Policy Parameter Manager hidden through a wrapper.
      */
     ParameterManagerWrapper *mPolicyParameterMgr;
-
-    DeviceStrategyMap mDevicesForStrategies;
 };
 
 } // namespace audio_policy
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 45c5eac..e72249f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -279,7 +279,8 @@
                         getLastRemovableMediaDevices(GROUP_NONE, {AUDIO_DEVICE_OUT_BLE_HEADSET}));
         if (!devices.isEmpty()) break;
         devices = availableOutputDevices.getFirstDevicesFromTypes({
-                AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE});
+                AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE,
+                AUDIO_DEVICE_OUT_SPEAKER});
     } break;
 
     case STRATEGY_SONIFICATION:
@@ -641,15 +642,9 @@
     return device;
 }
 
-void Engine::updateDeviceSelectionCache()
-{
-    for (const auto &iter : getProductStrategies()) {
-        const auto& strategy = iter.second;
-        auto devices = getDevicesForProductStrategy(strategy->getId());
-        mDevicesForStrategies[strategy->getId()] = devices;
-        strategy->setDeviceTypes(devices.types());
-        strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
-    }
+void Engine::setStrategyDevices(const sp<ProductStrategy>& strategy, const DeviceVector &devices) {
+    strategy->setDeviceTypes(devices.types());
+    strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
 }
 
 product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 595e289..be9f4cc 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -67,7 +67,10 @@
                                                      sp<AudioPolicyMix> *mix = nullptr)
                                                      const override;
 
-    void updateDeviceSelectionCache() override;
+    void setStrategyDevices(const sp<ProductStrategy>& strategy,
+                            const DeviceVector& devices) override;
+
+    DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
 
 private:
     /* Copy facilities are put private to disable copy. */
@@ -87,8 +90,6 @@
                                           DeviceVector availableOutputDevices,
                                           const SwAudioOutputCollection &outputs) const;
 
-    DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
-
     sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
 
     product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
@@ -97,8 +98,6 @@
     DeviceVector getPreferredAvailableDevicesForProductStrategy(
         const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
 
-    DeviceStrategyMap mDevicesForStrategies;
-
     std::map<product_strategy_t, legacy_strategy> mLegacyStrategyMap;
 };
 } // namespace audio_policy
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f7a3273..7b6b0fe 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5674,7 +5674,9 @@
         }
     }
 
-    mEngine->updateDeviceSelectionCache();
+    // The actual device selection cache will be updated when calling `updateDevicesAndOutputs`
+    // at the end of this function.
+    mEngine->initializeDeviceSelectionCache();
     mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
         mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));