AudioMixer: Expand mono track to multi-channel

Extend MONO_HACK to multi-channel output.

Mono track will have only one channel output on multi-channel devices.
Since ARC++ exposed a 4-channel output device and downmix track in
ChromeOS, we need to add this feature to support mono track sample
expansion.

Add support for both re-sample and non-resample path.
For resample path, we need to add MIXTYPE_STEREOEXPAND in
AudioMixerOps.h since AudioResampler will upmix mono track to stereo
track.

Bug: 120222604
Bug: 112341269
Bug: 117116052
Bug: crbug.com/890560
Test: Play mono tracks without re-sampling on ARC++
Test: Play mono tracks with re-sampling on ARC++
Test: Play normal stereo tracks on ARC++
(cherry picked from commit 9b79e0752e6536c31430aa31838a9de1b7b56f9f)

Change-Id: I51f5914c41dd0196db9c6a2e1a99b44e5d87c0d6
diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp
index a169db9..64f91fe 100644
--- a/media/libaudioprocessing/AudioMixerBase.cpp
+++ b/media/libaudioprocessing/AudioMixerBase.cpp
@@ -643,8 +643,14 @@
             if (n & NEEDS_RESAMPLE) {
                 all16BitsStereoNoResample = false;
                 resampling = true;
-                if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2
-                    && t->useStereoVolume()) {
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1
+                        && t->channelMask == AUDIO_CHANNEL_OUT_MONO // MONO_HACK
+                        && isAudioChannelPositionMask(t->mMixerChannelMask)) {
+                    t->hook = TrackBase::getTrackHook(
+                            TRACKTYPE_RESAMPLEMONO, t->mMixerChannelCount,
+                            t->mMixerInFormat, t->mMixerFormat);
+                } else if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2
+                        && t->useStereoVolume()) {
                     t->hook = TrackBase::getTrackHook(
                             TRACKTYPE_RESAMPLESTEREO, t->mMixerChannelCount,
                             t->mMixerInFormat, t->mMixerFormat);
@@ -658,7 +664,7 @@
             } else {
                 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
                     t->hook = TrackBase::getTrackHook(
-                            (t->mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO  // TODO: MONO_HACK
+                            (isAudioChannelPositionMask(t->mMixerChannelMask)  // TODO: MONO_HACK
                                     && t->channelMask == AUDIO_CHANNEL_OUT_MONO)
                                 ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE,
                             t->mMixerChannelCount,
@@ -1494,7 +1500,8 @@
     ALOGVV("track__Resample\n");
     mResampler->setSampleRate(sampleRate);
     const bool ramp = needsRamp();
-    if (ramp || aux != NULL) {
+    if (MIXTYPE == MIXTYPE_MONOEXPAND || MIXTYPE == MIXTYPE_STEREOEXPAND
+            || ramp || aux != NULL) {
         // if ramp:        resample with unity gain to temp buffer and scale/mix in 2nd step.
         // if aux != NULL: resample with unity gain to temp buffer then apply send level.
 
@@ -1629,6 +1636,23 @@
             break;
         }
         break;
+    // RESAMPLEMONO needs MIXTYPE_STEREOEXPAND since resampler will upmix mono
+    // track to stereo track
+    case TRACKTYPE_RESAMPLEMONO:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_STEREOEXPAND, float /*TO*/, float /*TI*/,
+                    TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_STEREOEXPAND, int32_t /*TO*/, int16_t /*TI*/,
+                    TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
     case TRACKTYPE_NORESAMPLEMONO:
         switch (mixerInFormat) {
         case AUDIO_FORMAT_PCM_FLOAT: