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
This commit is contained in:
@@ -312,7 +312,6 @@ private:
|
||||
|
||||
bool processAudioBuffer(const sp<ClientRecordThread>& thread);
|
||||
|
||||
sp<IAudioFlinger> mAudioFlinger;
|
||||
sp<IAudioRecord> mAudioRecord;
|
||||
sp<IMemory> mCblkMemory;
|
||||
sp<ClientRecordThread> mClientRecordThread;
|
||||
|
||||
@@ -383,7 +383,6 @@ private:
|
||||
|
||||
bool processAudioBuffer(const sp<AudioTrackThread>& thread);
|
||||
|
||||
sp<IAudioFlinger> mAudioFlinger;
|
||||
sp<IAudioTrack> mAudioTrack;
|
||||
sp<IMemory> mCblkMemory;
|
||||
sp<AudioTrackThread> mAudioTrackThread;
|
||||
|
||||
@@ -651,27 +651,30 @@ status_t AudioFlinger::setStreamVolume(int stream, float value)
|
||||
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 @@ float AudioFlinger::streamVolume(int stream) const
|
||||
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 @@ void AudioFlinger::handleForcedSpeakerRoute(int command)
|
||||
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 @@ status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track)
|
||||
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 @@ void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t
|
||||
|
||||
// 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 @@ AudioFlinger::MixerThread::Track::~Track()
|
||||
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()
|
||||
|
||||
@@ -501,7 +501,6 @@ private:
|
||||
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);
|
||||
|
||||
@@ -53,7 +53,7 @@ static const char* routeStrings[] =
|
||||
"EARPIECE ",
|
||||
"SPEAKER ",
|
||||
"BLUETOOTH ",
|
||||
"HEADSET "
|
||||
"HEADSET ",
|
||||
"BLUETOOTH_A2DP "
|
||||
};
|
||||
static const char* routeNone = "NONE";
|
||||
|
||||
@@ -200,7 +200,7 @@ public class AudioSystem
|
||||
* param error error code:
|
||||
* - AUDIO_STATUS_OK
|
||||
* - AUDIO_STATUS_SERVER_DIED
|
||||
* - UDIO_STATUS_ERROR
|
||||
* - AUDIO_STATUS_ERROR
|
||||
*/
|
||||
void onError(int error);
|
||||
};
|
||||
|
||||
@@ -73,7 +73,6 @@ AudioRecord::~AudioRecord()
|
||||
// Otherwise the callback thread will never exit.
|
||||
stop();
|
||||
if (mClientRecordThread != 0) {
|
||||
mCblk->cv.signal();
|
||||
mClientRecordThread->requestExitAndWait();
|
||||
mClientRecordThread.clear();
|
||||
}
|
||||
@@ -96,7 +95,7 @@ status_t AudioRecord::set(
|
||||
{
|
||||
|
||||
LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount);
|
||||
if (mAudioFlinger != 0) {
|
||||
if (mAudioRecord != 0) {
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
||||
@@ -181,7 +180,6 @@ status_t AudioRecord::set(
|
||||
|
||||
mStatus = NO_ERROR;
|
||||
|
||||
mAudioFlinger = audioFlinger;
|
||||
mAudioRecord = record;
|
||||
mCblkMemory = cblk;
|
||||
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
|
||||
@@ -293,6 +291,7 @@ status_t AudioRecord::stop()
|
||||
}
|
||||
|
||||
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 AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
||||
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 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
||||
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 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
|
||||
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;
|
||||
|
||||
@@ -92,7 +92,6 @@ AudioTrack::~AudioTrack()
|
||||
// Otherwise the callback thread will never exit.
|
||||
stop();
|
||||
if (mAudioTrackThread != 0) {
|
||||
mCblk->cv.signal();
|
||||
mAudioTrackThread->requestExitAndWait();
|
||||
mAudioTrackThread.clear();
|
||||
}
|
||||
@@ -117,7 +116,7 @@ status_t AudioTrack::set(
|
||||
|
||||
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 @@ status_t AudioTrack::set(
|
||||
|
||||
mStatus = NO_ERROR;
|
||||
|
||||
mAudioFlinger = audioFlinger;
|
||||
mAudioTrack = track;
|
||||
mCblkMemory = cblk;
|
||||
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
|
||||
@@ -357,6 +355,7 @@ void AudioTrack::stop()
|
||||
}
|
||||
|
||||
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 AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
||||
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 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
||||
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 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
|
||||
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;
|
||||
|
||||
@@ -336,7 +336,7 @@ public:
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
|
||||
remote()->transact(WAKE_UP, data, &reply);
|
||||
remote()->transact(WAKE_UP, data, &reply, IBinder::FLAG_ONEWAY);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user