Move frame count calculations for fast tracks

For fast tracks: move the default and minimum frame count calculations
from client to server.  If accepted, the default and minimum frame count
is the fast mixer (HAL) frame count.  If denied, the default and minimum
frame count is the same as it currently is for normal tracks.

For normal tracks: there is no change yet, preserve legacy behavior for
now but add a FIXME to change this later.

Bug fix: the test for buffer alignment matches channelCount was wrong.

Bug fix: check for 8-bit data in shared memory, which isn't supported.

Optimizations:
 - in set(), only call AudioSystem::getOutputSamplingRate() when needed
 - in createTrack_l(), only call AudioSystem::getSamplingRate() and
   AudioSystem::getFrameCount() when needed

Change-Id: I79d2fe507db1a8f7bb094c71da8a129951dbb82f
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index b1be8b1..cd419bd 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -54,6 +54,12 @@
         audio_stream_type_t streamType,
         uint32_t sampleRate)
 {
+    // FIXME merge with similar code in createTrack_l(), except we're missing
+    //       some information here that is available in createTrack_l():
+    //          audio_io_handle_t output
+    //          audio_format_t format
+    //          audio_channel_mask_t channelMask
+    //          audio_output_flags_t flags
     int afSampleRate;
     if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         return NO_INIT;
@@ -201,11 +207,11 @@
         streamType = AUDIO_STREAM_MUSIC;
     }
 
-    int afSampleRate;
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
-        return NO_INIT;
-    }
     if (sampleRate == 0) {
+        int afSampleRate;
+        if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+            return NO_INIT;
+        }
         sampleRate = afSampleRate;
     }
 
@@ -223,6 +229,12 @@
         return BAD_VALUE;
     }
 
+    // AudioFlinger does not currently support 8-bit data in shared memory
+    if (format == AUDIO_FORMAT_PCM_8_BIT && sharedBuffer != 0) {
+        ALOGE("8-bit data in shared memory is not supported");
+        return BAD_VALUE;
+    }
+
     // force direct flag if format is not linear PCM
     if (!audio_is_linear_pcm(format)) {
         flags = (audio_output_flags_t)
@@ -744,14 +756,6 @@
         return NO_INIT;
     }
 
-    int afSampleRate;
-    if (AudioSystem::getSamplingRate(output, streamType, &afSampleRate) != NO_ERROR) {
-        return NO_INIT;
-    }
-    int afFrameCount;
-    if (AudioSystem::getFrameCount(output, streamType, &afFrameCount) != NO_ERROR) {
-        return NO_INIT;
-    }
     uint32_t afLatency;
     if (AudioSystem::getLatency(output, streamType, &afLatency) != NO_ERROR) {
         return NO_INIT;
@@ -768,14 +772,57 @@
         ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client");
         flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST);
     }
-    ALOGV("createTrack_l() output %d afFrameCount %d afLatency %d", output, afFrameCount, afLatency);
+    ALOGV("createTrack_l() output %d afLatency %d", output, afLatency);
 
     mNotificationFramesAct = mNotificationFramesReq;
+
     if (!audio_is_linear_pcm(format)) {
+
         if (sharedBuffer != 0) {
+            // Same comment as below about ignoring frameCount parameter for set()
             frameCount = sharedBuffer->size();
+        } else if (frameCount == 0) {
+            int afFrameCount;
+            if (AudioSystem::getFrameCount(output, streamType, &afFrameCount) != NO_ERROR) {
+                return NO_INIT;
+            }
+            frameCount = afFrameCount;
         }
-    } else {
+
+    } else if (sharedBuffer != 0) {
+
+        // Ensure that buffer alignment matches channelCount
+        int channelCount = popcount(channelMask);
+        // 8-bit data in shared memory is not currently supported by AudioFlinger
+        size_t alignment = /* format == AUDIO_FORMAT_PCM_8_BIT ? 1 : */ 2;
+        if (channelCount > 1) {
+            // More than 2 channels does not require stronger alignment than stereo
+            alignment <<= 1;
+        }
+        if (((uint32_t)sharedBuffer->pointer() & (alignment - 1)) != 0) {
+            ALOGE("Invalid buffer alignment: address %p, channelCount %d",
+                    sharedBuffer->pointer(), channelCount);
+            return BAD_VALUE;
+        }
+
+        // When initializing a shared buffer AudioTrack via constructors,
+        // there's no frameCount parameter.
+        // But when initializing a shared buffer AudioTrack via set(),
+        // there _is_ a frameCount parameter.  We silently ignore it.
+        frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+
+    } else if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) {
+
+        // FIXME move these calculations and associated checks to server
+        int afSampleRate;
+        if (AudioSystem::getSamplingRate(output, streamType, &afSampleRate) != NO_ERROR) {
+            return NO_INIT;
+        }
+        int afFrameCount;
+        if (AudioSystem::getFrameCount(output, streamType, &afFrameCount) != NO_ERROR) {
+            return NO_INIT;
+        }
+
         // Ensure that buffer depth covers at least audio hardware latency
         uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
         if (minBufCount < 2) minBufCount = 2;
@@ -784,38 +831,27 @@
         ALOGV("minFrameCount: %d, afFrameCount=%d, minBufCount=%d, sampleRate=%d, afSampleRate=%d"
                 ", afLatency=%d",
                 minFrameCount, afFrameCount, minBufCount, sampleRate, afSampleRate, afLatency);
-#define MIN_FRAME_COUNT_FAST 128    // FIXME hard-coded
-        if ((flags & AUDIO_OUTPUT_FLAG_FAST) && (minFrameCount > MIN_FRAME_COUNT_FAST)) {
-            minFrameCount = MIN_FRAME_COUNT_FAST;
+
+        if (frameCount == 0) {
+            frameCount = minFrameCount;
+        }
+        if (mNotificationFramesAct == 0) {
+            mNotificationFramesAct = frameCount/2;
+        }
+        // Make sure that application is notified with sufficient margin
+        // before underrun
+        if (mNotificationFramesAct > (uint32_t)frameCount/2) {
+            mNotificationFramesAct = frameCount/2;
+        }
+        if (frameCount < minFrameCount) {
+            // not ALOGW because it happens all the time when playing key clicks over A2DP
+            ALOGV("Minimum buffer size corrected from %d to %d",
+                     frameCount, minFrameCount);
+            frameCount = minFrameCount;
         }
 
-        if (sharedBuffer == 0) {
-            if (frameCount == 0) {
-                frameCount = minFrameCount;
-            }
-            if (mNotificationFramesAct == 0) {
-                mNotificationFramesAct = frameCount/2;
-            }
-            // Make sure that application is notified with sufficient margin
-            // before underrun
-            if (mNotificationFramesAct > (uint32_t)frameCount/2) {
-                mNotificationFramesAct = frameCount/2;
-            }
-            if (frameCount < minFrameCount) {
-                // not ALOGW because it happens all the time when playing key clicks over A2DP
-                ALOGV("Minimum buffer size corrected from %d to %d",
-                         frameCount, minFrameCount);
-                frameCount = minFrameCount;
-            }
-        } else {
-            // Ensure that buffer alignment matches channelCount
-            int channelCount = popcount(channelMask);
-            if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
-                ALOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
-                return BAD_VALUE;
-            }
-            frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
-        }
+    } else {
+        // For fast tracks, the frame count calculations and checks are done by server
     }
 
     IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
