From eda6c364c253ba97ee45a3adeb8c2b45db1f81db Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 2 Feb 2011 09:33:30 -0800 Subject: Fix issue 3371080 Modified default volume control logic in AudioService: 1 IN_CALL volume if in video/audio chat 2 NOTIFICATION if notification is playing or was playing less than 5s ago. 3 MUSIC Modified silent mode: - now also affect MUSIC stream type - entering silent mode when VOL- hard key is pressed once while selected stream volume is already at 0 (except for VOICE_CALL stream). - exiting silent mode when pressing VOL+ hard key while in silent mode Play sound FX (audible selections, keyboard clicks) at a fixed volume. Modified audio framework: - isStreamActive() method now implemented in AudioPolicyManagerBase (previously AudioFlinger) - iStreamActive() now specifies a time window during which the stream is considered active after it actually stopped. Change-Id: I7e5a0724099450b9fc90825224180ac97322785f --- include/media/AudioSystem.h | 5 +++-- include/media/IAudioFlinger.h | 3 --- include/media/IAudioPolicyService.h | 1 + media/libmedia/AudioSystem.cpp | 17 +++++++-------- media/libmedia/IAudioFlinger.cpp | 16 -------------- media/libmedia/IAudioPolicyService.cpp | 20 +++++++++++++++++- services/audioflinger/AudioFlinger.cpp | 25 ---------------------- services/audioflinger/AudioFlinger.h | 4 ---- services/audioflinger/AudioPolicyManagerBase.cpp | 27 +++++++++++++++++------- services/audioflinger/AudioPolicyService.cpp | 9 ++++++++ services/audioflinger/AudioPolicyService.h | 5 +++-- 11 files changed, 62 insertions(+), 70 deletions(-) diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 1e29d82..03f8944 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -204,8 +204,9 @@ public: // set audio mode in audio hardware (see AudioSystem::audio_mode) static status_t setMode(int mode); - // returns true in *state if tracks are active on the specified stream - static status_t isStreamActive(int stream, bool *state); + // returns true in *state if tracks are active on the specified stream or has been active + // in the past inPastMs milliseconds + static status_t isStreamActive(int stream, bool *state, uint32_t inPastMs = 0); // set/get audio hardware parameters. The function accepts a list of parameters // key value pairs in the form: key1=value1;key2=value2;... diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index 70e505e..589f7cd 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -102,9 +102,6 @@ public: virtual status_t setMicMute(bool state) = 0; virtual bool getMicMute() const = 0; - // is any track active on this stream? - virtual bool isStreamActive(int stream) const = 0; - virtual status_t setParameters(int ioHandle, const String8& keyValuePairs) = 0; virtual String8 getParameters(int ioHandle, const String8& keys) = 0; diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 49eee59..5afceaa 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -81,6 +81,7 @@ public: int session, int id) = 0; virtual status_t unregisterEffect(int id) = 0; + virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0; }; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 1a3fcd6..9d9b3c0 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -169,15 +169,6 @@ status_t AudioSystem::setMode(int mode) return af->setMode(mode); } - -status_t AudioSystem::isStreamActive(int stream, bool* state) { - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *state = af->isStreamActive(stream); - return NO_ERROR; -} - - status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) { const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; @@ -702,6 +693,14 @@ status_t AudioSystem::unregisterEffect(int id) return aps->unregisterEffect(id); } +status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs) { + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + *state = aps->isStreamActive(stream, inPastMs); + return NO_ERROR; +} + + // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who) { diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 3a89e25..eec47c0 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -47,7 +47,6 @@ enum { SET_MODE, SET_MIC_MUTE, GET_MIC_MUTE, - IS_STREAM_ACTIVE, SET_PARAMETERS, GET_PARAMETERS, REGISTER_CLIENT, @@ -316,15 +315,6 @@ public: return reply.readInt32(); } - virtual bool isStreamActive(int stream) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(stream); - remote()->transact(IS_STREAM_ACTIVE, data, &reply); - return reply.readInt32(); - } - virtual status_t setParameters(int ioHandle, const String8& keyValuePairs) { Parcel data, reply; @@ -826,12 +816,6 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32( getMicMute() ); return NO_ERROR; } break; - case IS_STREAM_ACTIVE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int stream = data.readInt32(); - reply->writeInt32( isStreamActive(stream) ); - return NO_ERROR; - } break; case SET_PARAMETERS: { CHECK_INTERFACE(IAudioFlinger, data, reply); int ioHandle = data.readInt32(); diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 950c213..457f7ed 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -48,7 +48,8 @@ enum { GET_STRATEGY_FOR_STREAM, GET_OUTPUT_FOR_EFFECT, REGISTER_EFFECT, - UNREGISTER_EFFECT + UNREGISTER_EFFECT, + IS_STREAM_ACTIVE }; class BpAudioPolicyService : public BpInterface @@ -297,6 +298,15 @@ public: return static_cast (reply.readInt32()); } + virtual bool isStreamActive(int stream, uint32_t inPastMs) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(stream); + data.writeInt32(inPastMs); + remote()->transact(IS_STREAM_ACTIVE, data, &reply); + return reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -517,6 +527,14 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case IS_STREAM_ACTIVE: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + int stream = data.readInt32(); + uint32_t inPastMs = (uint32_t)data.readInt32(); + reply->writeInt32( isStreamActive(stream, inPastMs) ); + return NO_ERROR; + } break; + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 11ad4e4..4ec16c1 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -624,17 +624,6 @@ bool AudioFlinger::streamMute(int stream) const return mStreamTypes[stream].mute; } -bool AudioFlinger::isStreamActive(int stream) const -{ - Mutex::Autolock _l(mLock); - for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) { - if (mPlaybackThreads.valueAt(i)->isStreamActive(stream)) { - return true; - } - } - return false; -} - status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) { status_t result; @@ -1291,20 +1280,6 @@ bool AudioFlinger::PlaybackThread::streamMute(int stream) const return mStreamTypes[stream].mute; } -bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const -{ - Mutex::Autolock _l(mLock); - size_t count = mActiveTracks.size(); - for (size_t i = 0 ; i < count ; ++i) { - sp t = mActiveTracks[i].promote(); - if (t == 0) continue; - Track* const track = t.get(); - if (t->type() == stream) - return true; - } - return false; -} - // addTrack_l() must be called with ThreadBase::mLock held status_t AudioFlinger::PlaybackThread::addTrack_l(const sp& track) { diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index f0ef867..81f2eb4 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -107,8 +107,6 @@ public: virtual status_t setMicMute(bool state); virtual bool getMicMute() const; - virtual bool isStreamActive(int stream) const; - virtual status_t setParameters(int ioHandle, const String8& keyValuePairs); virtual String8 getParameters(int ioHandle, const String8& keys); @@ -579,8 +577,6 @@ private: virtual float streamVolume(int stream) const; virtual bool streamMute(int stream) const; - bool isStreamActive(int stream) const; - sp createTrack_l( const sp& client, int streamType, diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp index 2c81c34..afa9acc 100644 --- a/services/audioflinger/AudioPolicyManagerBase.cpp +++ b/services/audioflinger/AudioPolicyManagerBase.cpp @@ -312,8 +312,7 @@ void AudioPolicyManagerBase::setPhoneState(int state) // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE if (state == AudioSystem::MODE_RINGTONE && - (hwOutputDesc->mRefCount[AudioSystem::MUSIC] || - (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) { + isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { mLimitRingtoneVolume = true; } else { mLimitRingtoneVolume = false; @@ -478,6 +477,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str outputDesc->mLatency = 0; outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT); outputDesc->mRefCount[stream] = 0; + outputDesc->mStopTime[stream] = 0; output = mpClientInterface->openOutput(&outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, @@ -606,10 +606,8 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output, if (outputDesc->mRefCount[stream] > 0) { // decrement usage count of this stream on the output outputDesc->changeRefCount(stream, -1); - // store time at which the last music track was stopped - see computeVolume() - if (stream == AudioSystem::MUSIC) { - mMusicStopTime = systemTime(); - } + // store time at which the stream was stopped - see isStreamActive() + outputDesc->mStopTime[stream] = systemTime(); setOutputDevice(output, getNewDevice(output)); @@ -919,6 +917,19 @@ status_t AudioPolicyManagerBase::unregisterEffect(int id) return NO_ERROR; } +bool AudioPolicyManagerBase::isStreamActive(int stream, uint32_t inPastMs) const +{ + nsecs_t sysTime = systemTime(); + for (size_t i = 0; i < mOutputs.size(); i++) { + if (mOutputs.valueAt(i)->mRefCount[stream] != 0 || + ns2ms(sysTime - mOutputs.valueAt(i)->mStopTime[stream]) < inPastMs) { + return true; + } + } + return false; +} + + status_t AudioPolicyManagerBase::dump(int fd) { const size_t SIZE = 256; @@ -1009,7 +1020,7 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien Thread(false), #endif //AUDIO_POLICY_TEST mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), - mMusicStopTime(0), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), + mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0), mA2dpSuspended(false) { @@ -2036,6 +2047,7 @@ AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor() mRefCount[i] = 0; mCurVolume[i] = -1.0; mMuteCount[i] = 0; + mStopTime[i] = 0; } } @@ -2086,7 +2098,6 @@ uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing return refCount; } - status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd) { const size_t SIZE = 256; diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp index 46a01ad..b04672d 100644 --- a/services/audioflinger/AudioPolicyService.cpp +++ b/services/audioflinger/AudioPolicyService.cpp @@ -394,6 +394,15 @@ status_t AudioPolicyService::unregisterEffect(int id) return mpPolicyManager->unregisterEffect(id); } +bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const +{ + if (mpPolicyManager == NULL) { + return 0; + } + Mutex::Autolock _l(mLock); + return mpPolicyManager->isStreamActive(stream, inPastMs); +} + void AudioPolicyService::binderDied(const wp& who) { LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h index 558f455..54af1f1 100644 --- a/services/audioflinger/AudioPolicyService.h +++ b/services/audioflinger/AudioPolicyService.h @@ -88,6 +88,7 @@ public: int session, int id); virtual status_t unregisterEffect(int id); + virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const; virtual status_t onTransact( uint32_t code, @@ -230,8 +231,8 @@ private: status_t dumpPermissionDenial(int fd); - Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing device - // connection stated our routing + mutable Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing + // device connection state or routing AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager sp mAudioCommandThread; // audio commands thread sp mTonePlaybackThread; // tone playback thread -- cgit v1.1