summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/AudioPolicyService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger/AudioPolicyService.cpp')
-rw-r--r--services/audioflinger/AudioPolicyService.cpp158
1 files changed, 127 insertions, 31 deletions
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 2706880..35e816b 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,7 +51,7 @@ static const char kCmdDeadlockedString[] = "AudioPolicyService command thread ma
static const int kDumpLockRetries = 50;
static const int kDumpLockSleepUs = 20000;
-static const nsecs_t kAudioCommandTimeout = 3000000000; // 3 seconds
+static const nsecs_t kAudioCommandTimeout = 3000000000LL; // 3 seconds
namespace {
extern struct audio_policy_service_ops aps_ops;
@@ -68,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)
@@ -222,15 +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()");
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,
@@ -253,6 +257,15 @@ status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
return NO_INIT;
}
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);
}
@@ -263,6 +276,12 @@ void AudioPolicyService::releaseOutput(audio_io_handle_t output)
return;
}
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);
}
@@ -277,9 +296,14 @@ 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,
@@ -289,7 +313,10 @@ audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource,
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;
}
@@ -638,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;
}
@@ -647,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();
@@ -656,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()
@@ -735,6 +759,32 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
}
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:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -746,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");
@@ -890,17 +940,45 @@ status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume
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());
}
@@ -942,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: {
@@ -953,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:
@@ -975,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",
@@ -1055,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
// ----------------------------------------------------------------------------
@@ -1387,7 +1482,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) {
@@ -1395,7 +1491,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,