diff options
-rw-r--r-- | include/private/media/AudioTrackShared.h | 1 | ||||
-rw-r--r-- | media/codec2/sfplugin/CCodecConfig.cpp | 3 | ||||
-rw-r--r-- | media/codec2/vndk/C2Store.cpp | 16 | ||||
-rw-r--r-- | media/libaaudio/src/core/AAudioAudio.cpp | 3 | ||||
-rw-r--r-- | media/libaaudio/src/core/AudioStream.cpp | 1 | ||||
-rw-r--r-- | media/libaaudio/tests/test_various.cpp | 54 | ||||
-rw-r--r-- | media/libaudioclient/AudioTrack.cpp | 23 | ||||
-rw-r--r-- | media/libstagefright/ACodec.cpp | 5 | ||||
-rw-r--r-- | media/libstagefright/include/media/stagefright/MediaCodecConstants.h | 1 | ||||
-rw-r--r-- | media/libstagefright/rtsp/ARTPConnection.cpp | 1 | ||||
-rw-r--r-- | services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp | 5 | ||||
-rw-r--r-- | services/audiopolicy/managerdefault/AudioPolicyManager.cpp | 80 | ||||
-rw-r--r-- | services/audiopolicy/managerdefault/AudioPolicyManager.h | 44 | ||||
-rw-r--r-- | services/audiopolicy/service/AudioPolicyService.cpp | 3 | ||||
-rw-r--r-- | services/audiopolicy/service/Spatializer.cpp | 12 |
15 files changed, 195 insertions, 57 deletions
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index bd6db55669..a1e1702990 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -55,6 +55,7 @@ namespace android { // for audio_track_cblk_t::mState, to match TrackBase.h static inline constexpr int CBLK_STATE_IDLE = 0; +static inline constexpr int CBLK_STATE_ACTIVE = 6; static inline constexpr int CBLK_STATE_PAUSING = 7; /** diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp index c2751873c2..09e24bef29 100644 --- a/media/codec2/sfplugin/CCodecConfig.cpp +++ b/media/codec2/sfplugin/CCodecConfig.cpp @@ -894,6 +894,9 @@ void CCodecConfig::initializeStandardParams() { add(ConfigMapper(KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT, C2_PARAMKEY_MAX_CHANNEL_COUNT, "value") .limitTo(D::AUDIO & (D::CONFIG | D::PARAM | D::READ))); + add(ConfigMapper(KEY_MAX_OUTPUT_CHANNEL_COUNT, C2_PARAMKEY_MAX_CHANNEL_COUNT, "value") + .limitTo(D::AUDIO & (D::CONFIG | D::PARAM | D::READ))); + add(ConfigMapper(KEY_AAC_SBR_MODE, C2_PARAMKEY_AAC_SBR_MODE, "value") .limitTo(D::AUDIO & D::ENCODER & (D::CONFIG | D::PARAM | D::READ)) .withMapper([](C2Value v) -> C2Value { diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp index 1660c381b9..dfdd84d484 100644 --- a/media/codec2/vndk/C2Store.cpp +++ b/media/codec2/vndk/C2Store.cpp @@ -301,13 +301,21 @@ void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2Component std::lock_guard<std::mutex> lock(_mComponentStoreReadLock); _mComponentStore = store; } - std::shared_ptr<C2AllocatorIon> allocator; + std::shared_ptr<C2AllocatorIon> ionAllocator; { std::lock_guard<std::mutex> lock(gIonAllocatorMutex); - allocator = gIonAllocator.lock(); + ionAllocator = gIonAllocator.lock(); } - if (allocator) { - UseComponentStoreForIonAllocator(allocator, store); + if (ionAllocator) { + UseComponentStoreForIonAllocator(ionAllocator, store); + } + std::shared_ptr<C2DmaBufAllocator> dmaAllocator; + { + std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex); + dmaAllocator = gDmaBufAllocator.lock(); + } + if (dmaAllocator) { + UseComponentStoreForDmaBufAllocator(dmaAllocator, store); } } diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp index f07e66e1cc..90ff4a58bd 100644 --- a/media/libaaudio/src/core/AAudioAudio.cpp +++ b/media/libaaudio/src/core/AAudioAudio.cpp @@ -352,7 +352,8 @@ AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream* stream, { AudioStream *audioStream = convertAAudioStreamToAudioStream(stream); - return audioStream->waitForStateChange(inputState, nextState, timeoutNanoseconds); + android::sp<AudioStream> spAudioStream(audioStream); + return spAudioStream->waitForStateChange(inputState, nextState, timeoutNanoseconds); } // ============================================================ diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp index 73432af112..06f05b02ba 100644 --- a/media/libaaudio/src/core/AudioStream.cpp +++ b/media/libaaudio/src/core/AudioStream.cpp @@ -602,6 +602,7 @@ bool AudioStream::collidesWithCallback() const { void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) { ALOGD("%s() to %f", __func__, duckAndMuteVolume); + std::lock_guard<std::mutex> lock(mStreamLock); mDuckAndMuteVolume = duckAndMuteVolume; doSetVolume(); // apply this change } diff --git a/media/libaaudio/tests/test_various.cpp b/media/libaaudio/tests/test_various.cpp index cbf863fec7..b68fc7bd09 100644 --- a/media/libaaudio/tests/test_various.cpp +++ b/media/libaaudio/tests/test_various.cpp @@ -25,6 +25,7 @@ #include <gtest/gtest.h> #include <unistd.h> +#include <thread> // Callback function that does nothing. aaudio_data_callback_result_t NoopDataCallbackProc( @@ -51,6 +52,7 @@ aaudio_data_callback_result_t NoopDataCallbackProc( } constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000; +constexpr int64_t MICROS_PER_MILLISECOND = 1000; void checkReleaseThenClose(aaudio_performance_mode_t perfMode, aaudio_sharing_mode_t sharingMode, @@ -762,6 +764,58 @@ TEST(test_various, aaudio_callback_once_lowlat) { checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); } +void waitForStateChangeToClosingorClosed(AAudioStream **stream, std::atomic<bool>* isReady) +{ + *isReady = true; + aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN; + EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(*stream, + AAUDIO_STREAM_STATE_OPEN, &state, + 10000 * NANOS_PER_MILLISECOND)); + if ((state != AAUDIO_STREAM_STATE_CLOSING) && (state != AAUDIO_STREAM_STATE_CLOSED)){ + FAIL() << "ERROR - State not closing or closed. Current state: " << + AAudio_convertStreamStateToText(state); + } +} + +void testWaitForStateChangeClose(aaudio_performance_mode_t perfMode) { + AAudioStreamBuilder *aaudioBuilder = nullptr; + AAudioStream *aaudioStream = nullptr; + + ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder)); + AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode); + ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream)); + + // Verify Open State + aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN; + EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream, + AAUDIO_STREAM_STATE_UNKNOWN, &state, + 1000 * NANOS_PER_MILLISECOND)); + EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state); + + std::atomic<bool> isWaitThreadReady{false}; + + // Spawn a new thread to wait for the state change + std::thread waitThread (waitForStateChangeToClosingorClosed, &aaudioStream, + &isWaitThreadReady); + + // Wait for worker thread to be ready + while (!isWaitThreadReady) { + usleep(MICROS_PER_MILLISECOND); + } + // Sleep an additional millisecond to make sure waitForAudioThread is called + usleep(MICROS_PER_MILLISECOND); + EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream)); + waitThread.join(); +} + +TEST(test_various, wait_for_state_change_close_none) { + testWaitForStateChangeClose(AAUDIO_PERFORMANCE_MODE_NONE); +} + +TEST(test_various, wait_for_state_change_close_lowlat) { + testWaitForStateChangeClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); +} + // ************************************************************ struct WakeUpCallbackData { void wakeOther() { diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp index c2bea66309..54d186e3b3 100644 --- a/media/libaudioclient/AudioTrack.cpp +++ b/media/libaudioclient/AudioTrack.cpp @@ -972,8 +972,16 @@ bool AudioTrack::pauseAndWait(const std::chrono::milliseconds& timeout) { using namespace std::chrono_literals; + // We use atomic access here for state variables - these are used as hints + // to ensure we have ramped down audio. + const int priorState = mProxy->getState(); + const uint32_t priorPosition = mProxy->getPosition().unsignedValue(); + pause(); + // Only if we were previously active, do we wait to ramp down the audio. + if (priorState != CBLK_STATE_ACTIVE) return true; + AutoMutex lock(mLock); // offload and direct tracks do not wait because pause volume ramp is handled by hardware. if (isOffloadedOrDirect_l()) return true; @@ -981,16 +989,25 @@ bool AudioTrack::pauseAndWait(const std::chrono::milliseconds& timeout) // Wait for the track state to be anything besides pausing. // This ensures that the volume has ramped down. constexpr auto SLEEP_INTERVAL_MS = 10ms; + constexpr auto POSITION_TIMEOUT_MS = 40ms; // don't wait longer than this for position change. auto begin = std::chrono::steady_clock::now(); while (true) { - // wait for state to change + // Wait for state and position to change. + // After pause() the server state should be PAUSING, but that may immediately + // convert to PAUSED by prepareTracks before data is read into the mixer. + // Hence we check that the state is not PAUSING and that the server position + // has advanced to be a more reliable estimate that the volume ramp has completed. const int state = mProxy->getState(); + const uint32_t position = mProxy->getPosition().unsignedValue(); mLock.unlock(); // only local variables accessed until lock. auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::steady_clock::now() - begin); - if (state != CBLK_STATE_PAUSING) { - ALOGV("%s: success state:%d after %lld ms", __func__, state, elapsed.count()); + if (state != CBLK_STATE_PAUSING && + (elapsed >= POSITION_TIMEOUT_MS || position != priorPosition)) { + ALOGV("%s: success state:%d, position:%u after %lld ms" + " (prior state:%d prior position:%u)", + __func__, state, position, elapsed.count(), priorState, priorPosition); return true; } std::chrono::milliseconds remaining = timeout - elapsed; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 1e64538d89..2c8d8de226 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -2195,7 +2195,10 @@ status_t ACodec::configureCodec( } if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) { - maxOutputChannelCount = -1; + // check non AAC-specific key + if (!msg->findInt32("max-output-channel-count", &maxOutputChannelCount)) { + maxOutputChannelCount = -1; + } } if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) { // value is unknown diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h index 4237e8ccf7..c2c79dd396 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h +++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h @@ -789,6 +789,7 @@ constexpr char KEY_MAX_BIT_RATE[] = "max-bitrate"; constexpr char KEY_MAX_FPS_TO_ENCODER[] = "max-fps-to-encoder"; constexpr char KEY_MAX_HEIGHT[] = "max-height"; constexpr char KEY_MAX_INPUT_SIZE[] = "max-input-size"; +constexpr char KEY_MAX_OUTPUT_CHANNEL_COUNT[] = "max-output-channel-count"; constexpr char KEY_MAX_PTS_GAP_TO_ENCODER[] = "max-pts-gap-to-encoder"; constexpr char KEY_MAX_WIDTH[] = "max-width"; constexpr char KEY_MIME[] = "mime"; diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp index 0bd342ab01..83291f3f72 100644 --- a/media/libstagefright/rtsp/ARTPConnection.cpp +++ b/media/libstagefright/rtsp/ARTPConnection.cpp @@ -558,6 +558,7 @@ void ARTPConnection::onPollStreams() { if (n != (ssize_t)buffer->size()) { ALOGW("failed to send RTCP receiver report (%s).", n >= 0 ? "connection gone" : strerror(errno)); + ++it; continue; } diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index f3d2326601..866f1b5d15 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -549,6 +549,11 @@ status_t SwAudioOutputDescriptor::open(const audio_config_t *halConfig, audio_output_flags_t halFlags = mFlags; if ((mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) { halFlags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER); + // If no mixer config is specified for a spatializer output, default to 5.1 for proper + // configuration of the final downmixer or spatializer + if (mixerConfig == nullptr) { + lMixerConfig.channel_mask = AUDIO_CHANNEL_OUT_5POINT1; + } } ALOGV("opening output for device %s profile %p name %s", diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index e334532ebc..5a18762967 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -1372,7 +1372,8 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevices( } if (mSpatializerOutput != nullptr - && canBeSpatialized(attr, config, devices.toTypeAddrVector())) { + && canBeSpatializedInt(attr, config, + devices.toTypeAddrVector(), false /* allowCurrentOutputReconfig */)) { return mSpatializerOutput->mIoHandle; } @@ -3011,9 +3012,10 @@ status_t AudioPolicyManager::registerEffect(const effect_descriptor_t *desc, } } } - return mEffects.registerEffect(desc, io, session, id, - (strategy == streamToStrategy(AUDIO_STREAM_MUSIC) || - strategy == PRODUCT_STRATEGY_NONE)); + bool isMusicEffect = (session != AUDIO_SESSION_OUTPUT_STAGE) + && ((strategy == streamToStrategy(AUDIO_STREAM_MUSIC) + || strategy == PRODUCT_STRATEGY_NONE)); + return mEffects.registerEffect(desc, io, session, id, isMusicEffect); } status_t AudioPolicyManager::unregisterEffect(int id) @@ -4852,9 +4854,10 @@ bool AudioPolicyManager::isChannelMaskSpatialized(audio_channel_mask_t channels) } } -bool AudioPolicyManager::canBeSpatialized(const audio_attributes_t *attr, +bool AudioPolicyManager::canBeSpatializedInt(const audio_attributes_t *attr, const audio_config_t *config, - const AudioDeviceTypeAddrVector &devices) const + const AudioDeviceTypeAddrVector &devices, + bool allowCurrentOutputReconfig) const { // The caller can have the audio attributes criteria ignored by either passing a null ptr or // the AUDIO_ATTRIBUTES_INITIALIZER value. @@ -4890,7 +4893,8 @@ bool AudioPolicyManager::canBeSpatialized(const audio_attributes_t *attr, if (!isChannelMaskSpatialized(config->channel_mask)) { return false; } - if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile) { + if (!allowCurrentOutputReconfig && mSpatializerOutput != nullptr + && mSpatializerOutput->mProfile == profile) { if ((config->channel_mask & mSpatializerOutput->mMixerChannelMask) != config->channel_mask) { return false; @@ -4911,7 +4915,8 @@ void AudioPolicyManager::checkVirtualizerClientRoutes() { audio_config_base_t clientConfig = client->config(); audio_config_t config = audio_config_initializer(&clientConfig); if (desc != mSpatializerOutput - && canBeSpatialized(&attr, &config, devicesTypeAddress)) { + && canBeSpatializedInt(&attr, &config, + devicesTypeAddress, false /* allowCurrentOutputReconfig */)) { streamsToInvalidate.insert(client->stream()); } } @@ -4935,7 +4940,8 @@ status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mix config = audio_config_initializer(mixerConfig); configPtr = &config; } - if (!canBeSpatialized(attr, configPtr, devicesTypeAddress)) { + if (!canBeSpatializedInt( + attr, configPtr, devicesTypeAddress)) { ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__); return BAD_VALUE; } @@ -4958,6 +4964,7 @@ status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mix for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (!desc->isDuplicated() && desc->mProfile == profile) { + ALOGV("%s found output %d for spatializer profile", __func__, desc->mIoHandle); mSpatializerOutput = desc; break; } @@ -4977,39 +4984,29 @@ status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mix }; DeviceVector savedDevices = mSpatializerOutput->devices(); + ALOGV("%s reopening spatializer output to match channel mask %#x (current mask %#x)", + __func__, configPtr->channel_mask, mSpatializerOutput->mMixerChannelMask); + closeOutput(mSpatializerOutput->mIoHandle); - mSpatializerOutput.clear(); + //from now on mSpatializerOutput is null - const sp<SwAudioOutputDescriptor> desc = - new SwAudioOutputDescriptor(profile, mpClientInterface); - status_t status = desc->open(nullptr, mixerConfig, devices, - mEngine->getStreamTypeForAttributes(*attr), - AUDIO_OUTPUT_FLAG_SPATIALIZER, output); - if (status != NO_ERROR) { - ALOGW("%s failed opening output: status %d, output %d", __func__, status, *output); - if (*output != AUDIO_IO_HANDLE_NONE) { - desc->close(); - } + sp<SwAudioOutputDescriptor> desc = + openOutputWithProfileAndDevice(profile, devices, mixerConfig); + if (desc == nullptr) { // re open the spatializer output with previous channel mask - status_t newStatus = desc->open(nullptr, &savedMixerConfig, savedDevices, - mEngine->getStreamTypeForAttributes(*attr), - AUDIO_OUTPUT_FLAG_SPATIALIZER, output); - if (newStatus != NO_ERROR) { - if (*output != AUDIO_IO_HANDLE_NONE) { - desc->close(); - } - ALOGE("%s failed to re-open mSpatializerOutput, status %d", __func__, newStatus); + desc = openOutputWithProfileAndDevice(profile, savedDevices, &savedMixerConfig); + if (desc == nullptr) { + ALOGE("%s failed to restore mSpatializerOutput with previous config", __func__); } else { mSpatializerOutput = desc; - addOutput(*output, desc); } mPreviousOutputs = mOutputs; mpClientInterface->onAudioPortListUpdate(); *output = AUDIO_IO_HANDLE_NONE; - return status; + ALOGW("%s could not open spatializer output with requested config", __func__); + return BAD_VALUE; } mSpatializerOutput = desc; - addOutput(*output, desc); mPreviousOutputs = mOutputs; mpClientInterface->onAudioPortListUpdate(); } @@ -5682,6 +5679,9 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output) removeOutput(output); mPreviousOutputs = mOutputs; + if (closingOutput == mSpatializerOutput) { + mSpatializerOutput.clear(); + } // MSD patches may have been released to support a non-MSD direct output. Reset MSD patch if // no direct outputs are open. @@ -7222,7 +7222,8 @@ bool AudioPolicyManager::areAllActiveTracksRerouted(const sp<SwAudioOutputDescri } sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice( - const sp<IOProfile>& profile, const DeviceVector& devices) + const sp<IOProfile>& profile, const DeviceVector& devices, + const audio_config_base_t *mixerConfig) { for (const auto& device : devices) { // TODO: This should be checking if the profile supports the device combo. @@ -7232,7 +7233,7 @@ sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice( } sp<SwAudioOutputDescriptor> desc = new SwAudioOutputDescriptor(profile, mpClientInterface); audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; - status_t status = desc->open(nullptr /* halConfig */, nullptr /* mixerConfig */, devices, + status_t status = desc->open(nullptr /* halConfig */, mixerConfig, devices, AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output); if (status != NO_ERROR) { return nullptr; @@ -7262,7 +7263,7 @@ sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice( config.offload_info.channel_mask = config.channel_mask; config.offload_info.format = config.format; - status = desc->open(&config, nullptr /* mixerConfig */, devices, + status = desc->open(&config, mixerConfig, devices, AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output); if (status != NO_ERROR) { return nullptr; @@ -7270,6 +7271,7 @@ sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice( } addOutput(output, desc); + if (audio_is_remote_submix_device(deviceType) && address != "0") { sp<AudioPolicyMix> policyMix; if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix) == NO_ERROR) { @@ -7280,9 +7282,13 @@ sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice( address.string()); } - } else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) && hasPrimaryOutput()) { - // no duplicated output for direct outputs and - // outputs used by dynamic policy mixes + } else if (hasPrimaryOutput() && profile->getModule() + != mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY) + && ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) { + // no duplicated output for: + // - direct outputs + // - outputs used by dynamic policy mixes + // - outputs opened on the primary HW module audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE; //TODO: configure audio effect output stage here diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index 967aa10441..b1454fde47 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -358,7 +358,9 @@ public: virtual bool canBeSpatialized(const audio_attributes_t *attr, const audio_config_t *config, - const AudioDeviceTypeAddrVector &devices) const; + const AudioDeviceTypeAddrVector &devices) const { + return canBeSpatializedInt(attr, config, devices); + } virtual status_t getSpatializerOutput(const audio_config_base_t *config, const audio_attributes_t *attr, @@ -961,6 +963,30 @@ private: const DeviceVector &devices, audio_io_handle_t *output); + /** + * @brief Queries if some kind of spatialization will be performed if the audio playback + * context described by the provided arguments is present. + * The context is made of: + * - The audio attributes describing the playback use case. + * - The audio configuration describing the audio format, channels, sampling rate ... + * - The devices describing the sink audio device selected for playback. + * All arguments are optional and only the specified arguments are used to match against + * supported criteria. For instance, supplying no argument will tell if spatialization is + * supported or not in general. + * @param attr audio attributes describing the playback use case + * @param config audio configuration describing the audio format, channels, sample rate... + * @param devices the sink audio device selected for playback + * @param allowCurrentOutputReconfig if true, the result will be considering it is possible + * to close and reopen an existing spatializer output stream to match the requested + * criteria. If false, the criteria must be compatible with the opened sptializer + * output. + * @return true if spatialization is possible for this context, false otherwise. + */ + virtual bool canBeSpatializedInt(const audio_attributes_t *attr, + const audio_config_t *config, + const AudioDeviceTypeAddrVector &devices, + bool allowCurrentOutputReconfig = true) const; + sp<IOProfile> getSpatializerOutputProfile(const audio_config_t *config, const AudioDeviceTypeAddrVector &devices) const; @@ -1056,8 +1082,20 @@ private: bool areAllActiveTracksRerouted(const sp<SwAudioOutputDescriptor>& output); - sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice(const sp<IOProfile>& profile, - const DeviceVector& devices); + /** + * @brief Opens an output stream from the supplied IOProfile and route it to the + * supplied audio devices. If a mixer config is specified, it is forwarded to audio + * flinger. If not, a default config is derived from the output stream config. + * Also opens a duplicating output if needed and queries the audio HAL for supported + * audio profiles if the IOProfile is dynamic. + * @param[in] profile IOProfile to use as template + * @param[in] devices initial route to apply to this output stream + * @param[in] mixerConfig if not null, use this to configure the mixer + * @return an output descriptor for the newly opened stream or null in case of error. + */ + sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice( + const sp<IOProfile>& profile, const DeviceVector& devices, + const audio_config_base_t *mixerConfig = nullptr); }; diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 102b376ded..12cd136db9 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -392,7 +392,8 @@ void AudioPolicyService::doOnCheckSpatializer() audio_config_base_t config = mSpatializer->getAudioInConfig(); status_t status = mAudioPolicyManager->getSpatializerOutput(&config, &attr, &newOutput); - + ALOGV("%s currentOutput %d newOutput %d channel_mask %#x", + __func__, currentOutput, newOutput, config.channel_mask); if (status == NO_ERROR && currentOutput == newOutput) { return; } diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp index 0fdbe20239..6745005447 100644 --- a/services/audiopolicy/service/Spatializer.cpp +++ b/services/audiopolicy/service/Spatializer.cpp @@ -216,7 +216,9 @@ status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) { if (status != NO_ERROR) { return status; } - mSupportsHeadTracking = supportsHeadTracking[0]; +// Disable head tracking until head sensor activity is properly controlled. +// mSupportsHeadTracking = supportsHeadTracking[0]; + mSupportsHeadTracking = false; status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS, &mLevels); if (status != NO_ERROR) { @@ -227,12 +229,8 @@ status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) { if (status != NO_ERROR) { return status; } - status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS, + return getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS, &mChannelMasks); - if (status != NO_ERROR) { - return status; - } - return NO_ERROR; } /** Gets the channel mask, sampling rate and format set for the spatializer input. */ @@ -727,7 +725,7 @@ void Spatializer::engineCallback(int32_t event, void *user, void *info) { switch (event) { case AudioEffect::EVENT_FRAMES_PROCESSED: { int frames = info == nullptr ? 0 : *(int*)info; - ALOGD("%s frames processed %d for me %p", __func__, frames, me); + // ALOGD("%s frames processed %d for me %p", __func__, frames, me); me->postFramesProcessedMsg(frames); } break; default: |