Fix issue 1745312: Various cleanups in media framework
AudioTrack, AudioRecord:
- remove useless mAudioFlinger member of AudioTrack and AudioRecord.
- signal cblk.cv condition in stop() method to speed up stop completion.
- extend wait condition timeout in obtainBuffer() when waitCount is -1 to avoid waking up callback thread unnecessarily
AudioFlinger:
- remove some warnings in AudioFlinger.cpp.
- remove function AudioFlinger::MixerThread::removetrack_l() as its content is never executed.
- remove useless call to setMasterVolume in AudioFlinger::handleForcedSpeakerRoute().
- Offset VOICE_CALL stream volume to reflect actual volume that is never 0 in hardware (this fix has been made in the open source): 0.01 + v * 0.99.
AudioSystem.java:
- correct typo in comment
IAudioflinger, IAudioFlingerClient:
- make AudioFlinger binder interfaces used for callbacks ONEWAY.
AudioHardwareInterface:
- correct routeStrings[] table in AudioHardwareInteface.cpp
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 7164b78..6aa40d00 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -312,7 +312,6 @@
bool processAudioBuffer(const sp<ClientRecordThread>& thread);
- sp<IAudioFlinger> mAudioFlinger;
sp<IAudioRecord> mAudioRecord;
sp<IMemory> mCblkMemory;
sp<ClientRecordThread> mClientRecordThread;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 7645978..ba0467c 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -383,7 +383,6 @@
bool processAudioBuffer(const sp<AudioTrackThread>& thread);
- sp<IAudioFlinger> mAudioFlinger;
sp<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
sp<AudioTrackThread> mAudioTrackThread;
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index d11e13a..b56221f 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -651,27 +651,30 @@
return BAD_VALUE;
}
- mHardwareMixerThread->setStreamVolume(stream, value);
-#ifdef WITH_A2DP
- mA2dpMixerThread->setStreamVolume(stream, value);
-#endif
-
status_t ret = NO_ERROR;
if (stream == AudioSystem::VOICE_CALL ||
stream == AudioSystem::BLUETOOTH_SCO) {
-
+ float hwValue;
if (stream == AudioSystem::VOICE_CALL) {
- value = (float)AudioSystem::logToLinear(value)/100.0f;
+ hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
+ // offset value to reflect actual hardware volume that never reaches 0
+ // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
+ value = 0.01 + 0.99 * value;
} else { // (type == AudioSystem::BLUETOOTH_SCO)
- value = 1.0f;
+ hwValue = 1.0f;
}
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
- ret = mAudioHardware->setVoiceVolume(value);
+ ret = mAudioHardware->setVoiceVolume(hwValue);
mHardwareStatus = AUDIO_HW_IDLE;
}
+ mHardwareMixerThread->setStreamVolume(stream, value);
+#ifdef WITH_A2DP
+ mA2dpMixerThread->setStreamVolume(stream, value);
+#endif
+
return ret;
}
@@ -709,7 +712,14 @@
if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
return 0.0f;
}
- return mHardwareMixerThread->streamVolume(stream);
+
+ float volume = mHardwareMixerThread->streamVolume(stream);
+ // remove correction applied by setStreamVolume()
+ if (stream == AudioSystem::VOICE_CALL) {
+ volume = (volume - 0.01) / 0.99 ;
+ }
+
+ return volume;
}
bool AudioFlinger::streamMute(int stream) const
@@ -812,17 +822,12 @@
if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
- mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- mAudioHardware->setMasterVolume(0);
usleep(mHardwareMixerThread->latency()*1000);
mHardwareStatus = AUDIO_HW_SET_ROUTING;
mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
mHardwareStatus = AUDIO_HW_IDLE;
// delay track start so that audio hardware has time to siwtch routes
usleep(kStartSleepTime);
- mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume());
- mHardwareStatus = AUDIO_HW_IDLE;
}
mForcedRoute = AudioSystem::ROUTE_SPEAKER;
}
@@ -1480,18 +1485,6 @@
return status;
}
-// removeTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name)
-{
- sp<Track> t = track.promote();
- if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
- t->reset();
- deleteTrackName_l(name);
- removeActiveTrack_l(track);
- mAudioFlinger->mWaitWorkCV.broadcast();
- }
-}
-
// destroyTrack_l() must be called with AudioFlinger::mLock held
void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
{
@@ -1697,7 +1690,7 @@
// Check validity of returned pointer in case the track control block would have been corrupted.
if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
- cblk->channels == 2 && ((unsigned long)bufferStart & 3) ) {
+ (cblk->channels == 2 && ((unsigned long)bufferStart & 3))) {
LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
server %d, serverBase %d, user %d, userBase %d, channels %d",
bufferStart, bufferEnd, mBuffer, mBufferEnd,
@@ -1733,7 +1726,6 @@
wp<Track> weak(this); // never create a strong ref from the dtor
Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
mState = TERMINATED;
- mMixerThread->removeTrack_l(weak, mName);
}
void AudioFlinger::MixerThread::Track::destroy()
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index db5cc74..c7ca9ec 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -501,7 +501,6 @@
MixerThread& operator = (const MixerThread&);
status_t addTrack_l(const sp<Track>& track);
- void removeTrack_l(wp<Track> track, int name);
void destroyTrack_l(const sp<Track>& track);
int getTrackName_l();
void deleteTrackName_l(int name);
diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp
index ac76a19..cc1bd8f 100644
--- a/libs/audioflinger/AudioHardwareInterface.cpp
+++ b/libs/audioflinger/AudioHardwareInterface.cpp
@@ -53,7 +53,7 @@
"EARPIECE ",
"SPEAKER ",
"BLUETOOTH ",
- "HEADSET "
+ "HEADSET ",
"BLUETOOTH_A2DP "
};
static const char* routeNone = "NONE";
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index d0fa795..5917ab90 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -200,7 +200,7 @@
* param error error code:
* - AUDIO_STATUS_OK
* - AUDIO_STATUS_SERVER_DIED
- * - UDIO_STATUS_ERROR
+ * - AUDIO_STATUS_ERROR
*/
void onError(int error);
};
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 986f88e..1720af0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -73,7 +73,6 @@
// Otherwise the callback thread will never exit.
stop();
if (mClientRecordThread != 0) {
- mCblk->cv.signal();
mClientRecordThread->requestExitAndWait();
mClientRecordThread.clear();
}
@@ -96,7 +95,7 @@
{
LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount);
- if (mAudioFlinger != 0) {
+ if (mAudioRecord != 0) {
return INVALID_OPERATION;
}
@@ -181,7 +180,6 @@
mStatus = NO_ERROR;
- mAudioFlinger = audioFlinger;
mAudioRecord = record;
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
@@ -293,6 +291,7 @@
}
if (android_atomic_and(~1, &mActive) == 1) {
+ mCblk->cv.signal();
mAudioRecord->stop();
// the record head position will reset to 0, so if a marker is set, we need
// to activate it again
@@ -375,6 +374,7 @@
status_t result;
audio_track_cblk_t* cblk = mCblk;
uint32_t framesReq = audioBuffer->frameCount;
+ uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
audioBuffer->frameCount = 0;
audioBuffer->size = 0;
@@ -391,9 +391,9 @@
if (UNLIKELY(!waitCount))
return WOULD_BLOCK;
timeout = 0;
- result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
if (__builtin_expect(result!=NO_ERROR, false)) {
- cblk->waitTimeMs += WAIT_PERIOD_MS;
+ cblk->waitTimeMs += waitTimeMs;
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
LOGW( "obtainBuffer timed out (is the CPU pegged?) "
"user=%08x, server=%08x", cblk->user, cblk->server);
@@ -520,7 +520,7 @@
status_t err = obtainBuffer(&audioBuffer, 1);
if (err < NO_ERROR) {
if (err != TIMED_OUT) {
- LOGE("Error obtaining an audio buffer, giving up.");
+ LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
return false;
}
break;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 24f7281..289bd75 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -92,7 +92,6 @@
// Otherwise the callback thread will never exit.
stop();
if (mAudioTrackThread != 0) {
- mCblk->cv.signal();
mAudioTrackThread->requestExitAndWait();
mAudioTrackThread.clear();
}
@@ -117,7 +116,7 @@
LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
- if (mAudioFlinger != 0) {
+ if (mAudioTrack != 0) {
LOGE("Track already in use");
return INVALID_OPERATION;
}
@@ -228,7 +227,6 @@
mStatus = NO_ERROR;
- mAudioFlinger = audioFlinger;
mAudioTrack = track;
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
@@ -357,6 +355,7 @@
}
if (android_atomic_and(~1, &mActive) == 1) {
+ mCblk->cv.signal();
mAudioTrack->stop();
// Cancel loops (If we are in the middle of a loop, playback
// would not stop until loopCount reaches 0).
@@ -596,6 +595,7 @@
status_t result;
audio_track_cblk_t* cblk = mCblk;
uint32_t framesReq = audioBuffer->frameCount;
+ uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
audioBuffer->frameCount = 0;
audioBuffer->size = 0;
@@ -614,9 +614,9 @@
if (UNLIKELY(!waitCount))
return WOULD_BLOCK;
timeout = 0;
- result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
if (__builtin_expect(result!=NO_ERROR, false)) {
- cblk->waitTimeMs += WAIT_PERIOD_MS;
+ cblk->waitTimeMs += waitTimeMs;
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
// timing out when a loop has been set and we have already written upto loop end
// is a normal condition: no need to wake AudioFlinger up.
@@ -798,7 +798,7 @@
status_t err = obtainBuffer(&audioBuffer, 1);
if (err < NO_ERROR) {
if (err != TIMED_OUT) {
- LOGE("Error obtaining an audio buffer, giving up.");
+ LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
return false;
}
break;
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 5cbb25c..52bd7d4 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -336,7 +336,7 @@
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(WAKE_UP, data, &reply);
+ remote()->transact(WAKE_UP, data, &reply, IBinder::FLAG_ONEWAY);
return;
}
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 5feb11f..9d00aefb 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -43,7 +43,7 @@
Parcel data, reply;
data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
data.writeInt32((int)enabled);
- remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply);
+ remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
}
};