Use channel mask instead of channel count for track creation

Record and playback objects (resp AudioRecord and AudioTrack)
are created using a channel mask, but this information is lost
in the mixer because only the channel count is known to
AudioFlinger. A channel count can always be derived from a
channel mask.

The change consists in:
- disambiguiting variable names for channel masks and counts
- passing the mask information from the client to AudioFlinger
 and the mixer.
- when using the DIRECT ouput, only verifying the format of
 the track is compatible with the output's for PCM.

Change-Id: I50d87bfb7d7afcabdf5f12d4ab75ef3a54132c0e
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index baab2e8..605680a 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -130,7 +130,7 @@
      * sampleRate:         Track sampling rate in Hz.
      * format:             Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
      *                     16 bits per sample).
-     * channels:           Channel mask: see audio_channels_t.
+     * channelMask:        Channel mask: see audio_channels_t.
      * frameCount:         Total size of track PCM buffer in frames. This defines the
      *                     latency of the track.
      * flags:              A bitmask of acoustic values from enum record_flags.  It enables
@@ -151,7 +151,7 @@
                         AudioRecord(int inputSource,
                                     uint32_t sampleRate = 0,
                                     int format          = 0,
-                                    uint32_t channels = AUDIO_CHANNEL_IN_MONO,
+                                    uint32_t channelMask = AUDIO_CHANNEL_IN_MONO,
                                     int frameCount      = 0,
                                     uint32_t flags      = 0,
                                     callback_t cbf = 0,
@@ -177,7 +177,7 @@
             status_t    set(int inputSource     = 0,
                             uint32_t sampleRate = 0,
                             int format          = 0,
-                            uint32_t channels = AUDIO_CHANNEL_IN_MONO,
+                            uint32_t channelMask = AUDIO_CHANNEL_IN_MONO,
                             int frameCount      = 0,
                             uint32_t flags      = 0,
                             callback_t cbf = 0,
@@ -348,8 +348,8 @@
 
             bool processAudioBuffer(const sp<ClientRecordThread>& thread);
             status_t openRecord_l(uint32_t sampleRate,
-                                int format,
-                                int channelCount,
+                                uint32_t format,
+                                uint32_t channelMask,
                                 int frameCount,
                                 uint32_t flags,
                                 audio_io_handle_t input);
@@ -364,10 +364,10 @@
     uint32_t                mFrameCount;
 
     audio_track_cblk_t*     mCblk;
-    uint8_t                 mFormat;
+    uint32_t                mFormat;
     uint8_t                 mChannelCount;
     uint8_t                 mInputSource;
-    uint8_t                 mReserved;
+    uint8_t                 mReserved[2];
     status_t                mStatus;
     uint32_t                mLatency;
 
@@ -382,7 +382,7 @@
     uint32_t                mNewPosition;
     uint32_t                mUpdatePeriod;
     uint32_t                mFlags;
-    uint32_t                mChannels;
+    uint32_t                mChannelMask;
     audio_io_handle_t       mInput;
     int                     mSessionId;
 };
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index de928da..df30e8c 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -69,8 +69,8 @@
             MUTE    = 0x00000001
         };
         uint32_t    flags;
-        int         channelCount;
         int         format;
+        int         channelCount; // will be removed in the future, do not use
         size_t      frameCount;
         size_t      size;
         union {
@@ -129,7 +129,7 @@
      * sampleRate:         Track sampling rate in Hz.
      * format:             Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
      *                     16 bits per sample).
-     * channels:           Channel mask: see audio_channels_t.
+     * channelMask:        Channel mask: see audio_channels_t.
      * frameCount:         Total size of track PCM buffer in frames. This defines the
      *                     latency of the track.
      * flags:              Reserved for future use.
