AudioRecord notification frames

Change-Id: I76ec536d1504eb9a558178b62bf225aace4b40d1
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 7c240b4..c1b6b03 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -444,7 +444,10 @@
     void*                   mUserData;          // for client callback handler
 
     // for notification APIs
-    uint32_t                mNotificationFrames; // frames between each notification callback
+    uint32_t                mNotificationFramesReq; // requested number of frames between each
+                                                    // notification callback
+    uint32_t                mNotificationFramesAct; // actual number of frames between each
+                                                    // notification callback
     bool                    mRefreshRemaining;  // processAudioBuffer() should refresh next 2
 
     // These are private to processAudioBuffer(), and are not protected by a lock
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 0c798ae..6c04b43 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -270,7 +270,8 @@
 
     mActive = false;
     mCbf = cbf;
-    mNotificationFrames = notificationFrames;
+    mNotificationFramesReq = notificationFrames;
+    mNotificationFramesAct = 0;
     mRefreshRemaining = true;
     mUserData = user;
     // TODO: add audio hardware input latency here
@@ -458,7 +459,8 @@
         if ((mTransfer != TRANSFER_CALLBACK) || (mAudioRecordThread == 0)) {
             ALOGW("AUDIO_INPUT_FLAG_FAST denied by client");
             // once denied, do not request again if IAudioRecord is re-created
-            mFlags = (audio_input_flags_t) (flags & ~AUDIO_INPUT_FLAG_FAST);
+            flags = (audio_input_flags_t) (flags & ~AUDIO_INPUT_FLAG_FAST);
+            mFlags = flags;
         } else {
             trackFlags |= IAudioFlinger::TRACK_FAST;
             tid = mAudioRecordThread->getTid();
@@ -494,6 +496,27 @@
     mCblkMemory = iMem;
     audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer());
     mCblk = cblk;
+    // FIXME missing fast track frameCount logic
+    mAwaitBoost = false;
+    mNotificationFramesAct = mNotificationFramesReq;
+    if (flags & AUDIO_INPUT_FLAG_FAST) {
+        if (trackFlags & IAudioFlinger::TRACK_FAST) {
+            ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %u", frameCount);
+            mAwaitBoost = true;
+            // double-buffering is not required for fast tracks, due to tighter scheduling
+            if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount) {
+                mNotificationFramesAct = frameCount;
+            }
+        } else {
+            ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %u", frameCount);
+            // once denied, do not request again if IAudioRecord is re-created
+            flags = (audio_input_flags_t) (flags & ~AUDIO_INPUT_FLAG_FAST);
+            mFlags = flags;
+            if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) {
+                mNotificationFramesAct = frameCount/2;
+            }
+        }
+    }
 
     // starting address of buffers in shared memory
     void *buffers = (char*)cblk + sizeof(audio_track_cblk_t);
@@ -501,7 +524,7 @@
     // update proxy
     mProxy = new AudioRecordClientProxy(cblk, buffers, frameCount, mFrameSize);
     mProxy->setEpoch(epoch);
-    mProxy->setMinimum(mNotificationFrames);
+    mProxy->setMinimum(mNotificationFramesAct);
 
     mDeathNotifier = new DeathNotifier(this);
     mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this);
@@ -748,7 +771,7 @@
     }
 
     // Cache other fields that will be needed soon
-    size_t notificationFrames = mNotificationFrames;
+    size_t notificationFrames = mNotificationFramesAct;
     if (mRefreshRemaining) {
         mRefreshRemaining = false;
         mRemainingFrames = notificationFrames;