Merge "Fix issue 2285561: New AudioFlinger and audio driver API needed for A/V sync"
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index b42bf54..42bb4df 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -222,6 +222,17 @@
 
     static status_t setVoiceVolume(float volume);
 
+    // return the number of audio frames written by AudioFlinger to audio HAL and
+    // audio dsp to DAC since the output on which the specificed stream is playing
+    // has exited standby.
+    // returned status (from utils/Errors.h) can be:
+    // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data
+    // - INVALID_OPERATION: Not supported on current hardware platform
+    // - BAD_VALUE: invalid parameter
+    // NOTE: this feature is not supported on all hardware platforms and it is
+    // necessary to check returned status before using the returned values.
+    static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT);
+
     //
     // AudioPolicyService interface
     //
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index b689dcb..bddd23e 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -130,6 +130,7 @@
     virtual status_t setStreamOutput(uint32_t stream, int output) = 0;
 
     virtual status_t setVoiceVolume(float volume) = 0;
+    virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) = 0;
 };
 
 
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 6575da6..588c51a 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -72,6 +72,7 @@
         virtual ssize_t     frameSize() const = 0;
         virtual uint32_t    latency() const = 0;
         virtual float       msecsPerFrame() const = 0;
+        virtual status_t    getPosition(uint32_t *position) = 0;
 
         // If no callback is specified, use the "write" API below to submit
         // audio data. Otherwise return a full buffer of audio data on each
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index e3b829b..c5dfbb5 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -342,6 +342,18 @@
     return af->setVoiceVolume(value);
 }
 
+status_t AudioSystem::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    if (stream == DEFAULT) {
+        stream = MUSIC;
+    }
+
+    return af->getRenderPosition(halFrames, dspFrames, getOutput((stream_type)stream));
+}
+
 // ---------------------------------------------------------------------------
 
 void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index fc42979..ca3a2a6 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -60,7 +60,8 @@
     OPEN_INPUT,
     CLOSE_INPUT,
     SET_STREAM_OUTPUT,
-    SET_VOICE_VOLUME
+    SET_VOICE_VOLUME,
+    GET_RENDER_POSITION
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -466,6 +467,26 @@
         remote()->transact(SET_VOICE_VOLUME, data, &reply);
         return reply.readInt32();
     }
+
+    virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
+        remote()->transact(GET_RENDER_POSITION, data, &reply);
+        status_t status = reply.readInt32();
+        if (status == NO_ERROR) {
+            uint32_t tmp = reply.readInt32();
+            if (halFrames) {
+                *halFrames = tmp;
+            }
+            tmp = reply.readInt32();
+            if (dspFrames) {
+                *dspFrames = tmp;
+            }
+        }
+        return status;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -718,6 +739,19 @@
             reply->writeInt32( setVoiceVolume(volume) );
             return NO_ERROR;
         } break;
+        case GET_RENDER_POSITION: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int output = data.readInt32();
+            uint32_t halFrames;
+            uint32_t dspFrames;
+            status_t status = getRenderPosition(&halFrames, &dspFrames, output);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(halFrames);
+                reply->writeInt32(dspFrames);
+            }
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index af8d1b5..5b061b1 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1432,6 +1432,12 @@
     return mMsecsPerFrame;
 }
 
+status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position)
+{
+    if (mTrack == 0) return NO_INIT;
+    return mTrack->getPosition(position);
+}
+
 status_t MediaPlayerService::AudioOutput::open(
         uint32_t sampleRate, int channelCount, int format, int bufferCount,
         AudioCallback cb, void *cookie)
@@ -1613,6 +1619,13 @@
     return mMsecsPerFrame;
 }
 
+status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position)
+{
+    if (position == 0) return BAD_VALUE;
+    *position = mSize;
+    return NO_ERROR;
+}
+
 status_t MediaPlayerService::AudioCache::open(
         uint32_t sampleRate, int channelCount, int format, int bufferCount,
         AudioCallback cb, void *cookie)
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index d1206b4..d243b96 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -76,6 +76,7 @@
         virtual ssize_t         frameSize() const;
         virtual uint32_t        latency() const;
         virtual float           msecsPerFrame() const;
+        virtual status_t        getPosition(uint32_t *position);
 
         virtual status_t        open(
                 uint32_t sampleRate, int channelCount,
@@ -130,6 +131,7 @@
         virtual ssize_t         frameSize() const { return ssize_t(mChannelCount * ((mFormat == AudioSystem::PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); }
         virtual uint32_t        latency() const;
         virtual float           msecsPerFrame() const;
+        virtual status_t        getPosition(uint32_t *position);
 
         virtual status_t        open(
                 uint32_t sampleRate, int channelCount, int format,