Revert "audio policy: concurrent capture"
This reverts commit 4c1ef4b64d113be6ee1106375bd10cdc643e80d8.
Reason for revert: b/120588242
Bug: 120588242
Change-Id: Iac41f371cb739c54d5ce519232688bebe2285c72
Test: Launch QSB and capture from mic icon
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 1b088bb..6ec6a76 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1876,38 +1876,7 @@
}
if (!profile->canOpenNewIo()) {
- for (size_t i = 0; i < mInputs.size(); ) {
- sp <AudioInputDescriptor> desc = mInputs.valueAt(i);
- if (desc->mProfile != profile) {
- continue;
- }
- // if sound trigger, reuse input if used by other sound trigger on same session
- // else
- // reuse input if active client app is not in IDLE state
- //
- RecordClientVector clients = desc->clientsList();
- bool doClose = false;
- for (const auto& client : clients) {
- if (isSoundTrigger != client->isSoundTrigger()) {
- continue;
- }
- if (client->isSoundTrigger()) {
- if (session == client->session()) {
- return desc->mIoHandle;
- }
- continue;
- }
- if (client->active() && client->appState() != APP_STATE_IDLE) {
- return desc->mIoHandle;
- }
- doClose = true;
- }
- if (doClose) {
- closeInput(desc->mIoHandle);
- } else {
- i++;
- }
- }
+ return AUDIO_IO_HANDLE_NONE;
}
sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile, mpClientInterface);
@@ -1948,8 +1917,55 @@
return input;
}
-status_t AudioPolicyManager::startInput(audio_port_handle_t portId)
+//static
+bool AudioPolicyManager::isConcurrentSource(audio_source_t source)
{
+ return (source == AUDIO_SOURCE_HOTWORD) ||
+ (source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
+ (source == AUDIO_SOURCE_FM_TUNER);
+}
+
+// FIXME: remove when concurrent capture is ready. This is a hack to work around bug b/63083537.
+bool AudioPolicyManager::soundTriggerSupportsConcurrentCapture() {
+ if (!mHasComputedSoundTriggerSupportsConcurrentCapture) {
+ bool soundTriggerSupportsConcurrentCapture = false;
+ unsigned int numModules = 0;
+ struct sound_trigger_module_descriptor* nModules = NULL;
+
+ status_t status = SoundTrigger::listModules(nModules, &numModules);
+ if (status == NO_ERROR && numModules != 0) {
+ nModules = (struct sound_trigger_module_descriptor*) calloc(
+ numModules, sizeof(struct sound_trigger_module_descriptor));
+ if (nModules == NULL) {
+ // We failed to malloc the buffer, so just say no for now, and hope that we have more
+ // ram the next time this function is called.
+ ALOGE("Failed to allocate buffer for module descriptors");
+ return false;
+ }
+
+ status = SoundTrigger::listModules(nModules, &numModules);
+ if (status == NO_ERROR) {
+ soundTriggerSupportsConcurrentCapture = true;
+ for (size_t i = 0; i < numModules; ++i) {
+ soundTriggerSupportsConcurrentCapture &=
+ nModules[i].properties.concurrent_capture;
+ }
+ }
+ free(nModules);
+ }
+ mSoundTriggerSupportsConcurrentCapture = soundTriggerSupportsConcurrentCapture;
+ mHasComputedSoundTriggerSupportsConcurrentCapture = true;
+ }
+ return mSoundTriggerSupportsConcurrentCapture;
+}
+
+
+status_t AudioPolicyManager::startInput(audio_port_handle_t portId,
+ bool silenced,
+ concurrency_type__mask_t *concurrency)
+{
+ *concurrency = API_INPUT_CONCURRENCY_NONE;
+
ALOGV("%s portId %d", __FUNCTION__, portId);
sp<AudioInputDescriptor> inputDesc = mInputs.getInputForClient(portId);
@@ -1966,16 +1982,106 @@
audio_session_t session = client->session();
- ALOGV("%s input:%d, session:%d)", __FUNCTION__, input, session);
+ ALOGV("%s input:%d, session:%d, silenced:%d, concurrency:%d)",
+ __FUNCTION__, input, session, silenced, *concurrency);
- Vector<sp<AudioInputDescriptor>> activeInputs = mInputs.getActiveInputs();
+ if (!is_virtual_input_device(inputDesc->mDevice)) {
+ if (mCallTxPatch != 0 &&
+ inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
+ ALOGW("startInput(%d) failed: call in progress", input);
+ *concurrency |= API_INPUT_CONCURRENCY_CALL;
+ return INVALID_OPERATION;
+ }
- status_t status = inputDesc->start();
- if (status != NO_ERROR) {
- return status;
+ Vector<sp<AudioInputDescriptor>> activeInputs = mInputs.getActiveInputs();
+
+ // If a UID is idle and records silence and another not silenced recording starts
+ // from another UID (idle or active) we stop the current idle UID recording in
+ // favor of the new one - "There can be only one" TM
+ if (!silenced) {
+ for (const auto& activeDesc : activeInputs) {
+ if ((activeDesc->getAudioPort()->getFlags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
+ activeDesc->getId() == inputDesc->getId()) {
+ continue;
+ }
+
+ RecordClientVector activeClients = activeDesc->clientsList(true /*activeOnly*/);
+ for (const auto& activeClient : activeClients) {
+ if (activeClient->isSilenced()) {
+ closeClient(activeClient->portId());
+ ALOGV("%s client %d stopping silenced client %d", __FUNCTION__,
+ portId, activeClient->portId());
+ activeInputs = mInputs.getActiveInputs();
+ }
+ }
+ }
+ }
+
+ for (const auto& activeDesc : activeInputs) {
+ if ((client->flags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
+ activeDesc->getId() == inputDesc->getId()) {
+ continue;
+ }
+
+ audio_source_t activeSource = activeDesc->inputSource(true);
+ if (client->source() == AUDIO_SOURCE_HOTWORD) {
+ if (activeSource == AUDIO_SOURCE_HOTWORD) {
+ if (activeDesc->hasPreemptedSession(session)) {
+ ALOGW("%s input %d failed for HOTWORD: "
+ "other input %d already started for HOTWORD", __FUNCTION__,
+ input, activeDesc->mIoHandle);
+ *concurrency |= API_INPUT_CONCURRENCY_HOTWORD;
+ return INVALID_OPERATION;
+ }
+ } else {
+ ALOGV("%s input %d failed for HOTWORD: other input %d already started",
+ __FUNCTION__, input, activeDesc->mIoHandle);
+ *concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
+ return INVALID_OPERATION;
+ }
+ } else {
+ if (activeSource != AUDIO_SOURCE_HOTWORD) {
+ ALOGW("%s input %d failed: other input %d already started", __FUNCTION__,
+ input, activeDesc->mIoHandle);
+ *concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
+ return INVALID_OPERATION;
+ }
+ }
+ }
+
+ // We only need to check if the sound trigger session supports concurrent capture if the
+ // input is also a sound trigger input. Otherwise, we should preempt any hotword stream
+ // that's running.
+ const bool allowConcurrentWithSoundTrigger =
+ inputDesc->isSoundTrigger() ? soundTriggerSupportsConcurrentCapture() : false;
+
+ // if capture is allowed, preempt currently active HOTWORD captures
+ for (const auto& activeDesc : activeInputs) {
+ if (allowConcurrentWithSoundTrigger && activeDesc->isSoundTrigger()) {
+ continue;
+ }
+ RecordClientVector activeHotwordClients =
+ activeDesc->clientsList(true, AUDIO_SOURCE_HOTWORD);
+ if (activeHotwordClients.size() > 0) {
+ SortedVector<audio_session_t> sessions = activeDesc->getPreemptedSessions();
+
+ for (const auto& activeClient : activeHotwordClients) {
+ *concurrency |= API_INPUT_CONCURRENCY_PREEMPT;
+ sessions.add(activeClient->session());
+ closeClient(activeClient->portId());
+ ALOGV("%s input %d for HOTWORD preempting HOTWORD input %d", __FUNCTION__,
+ input, activeDesc->mIoHandle);
+ }
+
+ inputDesc->setPreemptedSessions(sessions);
+ }
+ }
}
- // increment activity count before calling getNewInputDevice() below as only active sessions
+ // Make sure we start with the correct silence state
+ client->setSilenced(silenced);
+
+ // increment activity count before calling getNewInputDevice() below as only active sessions
// are considered for device selection
inputDesc->setClientActive(client, true);
@@ -1984,6 +2090,12 @@
audio_devices_t device = getNewInputDevice(inputDesc);
setInputDevice(input, device, true /* force */);
+ status_t status = inputDesc->start();
+ if (status != NO_ERROR) {
+ inputDesc->setClientActive(client, false);
+ return status;
+ }
+
if (inputDesc->activeCount() == 1) {
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((inputDesc->mPolicyMix != NULL)
@@ -3232,7 +3344,7 @@
SortedVector<audio_io_handle_t> inputsToClose;
for (size_t i = 0; i < mInputs.size(); i++) {
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(i);
- if (affectedSources.indexOf(inputDesc->source()) >= 0) {
+ if (affectedSources.indexOf(inputDesc->inputSource()) >= 0) {
inputsToClose.add(inputDesc->mIoHandle);
}
}
@@ -3609,15 +3721,16 @@
void AudioPolicyManager::setAppState(uid_t uid, app_state_t state)
{
Vector<sp<AudioInputDescriptor> > activeInputs = mInputs.getActiveInputs();
+ bool silenced = state == APP_STATE_IDLE;
- ALOGV("%s(uid:%d, state:%d)", __func__, uid, state);
+ ALOGV("AudioPolicyManager:setRecordSilenced(uid:%d, silenced:%d)", uid, silenced);
for (size_t i = 0; i < activeInputs.size(); i++) {
sp<AudioInputDescriptor> activeDesc = activeInputs[i];
RecordClientVector clients = activeDesc->clientsList(true /*activeOnly*/);
for (const auto& client : clients) {
if (uid == client->uid()) {
- client->setAppState(state);
+ client->setSilenced(silenced);
}
}
}
@@ -3727,7 +3840,8 @@
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false),
- mMusicEffectOutput(AUDIO_IO_HANDLE_NONE)
+ mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
+ mHasComputedSoundTriggerSupportsConcurrentCapture(false)
{
}
@@ -4780,7 +4894,7 @@
// If we are not in call and no client is active on this input, this methods returns
// AUDIO_DEVICE_NONE, causing the patch on the input stream to be released.
- audio_source_t source = inputDesc->source();
+ audio_source_t source = inputDesc->getHighestPrioritySource(true /*activeOnly*/);
if (source == AUDIO_SOURCE_DEFAULT && isInCall()) {
source = AUDIO_SOURCE_VOICE_COMMUNICATION;
}
@@ -5119,6 +5233,20 @@
}
installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
}
+
+ // inform all input as well
+ for (size_t i = 0; i < mInputs.size(); i++) {
+ const sp<AudioInputDescriptor> inputDescriptor = mInputs.valueAt(i);
+ if (!is_virtual_input_device(inputDescriptor->mDevice)) {
+ AudioParameter inputCmd = AudioParameter();
+ ALOGV("%s: inform input %d of device:%d", __func__,
+ inputDescriptor->mIoHandle, device);
+ inputCmd.addInt(String8(AudioParameter::keyRouting),device);
+ mpClientInterface->setParameters(inputDescriptor->mIoHandle,
+ inputCmd.toString(),
+ delayMs);
+ }
+ }
}
// update stream volumes according to new device