Enable HapticGenerator AIDL effect
- Add Haptic and Spatializer compatible check in AudioPolicyManager
- The generated haptic samples is expected to append to the end of input
buffer which needs special handling in both effect and libaudiohal
- Fix the haptic generator effect implementation wrong parameter and add
configuration with each init_params
- Add parameter logging in HapticGenerator AIDL effect
Bug: 330686268
Test: atest --test-mapping hardware/interfaces/audio/aidl/vts:presubmit
Test: atest CtsMediaAudioTestCases
Test: HapticGenerator debug app on Pixel AIDL audio hal
Change-Id: Ia292acc54276d3ae035682ca421dc7ab7d6cff73
Merged-In: Ia292acc54276d3ae035682ca421dc7ab7d6cff73
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b251843..aae248b 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1654,12 +1654,14 @@
}
// Use the spatializer output if the content can be spatialized, no preferred mixer
- // was specified and offload or direct playback is not explicitly requested.
+ // was specified and offload or direct playback is not explicitly requested, and there is no
+ // haptic channel included in playback
*isSpatialized = false;
- if (mSpatializerOutput != nullptr
- && canBeSpatializedInt(attr, config, devices.toTypeAddrVector())
- && prefMixerConfigInfo == nullptr
- && ((*flags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0)) {
+ if (mSpatializerOutput != nullptr &&
+ canBeSpatializedInt(attr, config, devices.toTypeAddrVector()) &&
+ prefMixerConfigInfo == nullptr &&
+ ((*flags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) &&
+ checkHapticCompatibilityOnSpatializerOutput(config, session)) {
*isSpatialized = true;
return mSpatializerOutput->mIoHandle;
}
@@ -2119,7 +2121,7 @@
// matching.
if ((outputHapticChannelCount >= hapticChannelCount && format == outputDesc->getFormat() &&
samplingRate == outputDesc->getSamplingRate()) ||
- (hapticChannelCount == 0 && hasOrphanHaptic)) {
+ (outputHapticChannelCount != 0 && hasOrphanHaptic)) {
currentMatchCriteria[0] = outputHapticChannelCount;
}
@@ -6119,6 +6121,34 @@
return true;
}
+// The Spatializer output is compatible with Haptic use cases if:
+// 1. the Spatializer output thread supports Haptic, and format/sampleRate are same
+// with client if client haptic channel bits were set, or
+// 2. the Spatializer output thread does not support Haptic, and client did not ask haptic by
+// including the haptic bits or creating the HapticGenerator effect for same session.
+bool AudioPolicyManager::checkHapticCompatibilityOnSpatializerOutput(
+ const audio_config_t* config, audio_session_t sessionId) const {
+ const auto clientHapticChannel =
+ audio_channel_count_from_out_mask(config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
+ const auto threadOutputHapticChannel = audio_channel_count_from_out_mask(
+ mSpatializerOutput->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
+
+ if (threadOutputHapticChannel) {
+ // check format and sampleRate match if client haptic channel mask exist
+ if (clientHapticChannel) {
+ return mSpatializerOutput->getFormat() == config->format &&
+ mSpatializerOutput->getSamplingRate() == config->sample_rate;
+ }
+ return true;
+ } else {
+ // in the case of the Spatializer output channel mask does not have haptic channel bits, it
+ // means haptic use cases (either the client channelmask includes haptic bits, or created a
+ // HapticGenerator effect for this session) are not supported.
+ return clientHapticChannel == 0 &&
+ !mEffects.hasOrphanEffectsForSessionAndType(sessionId, FX_IID_HAPTICGENERATOR);
+ }
+}
+
void AudioPolicyManager::checkVirtualizerClientRoutes() {
std::set<audio_stream_type_t> streamsToInvalidate;
for (size_t i = 0; i < mOutputs.size(); i++) {