summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioSystem.h11
-rw-r--r--include/media/IAudioFlinger.h1
-rw-r--r--include/media/MediaPlayerInterface.h1
-rw-r--r--libs/audioflinger/A2dpAudioInterface.cpp6
-rw-r--r--libs/audioflinger/A2dpAudioInterface.h1
-rw-r--r--libs/audioflinger/AudioDumpInterface.cpp6
-rw-r--r--libs/audioflinger/AudioDumpInterface.h3
-rw-r--r--libs/audioflinger/AudioFlinger.cpp33
-rw-r--r--libs/audioflinger/AudioFlinger.h3
-rw-r--r--libs/audioflinger/AudioHardwareGeneric.cpp12
-rw-r--r--libs/audioflinger/AudioHardwareGeneric.h1
-rw-r--r--libs/audioflinger/AudioHardwareStub.cpp5
-rw-r--r--libs/audioflinger/AudioHardwareStub.h1
-rw-r--r--media/libmedia/AudioSystem.cpp12
-rw-r--r--media/libmedia/IAudioFlinger.cpp36
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp13
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h2
17 files changed, 137 insertions, 10 deletions
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 @@ public:
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 @@ public:
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 @@ public:
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/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index c07bbfe..747d0e4 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -457,4 +457,10 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<Strin
return NO_ERROR;
}
+status_t A2dpAudioInterface::A2dpAudioStreamOut::getRenderPosition(uint32_t *driverFrames)
+{
+ //TODO: enable when supported by driver
+ return INVALID_OPERATION;
+}
+
}; // namespace android
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index 530e432..48154f9 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -93,6 +93,7 @@ private:
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
private:
friend class A2dpAudioInterface;
diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp
index 858e5aa..30e2bc9 100644
--- a/libs/audioflinger/AudioDumpInterface.cpp
+++ b/libs/audioflinger/AudioDumpInterface.cpp
@@ -379,6 +379,12 @@ void AudioStreamOutDump::Close()
}
}
+status_t AudioStreamOutDump::getRenderPosition(uint32_t *dspFrames)
+{
+ if (mFinalStream != 0 ) return mFinalStream->getRenderPosition(dspFrames);
+ return INVALID_OPERATION;
+}
+
// ----------------------------------------------------------------------------
AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h
index 1136ce1..5b9a6b1 100644
--- a/libs/audioflinger/AudioDumpInterface.h
+++ b/libs/audioflinger/AudioDumpInterface.h
@@ -56,8 +56,9 @@ public:
void Close(void);
AudioStreamOut* finalStream() { return mFinalStream; }
uint32_t device() { return mDevice; }
-
int getId() { return mId; }
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
+
private:
AudioDumpInterface *mInterface;
int mId;
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 5c58603..cad420a 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -633,6 +633,20 @@ status_t AudioFlinger::setVoiceVolume(float value)
return ret;
}
+status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
+{
+ status_t status;
+
+ Mutex::Autolock _l(mLock);
+
+ PlaybackThread *playbackThread = checkPlaybackThread_l(output);
+ if (playbackThread != NULL) {
+ return playbackThread->getRenderPosition(halFrames, dspFrames);
+ }
+
+ return BAD_VALUE;
+}
+
void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
{
@@ -1166,6 +1180,19 @@ void AudioFlinger::PlaybackThread::readOutputParameters()
memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
}
+status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
+{
+ if (halFrames == 0 || dspFrames == 0) {
+ return BAD_VALUE;
+ }
+ if (mOutput == 0) {
+ return INVALID_OPERATION;
+ }
+ *halFrames = mBytesWritten/mOutput->frameSize();
+
+ return mOutput->getRenderPosition(dspFrames);
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
@@ -1290,8 +1317,9 @@ bool AudioFlinger::MixerThread::threadLoop()
if (sleepTime == 0) {
mLastWriteTime = systemTime();
mInWrite = true;
+ mBytesWritten += mixBufferSize;
int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
- if (bytesWritten > 0) mBytesWritten += bytesWritten;
+ if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
mNumWrites++;
mInWrite = false;
nsecs_t now = systemTime();
@@ -1812,8 +1840,9 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
if (sleepTime == 0) {
mLastWriteTime = systemTime();
mInWrite = true;
+ mBytesWritten += mixBufferSize;
int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
- if (bytesWritten) mBytesWritten += bytesWritten;
+ if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
mNumWrites++;
mInWrite = false;
mStandby = false;
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 52999b1..44da9ed 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -136,6 +136,8 @@ public:
virtual status_t setVoiceVolume(float volume);
+ virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output);
+
// IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
@@ -526,6 +528,7 @@ private:
bool isSuspended() { return (mSuspended != 0); }
virtual String8 getParameters(const String8& keys);
virtual void audioConfigChanged(int event, int param = 0);
+ virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
struct stream_type_t {
stream_type_t()
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp
index 57874f3..d63c031 100644
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ b/libs/audioflinger/AudioHardwareGeneric.cpp
@@ -298,6 +298,11 @@ String8 AudioStreamOutGeneric::getParameters(const String8& keys)
return param.toString();
}
+status_t AudioStreamOutGeneric::getRenderPosition(uint32_t *dspFrames)
+{
+ return INVALID_OPERATION;
+}
+
// ----------------------------------------------------------------------------
// record functions
@@ -310,9 +315,8 @@ status_t AudioStreamInGeneric::set(
uint32_t *pRate,
AudioSystem::audio_in_acoustics acoustics)
{
- // FIXME: remove logging
if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE;
- LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
+ LOGV("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
// check values
if ((*pFormat != format()) ||
(*pChannels != channels()) ||
@@ -332,14 +336,10 @@ status_t AudioStreamInGeneric::set(
AudioStreamInGeneric::~AudioStreamInGeneric()
{
- // FIXME: remove logging
- LOGD("AudioStreamInGeneric destructor");
}
ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
{
- // FIXME: remove logging
- LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, (int)bytes, mFd);
AutoMutex lock(mLock);
if (mFd < 0) {
LOGE("Attempt to read from unopened device");
diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h
index 42da413..95c7ea3 100644
--- a/libs/audioflinger/AudioHardwareGeneric.h
+++ b/libs/audioflinger/AudioHardwareGeneric.h
@@ -55,6 +55,7 @@ public:
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
private:
AudioHardwareGeneric *mAudioHardware;
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
index ae391ee..ae215d1 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/libs/audioflinger/AudioHardwareStub.cpp
@@ -158,6 +158,11 @@ String8 AudioStreamOutStub::getParameters(const String8& keys)
return param.toString();
}
+status_t AudioStreamOutStub::getRenderPosition(uint32_t *dspFrames)
+{
+ return INVALID_OPERATION;
+}
+
// ----------------------------------------------------------------------------
status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate,
diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h
index 583f852..769ae3f 100644
--- a/libs/audioflinger/AudioHardwareStub.h
+++ b/libs/audioflinger/AudioHardwareStub.h
@@ -41,6 +41,7 @@ public:
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR;}
virtual String8 getParameters(const String8& keys);
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
};
class AudioStreamInStub : public AudioStreamIn {
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 @@ status_t AudioSystem::setVoiceVolume(float value)
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 @@ enum {
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 @@ public:
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 @@ status_t BnAudioFlinger::onTransact(
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 @@ float MediaPlayerService::AudioOutput::msecsPerFrame() const
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 @@ float MediaPlayerService::AudioCache::msecsPerFrame() const
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 @@ class MediaPlayerService : public BnMediaPlayerService
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 @@ class MediaPlayerService : public BnMediaPlayerService
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,