@@ -143,7 +143,7 @@
                         AudioTrack( int streamType,
                                     uint32_t sampleRate  = 0,
                                     int format           = 0,
-                                    int channels         = 0,
+                                    int channelMask      = 0,
                                     int frameCount       = 0,
                                     uint32_t flags       = 0,
                                     callback_t cbf       = 0,
@@ -163,7 +163,7 @@
                         AudioTrack( int streamType,
                                     uint32_t sampleRate = 0,
                                     int format          = 0,
-                                    int channels        = 0,
+                                    int channelMask     = 0,
                                     const sp<IMemory>& sharedBuffer = 0,
                                     uint32_t flags      = 0,
                                     callback_t cbf      = 0,
@@ -187,7 +187,7 @@
             status_t    set(int streamType      =-1,
                             uint32_t sampleRate = 0,
                             int format          = 0,
-                            int channels        = 0,
+                            int channelMask     = 0,
                             int frameCount      = 0,
                             uint32_t flags      = 0,
                             callback_t cbf      = 0,
@@ -438,8 +438,8 @@
             bool processAudioBuffer(const sp<AudioTrackThread>& thread);
             status_t createTrack_l(int streamType,
                                  uint32_t sampleRate,
-                                 int format,
-                                 int channelCount,
+                                 uint32_t format,
+                                 uint32_t channelMask,
                                  int frameCount,
                                  uint32_t flags,
                                  const sp<IMemory>& sharedBuffer,
@@ -459,11 +459,12 @@
     uint32_t                mFrameCount;
 
     audio_track_cblk_t*     mCblk;
+    uint32_t                mFormat;
     uint8_t                 mStreamType;
-    uint8_t                 mFormat;
     uint8_t                 mChannelCount;
     uint8_t                 mMuted;
-    uint32_t                mChannels;
+    uint8_t                 mReserved;
+    uint32_t                mChannelMask;
     status_t                mStatus;
     uint32_t                mLatency;
 
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index d8fdc27..4037c46 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -48,8 +48,8 @@
                                 pid_t pid,
                                 int streamType,
                                 uint32_t sampleRate,
-                                int format,
-                                int channelCount,
+                                uint32_t format,
+                                uint32_t channelMask,
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
@@ -61,8 +61,8 @@
                                 pid_t pid,
                                 int input,
                                 uint32_t sampleRate,
-                                int format,
-                                int channelCount,
+                                uint32_t format,
+                                uint32_t channelMask,
                                 int frameCount,
                                 uint32_t flags,
                                 int *sessionId,
@@ -73,7 +73,7 @@
      */
     virtual     uint32_t    sampleRate(int output) const = 0;
     virtual     int         channelCount(int output) const = 0;
-    virtual     int         format(int output) const = 0;
+    virtual     uint32_t    format(int output) const = 0;
     virtual     size_t      frameCount(int output) const = 0;
     virtual     uint32_t    latency(int output) const = 0;
 
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 1827c3e..072329d 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -82,7 +82,7 @@
                 // 16 bit because data is converted to 16 bit before being stored in buffer
 
                 uint8_t     frameSize;
-                uint8_t     channelCount;
+                uint8_t     pad1;
                 uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
 
                 uint16_t    waitTimeMs;      // Cumulated wait time
@@ -90,6 +90,7 @@
     volatile    int32_t     flags;
 
                 // Cache line boundary (32 bytes)
+
                             audio_track_cblk_t();
                 uint32_t    stepUser(uint32_t frameCount);
                 bool        stepServer(uint32_t frameCount);
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 446e3df..f6c4cc7 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -88,7 +88,7 @@
         int inputSource,
         uint32_t sampleRate,
         int format,
-        uint32_t channels,
+        uint32_t channelMask,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -97,7 +97,7 @@
         int sessionId)
     : mStatus(NO_INIT), mSessionId(0)
 {
-    mStatus = set(inputSource, sampleRate, format, channels,
+    mStatus = set(inputSource, sampleRate, format, channelMask,
             frameCount, flags, cbf, user, notificationFrames, sessionId);
 }
 
@@ -121,7 +121,7 @@
         int inputSource,
         uint32_t sampleRate,
         int format,
-        uint32_t channels,
+        uint32_t channelMask,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -131,7 +131,7 @@
         int sessionId)
 {
 
-    LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount);
+    LOGV("set(): sampleRate %d, channelMask %d, frameCount %d",sampleRate, channelMask, frameCount);
 
     AutoMutex lock(mLock);
 
@@ -156,14 +156,14 @@
         return BAD_VALUE;
     }
 
-    if (!audio_is_input_channel(channels)) {
+    if (!audio_is_input_channel(channelMask)) {
         return BAD_VALUE;
     }
 
-    int channelCount = popcount(channels);
+    int channelCount = popcount(channelMask);
 
     audio_io_handle_t input = AudioSystem::getInput(inputSource,
-                                    sampleRate, format, channels, (audio_in_acoustics_t)flags);
+                                    sampleRate, format, channelMask, (audio_in_acoustics_t)flags);
     if (input == 0) {
         LOGE("Could not get audio input for record source %d", inputSource);
         return BAD_VALUE;
@@ -190,7 +190,7 @@
     mSessionId = sessionId;
 
     // create the IAudioRecord
-    status = openRecord_l(sampleRate, format, channelCount,
+    status = openRecord_l(sampleRate, format, channelMask,
                         frameCount, flags, input);
     if (status != NO_ERROR) {
         return status;
@@ -209,7 +209,7 @@
     // Update buffer size in case it has been limited by AudioFlinger during track creation
     mFrameCount = mCblk->frameCount;
     mChannelCount = (uint8_t)channelCount;
-    mChannels = channels;
+    mChannelMask = channelMask;
     mActive = 0;
     mCbf = cbf;
     mNotificationFrames = notificationFrames;
@@ -437,8 +437,8 @@
 // must be called with mLock held
 status_t AudioRecord::openRecord_l(
         uint32_t sampleRate,
-        int format,
-        int channelCount,
+        uint32_t format,
+        uint32_t channelMask,
         int frameCount,
         uint32_t flags,
         audio_io_handle_t input)
@@ -451,7 +451,7 @@
 
     sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
                                                        sampleRate, format,
-                                                       channelCount,
+                                                       channelMask,
                                                        frameCount,
                                                        ((uint16_t)flags) << 16,
                                                        &mSessionId,
@@ -589,7 +589,7 @@
 {
     mInput = AudioSystem::getInput(mInputSource,
                                 mCblk->sampleRate,
-                                mFormat, mChannels,
+                                mFormat, mChannelMask,
                                 (audio_in_acoustics_t)mFlags);
     return mInput;
 }
@@ -756,7 +756,7 @@
         // if the new IAudioRecord is created, openRecord_l() will modify the
         // following member variables: mAudioRecord, mCblkMemory and mCblk.
         // It will also delete the strong references on previous IAudioRecord and IMemory
-        result = openRecord_l(cblk->sampleRate, mFormat, mChannelCount,
+        result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
                 mFrameCount, mFlags, getInput_l());
         if (result == NO_ERROR) {
             result = mAudioRecord->start();
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7520ed9..ea44f87 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -87,7 +87,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channels,
+        int channelMask,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -96,7 +96,7 @@
         int sessionId)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channels,
+    mStatus = set(streamType, sampleRate, format, channelMask,
             frameCount, flags, cbf, user, notificationFrames,
             0, false, sessionId);
 }
@@ -105,7 +105,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channels,
+        int channelMask,
         const sp<IMemory>& sharedBuffer,
         uint32_t flags,
         callback_t cbf,
@@ -114,7 +114,7 @@
         int sessionId)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channels,
+    mStatus = set(streamType, sampleRate, format, channelMask,
             0, flags, cbf, user, notificationFrames,
             sharedBuffer, false, sessionId);
 }
@@ -141,7 +141,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channels,
+        int channelMask,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -180,8 +180,8 @@
     if (format == 0) {
         format = AUDIO_FORMAT_PCM_16_BIT;
     }
-    if (channels == 0) {
-        channels = AUDIO_CHANNEL_OUT_STEREO;
+    if (channelMask == 0) {
+        channelMask = AUDIO_CHANNEL_OUT_STEREO;
     }
 
     // validate parameters
@@ -195,15 +195,15 @@
         flags |= AUDIO_POLICY_OUTPUT_FLAG_DIRECT;
     }
 
-    if (!audio_is_output_channel(channels)) {
+    if (!audio_is_output_channel(channelMask)) {
         LOGE("Invalid channel mask");
         return BAD_VALUE;
     }
-    uint32_t channelCount = popcount(channels);
+    uint32_t channelCount = popcount(channelMask);
 
     audio_io_handle_t output = AudioSystem::getOutput(
                                     (audio_stream_type_t)streamType,
-                                    sampleRate,format, channels,
+                                    sampleRate,format, channelMask,
                                     (audio_policy_output_flags_t)flags);
 
     if (output == 0) {
@@ -222,8 +222,8 @@
     // create the IAudioTrack
     status_t status = createTrack_l(streamType,
                                   sampleRate,
-                                  format,
-                                  channelCount,
+                                  (uint32_t)format,
+                                  (uint32_t)channelMask,
                                   frameCount,
                                   flags,
                                   sharedBuffer,
@@ -245,8 +245,8 @@
     mStatus = NO_ERROR;
 
     mStreamType = streamType;
-    mFormat = format;
-    mChannels = channels;
+    mFormat = (uint32_t)format;
+    mChannelMask = (uint32_t)channelMask;
     mChannelCount = channelCount;
     mSharedBuffer = sharedBuffer;
     mMuted = false;
@@ -681,7 +681,7 @@
 audio_io_handle_t AudioTrack::getOutput_l()
 {
     return AudioSystem::getOutput((audio_stream_type_t)mStreamType,
-            mCblk->sampleRate, mFormat, mChannels, (audio_policy_output_flags_t)mFlags);
+            mCblk->sampleRate, mFormat, mChannelMask, (audio_policy_output_flags_t)mFlags);
 }
 
 int AudioTrack::getSessionId()
@@ -705,8 +705,8 @@
 status_t AudioTrack::createTrack_l(
         int streamType,
         uint32_t sampleRate,
-        int format,
-        int channelCount,
+        uint32_t format,
+        uint32_t channelMask,
         int frameCount,
         uint32_t flags,
         const sp<IMemory>& sharedBuffer,
@@ -767,6 +767,7 @@
             }
         } else {
             // Ensure that buffer alignment matches channelcount
+            int channelCount = popcount(channelMask);
             if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
                 LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
                 return BAD_VALUE;
@@ -779,7 +780,7 @@
                                                       streamType,
                                                       sampleRate,
                                                       format,
-                                                      channelCount,
+                                                      channelMask,
                                                       frameCount,
                                                       ((uint16_t)flags) << 16,
                                                       sharedBuffer,
@@ -1164,7 +1165,7 @@
         result = createTrack_l(mStreamType,
                                cblk->sampleRate,
                                mFormat,
-                               mChannelCount,
+                               mChannelMask,
                                mFrameCount,
                                mFlags,
                                mSharedBuffer,
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 158d2f5..4a12962 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -82,8 +82,8 @@
                                 pid_t pid,
                                 int streamType,
                                 uint32_t sampleRate,
-                                int format,
-                                int channelCount,
+                                uint32_t format,
+                                uint32_t channelMask,
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
@@ -98,7 +98,7 @@
         data.writeInt32(streamType);
         data.writeInt32(sampleRate);
         data.writeInt32(format);
-        data.writeInt32(channelCount);
+        data.writeInt32(channelMask);
         data.writeInt32(frameCount);
         data.writeInt32(flags);
         data.writeStrongBinder(sharedBuffer->asBinder());
@@ -129,8 +129,8 @@
                                 pid_t pid,
                                 int input,
                                 uint32_t sampleRate,
-                                int format,
-                                int channelCount,
+                                uint32_t format,
+                                uint32_t channelMask,
                                 int frameCount,
                                 uint32_t flags,
                                 int *sessionId,
@@ -143,7 +143,7 @@
         data.writeInt32(input);
         data.writeInt32(sampleRate);
         data.writeInt32(format);
-        data.writeInt32(channelCount);
+        data.writeInt32(channelMask);
         data.writeInt32(frameCount);
         data.writeInt32(flags);
         int lSessionId = 0;
@@ -186,7 +186,7 @@
         return reply.readInt32();
     }
 
-    virtual int format(int output) const
+    virtual uint32_t format(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index d51c946..eae93ff 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1164,7 +1164,7 @@
     mem = new MemoryBase(cache->getHeap(), 0, cache->size());
     *pSampleRate = cache->sampleRate();
     *pNumChannels = cache->channelCount();
-    *pFormat = cache->format();
+    *pFormat = (int)cache->format();
     LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
 
 Exit:
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 053854f..f806624 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -360,8 +360,8 @@
         pid_t pid,
         int streamType,
         uint32_t sampleRate,
-        int format,
-        int channelCount,
+        uint32_t format,
+        uint32_t channelMask,
         int frameCount,
         uint32_t flags,
         const sp<IMemory>& sharedBuffer,
@@ -429,7 +429,7 @@
         LOGV("createTrack() lSessionId: %d", lSessionId);
 
         track = thread->createTrack_l(client, streamType, sampleRate, format,
-                channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);
+                channelMask, frameCount, sharedBuffer, lSessionId, &lStatus);
 
         // move effect chain to this output thread if an effect on same session was waiting
         // for a track to be created
@@ -477,7 +477,7 @@
     return thread->channelCount();
 }
 
-int AudioFlinger::format(int output) const
+uint32_t AudioFlinger::format(int output) const
 {
     Mutex::Autolock _l(mLock);
     PlaybackThread *thread = checkPlaybackThread_l(output);
@@ -916,7 +916,7 @@
     return (int)mChannelCount;
 }
 
-int AudioFlinger::ThreadBase::format() const
+uint32_t AudioFlinger::ThreadBase::format() const
 {
     return mFormat;
 }
@@ -1002,6 +1002,8 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
     result.append(buffer);
+    snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
+    result.append(buffer);
     snprintf(buffer, SIZE, "Format: %d\n", mFormat);
     result.append(buffer);
     snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
@@ -1075,7 +1077,7 @@
 
     snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
     result.append(buffer);
-    result.append("   Name  Clien Typ Fmt Chn Session Buf  S M F SRate LeftV RighV  Serv       User       Main buf   Aux Buf\n");
+    result.append("   Name  Clien Typ Fmt Chn mask   Session Buf  S M F SRate LeftV RighV  Serv       User       Main buf   Aux Buf\n");
     for (size_t i = 0; i < mTracks.size(); ++i) {
         sp<Track> track = mTracks[i];
         if (track != 0) {
@@ -1086,7 +1088,7 @@
 
     snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
     result.append(buffer);
-    result.append("   Name  Clien Typ Fmt Chn Session Buf  S M F SRate LeftV RighV  Serv       User       Main buf   Aux Buf\n");
+    result.append("   Name  Clien Typ Fmt Chn mask   Session Buf  S M F SRate LeftV RighV  Serv       User       Main buf   Aux Buf\n");
     for (size_t i = 0; i < mActiveTracks.size(); ++i) {
         wp<Track> wTrack = mActiveTracks[i];
         if (wTrack != 0) {
@@ -1172,8 +1174,8 @@
         const sp<AudioFlinger::Client>& client,
         int streamType,
         uint32_t sampleRate,
-        int format,
-        int channelCount,
+        uint32_t format,
+        uint32_t channelMask,
         int frameCount,
         const sp<IMemory>& sharedBuffer,
         int sessionId,
@@ -1183,11 +1185,14 @@
     status_t lStatus;
 
     if (mType == DIRECT) {
-        if (sampleRate != mSampleRate || format != mFormat || channelCount != (int)mChannelCount) {
-            LOGE("createTrack_l() Bad parameter:  sampleRate %d format %d, channelCount %d for output %p",
-                 sampleRate, format, channelCount, mOutput);
-            lStatus = BAD_VALUE;
-            goto Exit;
+        if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
+            if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
+                LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
+                        "for output %p with format %d",
+                        sampleRate, format, channelMask, mOutput, mFormat);
+                lStatus = BAD_VALUE;
+                goto Exit;
+            }
         }
     } else {
         // Resampler implementation limits input sampling rate to 2 x output sampling rate.
@@ -1224,7 +1229,7 @@
         }
 
         track = new Track(this, client, streamType, sampleRate, format,
-                channelCount, frameCount, sharedBuffer, sessionId);
+                channelMask, frameCount, sharedBuffer, sessionId);
         if (track->getCblk() == NULL || track->name() < 0) {
             lStatus = NO_MEMORY;
             goto Exit;
@@ -1373,7 +1378,7 @@
     switch (event) {
     case AudioSystem::OUTPUT_OPENED:
     case AudioSystem::OUTPUT_CONFIG_CHANGED:
-        desc.channels = mChannels;
+        desc.channels = mChannelMask;
         desc.samplingRate = mSampleRate;
         desc.format = mFormat;
         desc.frameCount = mFrameCount;
@@ -1393,8 +1398,8 @@
 void AudioFlinger::PlaybackThread::readOutputParameters()
 {
     mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
-    mChannels = mOutput->stream->common.get_channels(&mOutput->stream->common);
-    mChannelCount = (uint16_t)popcount(mChannels);
+    mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
+    mChannelCount = (uint16_t)popcount(mChannelMask);
     mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
     mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->stream->common);
     mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
@@ -1804,7 +1809,7 @@
                 AudioMixer::FORMAT, (void *)track->format());
             mAudioMixer->setParameter(
                 AudioMixer::TRACK,
-                AudioMixer::CHANNEL_COUNT, (void *)track->channelCount());
+                AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
             mAudioMixer->setParameter(
                 AudioMixer::RESAMPLE,
                 AudioMixer::SAMPLE_RATE,
@@ -2683,7 +2688,7 @@
                                             this,
                                             mSampleRate,
                                             mFormat,
-                                            mChannelCount,
+                                            mChannelMask,
                                             frameCount);
     if (outputTrack->cblk() != NULL) {
         thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
@@ -2751,8 +2756,8 @@
             const wp<ThreadBase>& thread,
             const sp<Client>& client,
             uint32_t sampleRate,
-            int format,
-            int channelCount,
+            uint32_t format,
+            uint32_t channelMask,
             int frameCount,
             uint32_t flags,
             const sp<IMemory>& sharedBuffer,
@@ -2772,6 +2777,7 @@
 
     // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
    size_t size = sizeof(audio_track_cblk_t);
+   uint8_t channelCount = popcount(channelMask);
    size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
    if (sharedBuffer == 0) {
        size += bufferSize;
@@ -2786,7 +2792,8 @@
                 // clear all buffers
                 mCblk->frameCount = frameCount;
                 mCblk->sampleRate = sampleRate;
-                mCblk->channelCount = (uint8_t)channelCount;
+                mChannelCount = channelCount;
+                mChannelMask = channelMask;
                 if (sharedBuffer == 0) {
                     mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
                     memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
@@ -2810,7 +2817,8 @@
            // clear all buffers
            mCblk->frameCount = frameCount;
            mCblk->sampleRate = sampleRate;
-           mCblk->channelCount = (uint8_t)channelCount;
+           mChannelCount = channelCount;
+           mChannelMask = channelMask;
            mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
            memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
            // Force underrun condition to avoid false underrun callback until first data is
@@ -2877,7 +2885,11 @@
 }
 
 int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
-    return (int)mCblk->channelCount;
+    return (const int)mChannelCount;
+}
+
+uint32_t AudioFlinger::ThreadBase::TrackBase::channelMask() const {
+    return mChannelMask;
 }
 
 void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
@@ -2889,9 +2901,9 @@
     if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
         ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
         LOGE("TrackBase::getBuffer buffer out of range:\n    start: %p, end %p , mBuffer %p mBufferEnd %p\n    \
-                server %d, serverBase %d, user %d, userBase %d, channelCount %d",
+                server %d, serverBase %d, user %d, userBase %d",
                 bufferStart, bufferEnd, mBuffer, mBufferEnd,
-                cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channelCount);
+                cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
         return 0;
     }
 
@@ -2906,12 +2918,12 @@
             const sp<Client>& client,
             int streamType,
             uint32_t sampleRate,
-            int format,
-            int channelCount,
+            uint32_t format,
+            uint32_t channelMask,
             int frameCount,
             const sp<IMemory>& sharedBuffer,
             int sessionId)
-    :   TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer, sessionId),
+    :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0, sharedBuffer, sessionId),
     mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
     mAuxEffectId(0), mHasVolumeController(false)
 {
@@ -2931,7 +2943,7 @@
         mStreamType = streamType;
         // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
         // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
-        mCblk->frameSize = audio_is_linear_pcm(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
+        mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(int8_t);
     }
 }
 
@@ -2979,12 +2991,12 @@
 
 void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
 {
-    snprintf(buffer, size, "   %05d %05d %03u %03u %03u %05u   %04u %1d %1d %1d %05u %05u %05u  0x%08x 0x%08x 0x%08x 0x%08x\n",
+    snprintf(buffer, size, "   %05d %05d %03u %03u 0x%08x %05u   %04u %1d %1d %1d %05u %05u %05u  0x%08x 0x%08x 0x%08x 0x%08x\n",
             mName - AudioMixer::TRACK0,
             (mClient == NULL) ? getpid() : mClient->pid(),
             mStreamType,
             mFormat,
-            mCblk->channelCount,
+            mChannelMask,
             mSessionId,
             mFrameCount,
             mState,
@@ -3219,21 +3231,21 @@
             const wp<ThreadBase>& thread,
             const sp<Client>& client,
             uint32_t sampleRate,
-            int format,
-            int channelCount,
+            uint32_t format,
+            uint32_t channelMask,
             int frameCount,
             uint32_t flags,
             int sessionId)
     :   TrackBase(thread, client, sampleRate, format,
-                  channelCount, frameCount, flags, 0, sessionId),
+                  channelMask, frameCount, flags, 0, sessionId),
         mOverflow(false)
 {
     if (mCblk != NULL) {
        LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
        if (format == AUDIO_FORMAT_PCM_16_BIT) {
-           mCblk->frameSize = channelCount * sizeof(int16_t);
+           mCblk->frameSize = mChannelCount * sizeof(int16_t);
        } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
-           mCblk->frameSize = channelCount * sizeof(int8_t);
+           mCblk->frameSize = mChannelCount * sizeof(int8_t);
        } else {
            mCblk->frameSize = sizeof(int8_t);
        }
@@ -3313,10 +3325,10 @@
 
 void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
 {
-    snprintf(buffer, size, "   %05d %03u %03u %05d   %04u %01d %05u  %08x %08x\n",
+    snprintf(buffer, size, "   %05d %03u 0x%08x %05d   %04u %01d %05u  %08x %08x\n",
             (mClient == NULL) ? getpid() : mClient->pid(),
             mFormat,
-            mCblk->channelCount,
+            mChannelMask,
             mSessionId,
             mFrameCount,
             mState,
@@ -3332,10 +3344,10 @@
             const wp<ThreadBase>& thread,
             DuplicatingThread *sourceThread,
             uint32_t sampleRate,
-            int format,
-            int channelCount,
+            uint32_t format,
+            uint32_t channelMask,
             int frameCount)
-    :   Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelCount, frameCount, NULL, 0),
+    :   Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
     mActive(false), mSourceThread(sourceThread)
 {
 
@@ -3346,8 +3358,10 @@
         mCblk->volume[0] = mCblk->volume[1] = 0x1000;
         mOutBuffer.frameCount = 0;
         playbackThread->mTracks.add(this);
-        LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p",
-                mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd);
+        LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
+                "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
+                mCblk, mBuffer, mCblk->buffers,
+                mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
     } else {
         LOGW("Error creating output track on thread %p", playbackThread);
     }
@@ -3382,7 +3396,7 @@
 {
     Buffer *pInBuffer;
     Buffer inBuffer;
-    uint32_t channelCount = mCblk->channelCount;
+    uint32_t channelCount = mChannelCount;
     bool outputBufferFull = false;
     inBuffer.frameCount = frames;
     inBuffer.i16 = data;
@@ -3667,8 +3681,8 @@
         pid_t pid,
         int input,
         uint32_t sampleRate,
-        int format,
-        int channelCount,
+        uint32_t format,
+        uint32_t channelMask,
         int frameCount,
         uint32_t flags,
         int *sessionId,
@@ -3717,7 +3731,7 @@
         }
         // create new record track. The record track uses one track in mHardwareMixerThread by convention.
         recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
-                                                   format, channelCount, frameCount, flags, lSessionId);
+                                                   format, channelMask, frameCount, flags, lSessionId);
     }
     if (recordTrack->getCblk() == NULL) {
         // remove local strong reference to Client before deleting the RecordTrack so that the Client
@@ -4065,7 +4079,7 @@
 
     if (mActiveTrack != 0) {
         result.append("Active Track:\n");
-        result.append("   Clien Fmt Chn Session Buf  S SRate  Serv     User\n");
+        result.append("   Clien Fmt Chn mask   Session Buf  S SRate  Serv     User\n");
         mActiveTrack->dump(buffer, SIZE);
         result.append(buffer);
 
@@ -4219,7 +4233,7 @@
     switch (event) {
     case AudioSystem::INPUT_OPENED:
     case AudioSystem::INPUT_CONFIG_CHANGED:
-        desc.channels = mChannels;
+        desc.channels = mChannelMask;
         desc.samplingRate = mSampleRate;
         desc.format = mFormat;
         desc.frameCount = mFrameCount;
@@ -4242,8 +4256,8 @@
     mResampler = 0;
 
     mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
-    mChannels = mInput->stream->common.get_channels(&mInput->stream->common);
-    mChannelCount = (uint16_t)popcount(mChannels);
+    mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
+    mChannelCount = (uint16_t)popcount(mChannelMask);
     mFormat = mInput->stream->common.get_format(&mInput->stream->common);
     mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->stream->common);
     mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 0698dcb..f3371bf 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -76,8 +76,8 @@
                                 pid_t pid,
                                 int streamType,
                                 uint32_t sampleRate,
-                                int format,
-                                int channelCount,
+                                uint32_t format,
+                                uint32_t channelMask,
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
@@ -87,7 +87,7 @@
 
     virtual     uint32_t    sampleRate(int output) const;
     virtual     int         channelCount(int output) const;
-    virtual     int         format(int output) const;
+    virtual     uint32_t    format(int output) const;
     virtual     size_t      frameCount(int output) const;
     virtual     uint32_t    latency(int output) const;
 
@@ -189,8 +189,8 @@
                                 pid_t pid,
                                 int input,
                                 uint32_t sampleRate,
-                                int format,
-                                int channelCount,
+                                uint32_t format,
+                                uint32_t channelMask,
                                 int frameCount,
                                 uint32_t flags,
                                 int *sessionId,
@@ -301,8 +301,8 @@
                                 TrackBase(const wp<ThreadBase>& thread,
                                         const sp<Client>& client,
                                         uint32_t sampleRate,
-                                        int format,
-                                        int channelCount,
+                                        uint32_t format,
+                                        uint32_t channelMask,
                                         int frameCount,
                                         uint32_t flags,
                                         const sp<IMemory>& sharedBuffer,
@@ -329,12 +329,14 @@
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
             virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
 
-            int format() const {
+            uint32_t format() const {
                 return mFormat;
             }
 
             int channelCount() const ;
 
+            uint32_t channelMask() const;
+
             int sampleRate() const;
 
             void* getBuffer(uint32_t offset, uint32_t frames) const;
@@ -360,9 +362,11 @@
             // we don't really need a lock for these
             int                 mState;
             int                 mClientTid;
-            uint8_t             mFormat;
+            uint32_t            mFormat;
             uint32_t            mFlags;
             int                 mSessionId;
+            uint8_t             mChannelCount;
+            uint32_t            mChannelMask;
         };
 
         class ConfigEvent {
@@ -375,7 +379,7 @@
 
                     uint32_t    sampleRate() const;
                     int         channelCount() const;
-                    int         format() const;
+                    uint32_t    format() const;
                     size_t      frameCount() const;
                     void        wakeUp()    { mWaitWorkCV.broadcast(); }
                     void        exit();
@@ -406,10 +410,10 @@
                     sp<AudioFlinger>        mAudioFlinger;
                     uint32_t                mSampleRate;
                     size_t                  mFrameCount;
-                    uint32_t                mChannels;
+                    uint32_t                mChannelMask;
                     uint16_t                mChannelCount;
                     uint16_t                mFrameSize;
-                    int                     mFormat;
+                    uint32_t                mFormat;
                     Condition               mParamCond;
                     Vector<String8>         mNewParameters;
                     status_t                mParamStatus;
@@ -442,8 +446,8 @@
                                         const sp<Client>& client,
                                         int streamType,
                                         uint32_t sampleRate,
-                                        int format,
-                                        int channelCount,
+                                        uint32_t format,
+                                        uint32_t channelMask,
                                         int frameCount,
                                         const sp<IMemory>& sharedBuffer,
                                         int sessionId);
@@ -530,8 +534,8 @@
                                 OutputTrack(  const wp<ThreadBase>& thread,
                                         DuplicatingThread *sourceThread,
                                         uint32_t sampleRate,
-                                        int format,
-                                        int channelCount,
+                                        uint32_t format,
+                                        uint32_t channelMask,
                                         int frameCount);
                                 ~OutputTrack();
 
@@ -583,8 +587,8 @@
                                     const sp<AudioFlinger::Client>& client,
                                     int streamType,
                                     uint32_t sampleRate,
-                                    int format,
-                                    int channelCount,
+                                    uint32_t format,
+                                    uint32_t channelMask,
                                     int frameCount,
                                     const sp<IMemory>& sharedBuffer,
                                     int sessionId,
@@ -829,8 +833,8 @@
                                 RecordTrack(const wp<ThreadBase>& thread,
                                         const sp<Client>& client,
                                         uint32_t sampleRate,
-                                        int format,
-                                        int channelCount,
+                                        uint32_t format,
+                                        uint32_t channelMask,
                                         int frameCount,
                                         uint32_t flags,
                                         int sessionId);
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 50dcda7..6e9319d 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -26,6 +26,10 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
+#include <cutils/bitops.h>
+
+#include <system/audio.h>
+
 #include "AudioMixer.h"
 
 namespace android {
@@ -61,6 +65,7 @@
         t->channelCount = 2;
         t->enabled = 0;
         t->format = 16;
+        t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
         t->buffer.raw = 0;
         t->bufferProvider = 0;
         t->hook = 0;
@@ -180,13 +185,18 @@
 
     switch (target) {
     case TRACK:
-        if (name == CHANNEL_COUNT) {
-            if ((uint32_t(valueInt) <= MAX_NUM_CHANNELS) && (valueInt)) {
-                if (mState.tracks[ mActiveTrack ].channelCount != valueInt) {
-                    mState.tracks[ mActiveTrack ].channelCount = valueInt;
-                    LOGV("setParameter(TRACK, CHANNEL_COUNT, %d)", valueInt);
+        if (name == CHANNEL_MASK) {
+            uint32_t mask = (uint32_t)value;
+            if (mState.tracks[ mActiveTrack ].channelMask != mask) {
+                uint8_t channelCount = popcount(mask);
+                if ((channelCount <= MAX_NUM_CHANNELS) && (channelCount)) {
+                    mState.tracks[ mActiveTrack ].channelMask = mask;
+                    mState.tracks[ mActiveTrack ].channelCount = channelCount;
+                    LOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
                     invalidateState(1<<mActiveTrack);
+                    return NO_ERROR;
                 }
+            } else {
                 return NO_ERROR;
             }
         }
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index 88408a7..75c9170 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -61,7 +61,7 @@
 
         // set Parameter names
         // for target TRACK
-        CHANNEL_COUNT   = 0x4000,
+        CHANNEL_MASK    = 0x4000,
         FORMAT          = 0x4001,
         MAIN_BUFFER     = 0x4002,
         AUX_BUFFER      = 0x4003,
@@ -150,6 +150,7 @@
         uint8_t     enabled      : 1;
         uint8_t     reserved0    : 3;
         uint8_t     format;
+        uint32_t    channelMask;
 
         AudioBufferProvider*                bufferProvider;
         mutable AudioBufferProvider::Buffer buffer;