diff options
Diffstat (limited to 'services/audioflinger/AudioPolicyService.cpp')
-rw-r--r-- | services/audioflinger/AudioPolicyService.cpp | 204 |
1 files changed, 160 insertions, 44 deletions
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp index 8b99bd2..646a317 100644 --- a/services/audioflinger/AudioPolicyService.cpp +++ b/services/audioflinger/AudioPolicyService.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "AudioPolicyService" //#define LOG_NDEBUG 0 +#include "Configuration.h" #undef __STRICT_ANSI__ #define __STDINT_LIMITS #define __STDC_LIMIT_MACROS @@ -40,6 +41,7 @@ #include <system/audio_policy.h> #include <hardware/audio_policy.h> #include <audio_effects/audio_effects_conf.h> +#include <media/AudioParameter.h> namespace android { @@ -49,6 +51,8 @@ static const char kCmdDeadlockedString[] = "AudioPolicyService command thread ma static const int kDumpLockRetries = 50; static const int kDumpLockSleepUs = 20000; +static const nsecs_t kAudioCommandTimeout = 3000000000LL; // 3 seconds + namespace { extern struct audio_policy_service_ops aps_ops; }; @@ -66,10 +70,11 @@ AudioPolicyService::AudioPolicyService() Mutex::Autolock _l(mLock); // start tone playback thread - mTonePlaybackThread = new AudioCommandThread(String8("")); + mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this); // start audio commands thread - mAudioCommandThread = new AudioCommandThread(String8("ApmCommand")); - + mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this); + // start output activity command thread + mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this); /* instantiate the audio policy manager */ rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module); if (rc) @@ -145,7 +150,7 @@ status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device, return BAD_VALUE; } - ALOGV("setDeviceConnectionState() tid %d", gettid()); + ALOGV("setDeviceConnectionState()"); Mutex::Autolock _l(mLock); return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device, state, device_address); @@ -174,7 +179,7 @@ status_t AudioPolicyService::setPhoneState(audio_mode_t state) return BAD_VALUE; } - ALOGV("setPhoneState() tid %d", gettid()); + ALOGV("setPhoneState()"); // TODO: check if it is more appropriate to do it in platform specific policy manager AudioSystem::setMode(state); @@ -199,7 +204,7 @@ status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage, if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) { return BAD_VALUE; } - ALOGV("setForceUse() tid %d", gettid()); + ALOGV("setForceUse()"); Mutex::Autolock _l(mLock); mpAudioPolicy->set_force_use(mpAudioPolicy, usage, config); return NO_ERROR; @@ -220,14 +225,16 @@ audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - audio_output_flags_t flags) + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) { if (mpAudioPolicy == NULL) { return 0; } - ALOGV("getOutput() tid %d", gettid()); + ALOGV("getOutput()"); Mutex::Autolock _l(mLock); - return mpAudioPolicy->get_output(mpAudioPolicy, stream, samplingRate, format, channelMask, flags); + return mpAudioPolicy->get_output(mpAudioPolicy, stream, samplingRate, + format, channelMask, flags, offloadInfo); } status_t AudioPolicyService::startOutput(audio_io_handle_t output, @@ -237,7 +244,7 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output, if (mpAudioPolicy == NULL) { return NO_INIT; } - ALOGV("startOutput() tid %d", gettid()); + ALOGV("startOutput()"); Mutex::Autolock _l(mLock); return mpAudioPolicy->start_output(mpAudioPolicy, output, stream, session); } @@ -249,7 +256,16 @@ status_t AudioPolicyService::stopOutput(audio_io_handle_t output, if (mpAudioPolicy == NULL) { return NO_INIT; } - ALOGV("stopOutput() tid %d", gettid()); + ALOGV("stopOutput()"); + mOutputCommandThread->stopOutputCommand(output, stream, session); + return NO_ERROR; +} + +status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, + audio_stream_type_t stream, + int session) +{ + ALOGV("doStopOutput from tid %d", gettid()); Mutex::Autolock _l(mLock); return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session); } @@ -259,7 +275,13 @@ void AudioPolicyService::releaseOutput(audio_io_handle_t output) if (mpAudioPolicy == NULL) { return; } - ALOGV("releaseOutput() tid %d", gettid()); + ALOGV("releaseOutput()"); + mOutputCommandThread->releaseOutputCommand(output); +} + +void AudioPolicyService::doReleaseOutput(audio_io_handle_t output) +{ + ALOGV("doReleaseOutput from tid %d", gettid()); Mutex::Autolock _l(mLock); mpAudioPolicy->release_output(mpAudioPolicy, output); } @@ -274,19 +296,27 @@ audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource, return 0; } // already checked by client, but double-check in case the client wrapper is bypassed - if (uint32_t(inputSource) >= AUDIO_SOURCE_CNT) { + if (inputSource >= AUDIO_SOURCE_CNT && inputSource != AUDIO_SOURCE_HOTWORD) { return 0; } + + if ((inputSource == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) { + return 0; + } + Mutex::Autolock _l(mLock); // the audio_in_acoustics_t parameter is ignored by get_input() audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate, - format, channelMask, (audio_in_acoustics_t) 0); + format, channelMask, (audio_in_acoustics_t) 0); if (input == 0) { return input; } // create audio pre processors according to input source - ssize_t index = mInputSources.indexOfKey(inputSource); + audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ? + AUDIO_SOURCE_VOICE_RECOGNITION : inputSource; + + ssize_t index = mInputSources.indexOfKey(aliasSource); if (index < 0) { return input; } @@ -483,6 +513,15 @@ bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inP return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs); } +bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const +{ + if (mpAudioPolicy == NULL) { + return 0; + } + Mutex::Autolock _l(mLock); + return mpAudioPolicy->is_stream_active_remotely(mpAudioPolicy, stream, inPastMs); +} + bool AudioPolicyService::isSourceActive(audio_source_t source) const { if (mpAudioPolicy == NULL) { @@ -533,7 +572,7 @@ status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession, } void AudioPolicyService::binderDied(const wp<IBinder>& who) { - ALOGW("binderDied() %p, tid %d, calling pid %d", who.unsafe_get(), gettid(), + ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(), IPCThreadState::self()->getCallingPid()); } @@ -626,8 +665,9 @@ status_t AudioPolicyService::onTransact( // ----------- AudioPolicyService::AudioCommandThread implementation ---------- -AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name) - : Thread(false), mName(name) +AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name, + const wp<AudioPolicyService>& service) + : Thread(false), mName(name), mService(service) { mpToneGenerator = NULL; } @@ -635,7 +675,7 @@ AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name) AudioPolicyService::AudioCommandThread::~AudioCommandThread() { - if (mName != "" && !mAudioCommands.isEmpty()) { + if (!mAudioCommands.isEmpty()) { release_wake_lock(mName.string()); } mAudioCommands.clear(); @@ -644,11 +684,7 @@ AudioPolicyService::AudioCommandThread::~AudioCommandThread() void AudioPolicyService::AudioCommandThread::onFirstRef() { - if (mName != "") { - run(mName.string(), ANDROID_PRIORITY_AUDIO); - } else { - run("AudioCommand", ANDROID_PRIORITY_AUDIO); - } + run(mName.string(), ANDROID_PRIORITY_AUDIO); } bool AudioPolicyService::AudioCommandThread::threadLoop() @@ -697,7 +733,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() data->mIO); if (command->mWaitStatus) { command->mCond.signal(); - mWaitWorkCV.wait(mLock); + command->mCond.waitRelative(mLock, kAudioCommandTimeout); } delete data; }break; @@ -708,7 +744,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs); if (command->mWaitStatus) { command->mCond.signal(); - mWaitWorkCV.wait(mLock); + command->mCond.waitRelative(mLock, kAudioCommandTimeout); } delete data; }break; @@ -719,8 +755,34 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() command->mStatus = AudioSystem::setVoiceVolume(data->mVolume); if (command->mWaitStatus) { command->mCond.signal(); - mWaitWorkCV.wait(mLock); + command->mCond.waitRelative(mLock, kAudioCommandTimeout); + } + delete data; + }break; + case STOP_OUTPUT: { + StopOutputData *data = (StopOutputData *)command->mParam; + ALOGV("AudioCommandThread() processing stop output %d", + data->mIO); + sp<AudioPolicyService> svc = mService.promote(); + if (svc == 0) { + break; } + mLock.unlock(); + svc->doStopOutput(data->mIO, data->mStream, data->mSession); + mLock.lock(); + delete data; + }break; + case RELEASE_OUTPUT: { + ReleaseOutputData *data = (ReleaseOutputData *)command->mParam; + ALOGV("AudioCommandThread() processing release output %d", + data->mIO); + sp<AudioPolicyService> svc = mService.promote(); + if (svc == 0) { + break; + } + mLock.unlock(); + svc->doReleaseOutput(data->mIO); + mLock.lock(); delete data; }break; default: @@ -734,7 +796,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() } } // release delayed commands wake lock - if (mName != "" && mAudioCommands.isEmpty()) { + if (mAudioCommands.isEmpty()) { release_wake_lock(mName.string()); } ALOGV("AudioCommandThread() going to sleep"); @@ -827,7 +889,7 @@ status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type if (command->mWaitStatus) { command->mCond.wait(mLock); status = command->mStatus; - mWaitWorkCV.signal(); + command->mCond.signal(); } return status; } @@ -852,7 +914,7 @@ status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_hand if (command->mWaitStatus) { command->mCond.wait(mLock); status = command->mStatus; - mWaitWorkCV.signal(); + command->mCond.signal(); } return status; } @@ -873,22 +935,50 @@ status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume if (command->mWaitStatus) { command->mCond.wait(mLock); status = command->mStatus; - mWaitWorkCV.signal(); + command->mCond.signal(); } return status; } +void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output, + audio_stream_type_t stream, + int session) +{ + AudioCommand *command = new AudioCommand(); + command->mCommand = STOP_OUTPUT; + StopOutputData *data = new StopOutputData(); + data->mIO = output; + data->mStream = stream; + data->mSession = session; + command->mParam = (void *)data; + Mutex::Autolock _l(mLock); + insertCommand_l(command); + ALOGV("AudioCommandThread() adding stop output %d", output); + mWaitWorkCV.signal(); +} + +void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output) +{ + AudioCommand *command = new AudioCommand(); + command->mCommand = RELEASE_OUTPUT; + ReleaseOutputData *data = new ReleaseOutputData(); + data->mIO = output; + command->mParam = (void *)data; + Mutex::Autolock _l(mLock); + insertCommand_l(command); + ALOGV("AudioCommandThread() adding release output %d", output); + mWaitWorkCV.signal(); +} + // insertCommand_l() must be called with mLock held void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs) { ssize_t i; // not size_t because i will count down to -1 Vector <AudioCommand *> removedCommands; - - nsecs_t time = 0; command->mTime = systemTime() + milliseconds(delayMs); // acquire wake lock to make sure delayed commands are processed - if (mName != "" && mAudioCommands.isEmpty()) { + if (mAudioCommands.isEmpty()) { acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string()); } @@ -930,7 +1020,10 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *comma } else { data2->mKeyValuePairs = param2.toString(); } - time = command2->mTime; + command->mTime = command2->mTime; + // force delayMs to non 0 so that code below does not request to wait for + // command status as the command is now delayed + delayMs = 1; } break; case SET_VOLUME: { @@ -941,7 +1034,10 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *comma ALOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream); removedCommands.add(command2); - time = command2->mTime; + command->mTime = command2->mTime; + // force delayMs to non 0 so that code below does not request to wait for + // command status as the command is now delayed + delayMs = 1; } break; case START_TONE: case STOP_TONE: @@ -963,16 +1059,12 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *comma } removedCommands.clear(); - // wait for status only if delay is 0 and command time was not modified above - if (delayMs == 0 && time == 0) { + // wait for status only if delay is 0 + if (delayMs == 0) { command->mWaitStatus = true; } else { command->mWaitStatus = false; } - // update command time if modified above - if (time != 0) { - command->mTime = time; - } // insert command at the right place according to its time stamp ALOGV("inserting command: %d at index %d, num commands %d", @@ -1043,6 +1135,21 @@ int AudioPolicyService::setVoiceVolume(float volume, int delayMs) return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs); } +bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info) +{ + if (mpAudioPolicy == NULL) { + ALOGV("mpAudioPolicy == NULL"); + return false; + } + + if (mpAudioPolicy->is_offload_supported == NULL) { + ALOGV("HAL does not implement is_offload_supported"); + return false; + } + + return mpAudioPolicy->is_offload_supported(mpAudioPolicy, &info); +} + // ---------------------------------------------------------------------------- // Audio pre-processing configuration // ---------------------------------------------------------------------------- @@ -1326,6 +1433,14 @@ status_t AudioPolicyService::loadPreProcessorConfig(const char *path) loadEffects(root, effects); loadInputSources(root, effects); + // delete effects to fix memory leak. + // as effects is local var and valgrind would treat this as memory leak + // and although it only did in mediaserver init, but free it in case mediaserver reboot + size_t i; + for (i = 0; i < effects.size(); i++) { + delete effects[i]; + } + config_free(root); free(root); free(data); @@ -1375,7 +1490,8 @@ static audio_io_handle_t aps_open_output_on_module(void *service, audio_format_t *pFormat, audio_channel_mask_t *pChannelMask, uint32_t *pLatencyMs, - audio_output_flags_t flags) + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) { sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); if (af == 0) { @@ -1383,7 +1499,7 @@ static audio_io_handle_t aps_open_output_on_module(void *service, return 0; } return af->openOutput(module, pDevices, pSamplingRate, pFormat, pChannelMask, - pLatencyMs, flags); + pLatencyMs, flags, offloadInfo); } static audio_io_handle_t aps_open_dup_output(void *service, |