Add gapless playback support for NuPlayer

This makes NuPlayer use a SkipCutBuffer when needed, and adds a new
AudioSink method to retrieve the number of frames written so far, so
NuPlayerRenderer can calculate how much data it can write without blocking.
Also make some more methods const.

Change-Id: Id7d253ad8a7b85e9a84ca2baafbe32817b16c744
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index cc3138d..a977337 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1417,6 +1417,7 @@
     : mCallback(NULL),
       mCallbackCookie(NULL),
       mCallbackData(NULL),
+      mBytesWritten(0),
       mSessionId(sessionId) {
     ALOGV("AudioOutput(%d)", sessionId);
     mTrack = 0;
@@ -1495,12 +1496,19 @@
     return mMsecsPerFrame;
 }
 
-status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position)
+status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
 {
     if (mTrack == 0) return NO_INIT;
     return mTrack->getPosition(position);
 }
 
+status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
+{
+    if (mTrack == 0) return NO_INIT;
+    *frameswritten = mBytesWritten / frameSize();
+    return OK;
+}
+
 status_t MediaPlayerService::AudioOutput::open(
         uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
         audio_format_t format, int bufferCount,
@@ -1656,6 +1664,7 @@
         mTrack = NULL;
         mNextOutput->mSampleRateHz = mSampleRateHz;
         mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
+        mNextOutput->mBytesWritten = mBytesWritten;
     }
 }
 
@@ -1666,6 +1675,7 @@
     //ALOGV("write(%p, %u)", buffer, size);
     if (mTrack) {
         ssize_t ret = mTrack->write(buffer, size);
+        mBytesWritten += ret;
         return ret;
     }
     return NO_INIT;
@@ -1777,7 +1787,7 @@
     data->unlock();
 }
 
-int MediaPlayerService::AudioOutput::getSessionId()
+int MediaPlayerService::AudioOutput::getSessionId() const
 {
     return mSessionId;
 }
@@ -1802,13 +1812,20 @@
     return mMsecsPerFrame;
 }
 
-status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position)
+status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const
 {
     if (position == 0) return BAD_VALUE;
     *position = mSize;
     return NO_ERROR;
 }
 
+status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
+{
+    if (written == 0) return BAD_VALUE;
+    *written = mSize;
+    return NO_ERROR;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 struct CallbackThread : public Thread {
@@ -1971,7 +1988,7 @@
     p->mSignal.signal();
 }
 
-int MediaPlayerService::AudioCache::getSessionId()
+int MediaPlayerService::AudioCache::getSessionId() const
 {
     return 0;
 }