AudioMixer: Enable 5.1 based for fallback downmix

Test: oboetester
Test: atest downmix_tests
Bug: 230414312
Bug: 238397904
Change-Id: Ie093319c5fefc459165ae3d6c57b7836e8b625e5
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 6a39108..57b860d 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -193,7 +193,7 @@
 
     // See if we should use our built-in non-effect downmixer.
     if (mMixerInFormat == AUDIO_FORMAT_PCM_FLOAT
-            && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO
+            && ChannelMixBufferProvider::isOutputChannelMaskSupported(mMixerChannelMask)
             && audio_channel_mask_get_representation(channelMask)
                     == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
         mDownmixerBufferProvider.reset(new ChannelMixBufferProvider(channelMask,
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index a9944fb..9f19f7b 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -373,18 +373,23 @@
                 audio_bytes_per_sample(format)
                     * audio_channel_count_from_out_mask(outputChannelMask),
                 bufferFrameCount)
+        , mChannelMix{format == AUDIO_FORMAT_PCM_FLOAT
+                ? audio_utils::channels::IChannelMix::create(outputChannelMask) : nullptr}
+        , mIsValid{mChannelMix && mChannelMix->setInputChannelMask(inputChannelMask)}
 {
     ALOGV("ChannelMixBufferProvider(%p)(%#x, %#x, %#x)",
             this, format, inputChannelMask, outputChannelMask);
-    if (outputChannelMask == AUDIO_CHANNEL_OUT_STEREO && format == AUDIO_FORMAT_PCM_FLOAT) {
-        mIsValid = mChannelMix.setInputChannelMask(inputChannelMask);
-    }
 }
 
 void ChannelMixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
 {
-    mChannelMix.process(static_cast<const float *>(src), static_cast<float *>(dst),
-            frames, false /* accumulate */);
+    if (mIsValid) {
+        mChannelMix->process(static_cast<const float *>(src), static_cast<float *>(dst),
+                frames, false /* accumulate */);
+    } else {
+        // Should fall back to a different BufferProvider if not valid.
+        ALOGE("%s: Use without being valid!", __func__);
+    }
 }
 
 ReformatBufferProvider::ReformatBufferProvider(int32_t channelCount,
diff --git a/media/libaudioprocessing/include/media/BufferProviders.h b/media/libaudioprocessing/include/media/BufferProviders.h
index a0b025f..8d18010 100644
--- a/media/libaudioprocessing/include/media/BufferProviders.h
+++ b/media/libaudioprocessing/include/media/BufferProviders.h
@@ -142,9 +142,14 @@
 
     bool isValid() const { return mIsValid; }
 
+    static bool isOutputChannelMaskSupported(audio_channel_mask_t outputChannelMask) {
+        return audio_utils::channels::IChannelMix::isOutputChannelMaskSupported(
+                outputChannelMask);
+    }
+
 protected:
-    audio_utils::channels::ChannelMix<AUDIO_CHANNEL_OUT_STEREO> mChannelMix;
-    bool mIsValid = false;
+    const std::shared_ptr<audio_utils::channels::IChannelMix> mChannelMix;
+    const bool mIsValid;
 };
 
 // RemixBufferProvider derives from CopyBufferProvider to perform an
diff --git a/media/libeffects/downmix/EffectDownmix.cpp b/media/libeffects/downmix/EffectDownmix.cpp
index 7f8455a..b921537 100644
--- a/media/libeffects/downmix/EffectDownmix.cpp
+++ b/media/libeffects/downmix/EffectDownmix.cpp
@@ -259,7 +259,7 @@
     ret = Downmix_Init(module);
     if (ret < 0) {
         ALOGW("DownmixLib_Create() init failed");
-        free(module);
+        delete module;
         return ret;
     }
 
@@ -582,7 +582,7 @@
     ALOGV("Downmix_Init module %p", pDwmModule);
     int ret = 0;
 
-    memset(&pDwmModule->context, 0, sizeof(downmix_object_t));
+    pDwmModule->context = downmix_object_t{};  // zero initialize (contains class with vtable).
 
     pDwmModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
     pDwmModule->config.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;