@@ -864,6 +900,9 @@
         } else {
             ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", mCblk->frameCount);
         }
+        if (sharedBuffer == 0) {
+            mNotificationFramesAct = mCblk->frameCount/2;
+        }
     }
     if (sharedBuffer == 0) {
         mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
@@ -879,6 +918,7 @@
     mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
     mCblk->waitTimeMs = 0;
     mRemainingFrames = mNotificationFramesAct;
+    // FIXME don't believe this lie
     mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate;
     return NO_ERROR;
 }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 6eeda9a..1c277ce 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1623,8 +1623,8 @@
     bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
 
     // client expresses a preference for FAST, but we get the final say
-    if ((flags & IAudioFlinger::TRACK_FAST) &&
-          !(
+    if (flags & IAudioFlinger::TRACK_FAST) {
+      if (
             // not timed
             (!isTimed) &&
             // either of these use cases:
@@ -1633,11 +1633,11 @@
               (
                 (sharedBuffer != 0)
               ) ||
-              // use case 2: callback handler and frame count at least as large as HAL
+              // use case 2: callback handler and frame count is default or at least as large as HAL
               (
                 (tid != -1) &&
-                // FIXME supported frame counts should not be hard-coded
-                frameCount >= (int) mFrameCount // FIXME int cast is due to wrong parameter type
+                ((frameCount == 0) ||
+                (frameCount >= (int) mFrameCount)) // FIXME int cast is due to wrong parameter type
               )
             ) &&
             // PCM data
@@ -1655,17 +1655,35 @@
             (mFastTrackAvailMask != 0)
             // FIXME test that MixerThread for this fast track has a capable output HAL
             // FIXME add a permission test also?
-          ) ) {
-        ALOGW("AUDIO_POLICY_FLAG_FAST denied: isTimed=%d sharedBuffer=%p frameCount=%d "
+        ) {
+        ALOGI("AUDIO_OUTPUT_FLAG_FAST accepted: frameCount=%d mFrameCount=%d",
+                frameCount, mFrameCount);
+        // if frameCount not specified, then it defaults to fast mixer (HAL) frame count
+        if (frameCount == 0) {
+            frameCount = mFrameCount;
+        }
+      } else {
+        ALOGW("AUDIO_OUTPUT_FLAG_FAST denied: isTimed=%d sharedBuffer=%p frameCount=%d "
                 "mFrameCount=%d format=%d isLinear=%d channelMask=%d sampleRate=%d mSampleRate=%d "
                 "hasFastMixer=%d tid=%d fastTrackAvailMask=%#x",
                 isTimed, sharedBuffer.get(), frameCount, mFrameCount, format,
                 audio_is_linear_pcm(format),
                 channelMask, sampleRate, mSampleRate, hasFastMixer(), tid, mFastTrackAvailMask);
         flags &= ~IAudioFlinger::TRACK_FAST;
-        if (0 < frameCount && frameCount < (int) mNormalFrameCount) {
-            frameCount = mNormalFrameCount;
+        // For compatibility with AudioTrack calculation, buffer depth is forced
+        // to be at least 2 x the normal mixer frame count and cover audio hardware latency.
+        // This is probably too conservative, but legacy application code may depend on it.
+        // If you change this calculation, also review the start threshold which is related.
+        uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
+        uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
+        if (minBufCount < 2) {
+            minBufCount = 2;
         }
+        int minFrameCount = mNormalFrameCount * minBufCount;
+        if (frameCount < minFrameCount) {
+            frameCount = minFrameCount;
+        }
+      }
     }
 
     if (mType == DIRECT) {