Add support for deep audio buffers

Allow AudioSink to use deep audio buffering when the
source is audio only and its duration is more than
a certain threshold.
This helps improve battery life but implies higher
audio latency.

Change-Id: Ie79915b61c370292f05aabda9779356570e03cbb
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 7254599..bfdf250 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1412,7 +1412,8 @@
       mCallbackCookie(NULL),
       mCallbackData(NULL),
       mBytesWritten(0),
-      mSessionId(sessionId) {
+      mSessionId(sessionId),
+      mFlags(AUDIO_OUTPUT_FLAG_NONE) {
     ALOGV("AudioOutput(%d)", sessionId);
     mTrack = 0;
     mRecycledTrack = 0;
@@ -1506,7 +1507,8 @@
 status_t MediaPlayerService::AudioOutput::open(
         uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
         audio_format_t format, int bufferCount,
-        AudioCallback cb, void *cookie)
+        AudioCallback cb, void *cookie,
+        audio_output_flags_t flags)
 {
     mCallback = cb;
     mCallbackCookie = cookie;
@@ -1521,7 +1523,7 @@
             format, bufferCount, mSessionId);
     int afSampleRate;
     int afFrameCount;
-    int frameCount;
+    uint32_t frameCount;
 
     if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
         return NO_INIT;
@@ -1539,6 +1541,7 @@
             return NO_INIT;
         }
     }
+
     if (mRecycledTrack) {
         // check if the existing track can be reused as-is, or if a new track needs to be created.
 
@@ -1553,6 +1556,9 @@
                 (mRecycledTrack->frameCount() != frameCount)) {
             ALOGV("samplerate, channelcount or framecount differ");
             reuse = false;
+        } if (flags != mFlags) {
+            ALOGV("output flags differ");
+            reuse = false;
         }
         if (reuse) {
             ALOGV("chaining to next output");
@@ -1587,7 +1593,7 @@
                 format,
                 channelMask,
                 frameCount,
-                AUDIO_OUTPUT_FLAG_NONE,
+                flags,
                 CallbackWrapper,
                 mCallbackData,
                 0,  // notification frames
@@ -1599,7 +1605,7 @@
                 format,
                 channelMask,
                 frameCount,
-                AUDIO_OUTPUT_FLAG_NONE,
+                flags,
                 NULL,
                 NULL,
                 0,
@@ -1616,6 +1622,7 @@
     t->setVolume(mLeftVolume, mRightVolume);
 
     mSampleRateHz = sampleRate;
+    mFlags = flags;
     mMsecsPerFrame = mPlaybackRatePermille / (float) sampleRate;
     uint32_t pos;
     if (t->getPosition(&pos) == OK) {
@@ -1891,7 +1898,7 @@
 status_t MediaPlayerService::AudioCache::open(
         uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
         audio_format_t format, int bufferCount,
-        AudioCallback cb, void *cookie)
+        AudioCallback cb, void *cookie, audio_output_flags_t flags)
 {
     ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount);
     if (mHeap->getHeapID() < 0) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 2a8cfd2..95b1b05 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -91,7 +91,8 @@
         virtual status_t        open(
                 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
                 audio_format_t format, int bufferCount,
-                AudioCallback cb, void *cookie);
+                AudioCallback cb, void *cookie,
+                audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE);
 
         virtual void            start();
         virtual ssize_t         write(const void* buffer, size_t size);
@@ -135,6 +136,7 @@
         int                     mAuxEffectId;
         static bool             mIsOnEmulator;
         static int              mMinBufferCount;  // 12 for emulator; otherwise 4
+        audio_output_flags_t    mFlags;
 
         // CallbackData is what is passed to the AudioTrack as the "user" data.
         // We need to be able to target this to a different Output on the fly,
@@ -190,7 +192,8 @@
         virtual status_t        open(
                 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
                 audio_format_t format, int bufferCount = 1,
-                AudioCallback cb = NULL, void *cookie = NULL);
+                AudioCallback cb = NULL, void *cookie = NULL,
+                audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE);
 
         virtual void            start();
         virtual ssize_t         write(const void* buffer, size_t size);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 11cea3b..f1467c4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -390,12 +390,30 @@
                          sampleRate, numChannels);
 
                     mAudioSink->close();
+
+                    audio_output_flags_t flags;
+                    int64_t durationUs;
+                    // FIXME: we should handle the case where the video decoder is created after
+                    // we receive the format change indication. Current code will just make that
+                    // we select deep buffer with video which should not be a problem as it should
+                    // not prevent from keeping A/V sync.
+                    if (mVideoDecoder == NULL &&
+                            mSource->getDuration(&durationUs) == OK &&
+                            durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
+                        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+                    } else {
+                        flags = AUDIO_OUTPUT_FLAG_NONE;
+                    }
+
                     CHECK_EQ(mAudioSink->open(
                                 sampleRate,
                                 numChannels,
                                 CHANNEL_MASK_USE_CHANNEL_ORDER,
                                 AUDIO_FORMAT_PCM_16_BIT,
-                                8 /* bufferCount */),
+                                8 /* bufferCount */,
+                                NULL,
+                                NULL,
+                                flags),
                              (status_t)OK);
                     mAudioSink->start();