Select haptic output when haptic-generating effect exists.
Haptic-generating effect must be attached to haptic output thread as it
requires writing haptic channels. In that case, when haptic-generating
effect exist, try to select the output that it is attatched to.
Bug: 136490803
Test: make
Change-Id: I6be84a3edac1094d6e457b3226c3930f28219167
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index c4eab30..59eee52 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -72,6 +72,9 @@
audio_io_handle_t dstOutput);
void moveEffects(const std::vector<int>& ids, audio_io_handle_t dstOutput);
+ audio_io_handle_t getIoForSession(audio_session_t sessionId,
+ const effect_uuid_t *effectType = nullptr);
+
void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
private:
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 415962a..843f5da 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -202,6 +202,19 @@
}
}
+audio_io_handle_t EffectDescriptorCollection::getIoForSession(audio_session_t sessionId,
+ const effect_uuid_t *effectType)
+{
+ for (size_t i = 0; i < size(); ++i) {
+ sp<EffectDescriptor> effect = valueAt(i);
+ if (effect->mSession == sessionId && (effectType == nullptr ||
+ memcmp(&effect->mDesc.type, effectType, sizeof(effect_uuid_t)) == 0)) {
+ return effect->mIo;
+ }
+ }
+ return AUDIO_IO_HANDLE_NONE;
+}
+
EffectDescriptorCollection EffectDescriptorCollection::getEffectsForIo(audio_io_handle_t io) const
{
EffectDescriptorCollection effects;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f05be06..559d406 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -48,6 +48,7 @@
#include <private/android_filesystem_config.h>
#include <system/audio.h>
#include <system/audio_config.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
#include "AudioPolicyManager.h"
#include <Serializer.h>
#include "TypeConverter.h"
@@ -1298,7 +1299,8 @@
// at this stage we should ignore the DIRECT flag as no direct output could be found earlier
*flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
- output = selectOutput(outputs, *flags, config->format, channelMask, config->sample_rate);
+ output = selectOutput(
+ outputs, *flags, config->format, channelMask, config->sample_rate, session);
}
ALOGW_IF((output == 0), "getOutputForDevices() could not find output for stream %d, "
"sampling rate %d, format %#x, channels %#x, flags %#x",
@@ -1471,14 +1473,26 @@
}
audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
- audio_output_flags_t flags,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- uint32_t samplingRate)
+ audio_output_flags_t flags,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ uint32_t samplingRate,
+ audio_session_t sessionId)
{
LOG_ALWAYS_FATAL_IF(!(format == AUDIO_FORMAT_INVALID || audio_is_linear_pcm(format)),
"%s called with format %#x", __func__, format);
+ // Return the output that haptic-generating attached to when 1) session id is specified,
+ // 2) haptic-generating effect exists for given session id and 3) the output that
+ // haptic-generating effect attached to is in given outputs.
+ if (sessionId != AUDIO_SESSION_NONE) {
+ audio_io_handle_t hapticGeneratingOutput = mEffects.getIoForSession(
+ sessionId, FX_IID_HAPTICGENERATOR);
+ if (outputs.indexOf(hapticGeneratingOutput) >= 0) {
+ return hapticGeneratingOutput;
+ }
+ }
+
// Flags disqualifying an output: the match must happen before calling selectOutput()
static const audio_output_flags_t kExcludedFlags = (audio_output_flags_t)
(AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
@@ -5270,7 +5284,8 @@
client->flags(),
client->config().format,
client->config().channel_mask,
- client->config().sample_rate);
+ client->config().sample_rate,
+ client->session());
if (newOutput != srcOut) {
invalidate = true;
break;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index b588f89..201abc6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -608,7 +608,8 @@
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
audio_format_t format = AUDIO_FORMAT_INVALID,
audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE,
- uint32_t samplingRate = 0);
+ uint32_t samplingRate = 0,
+ audio_session_t sessionId = AUDIO_SESSION_NONE);
// samplingRate, format, channelMask are in/out and so may be modified
sp<IOProfile> getInputProfile(const sp<DeviceDescriptor> & device,
uint32_t& samplingRate,