Merge "mediaextractor_service_fuzzer: Add signal() to handle SIGPIPE" into main
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 06a21f6..aec6523 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -712,6 +712,7 @@
case kWhatStop: {
int32_t err = thiz->onStop();
thiz->mOutputBlockPool.reset();
+ mRunning = false;
Reply(msg, &err);
break;
}
diff --git a/media/codec2/hal/client/GraphicsTracker.cpp b/media/codec2/hal/client/GraphicsTracker.cpp
index dbbabfe..f80809a 100644
--- a/media/codec2/hal/client/GraphicsTracker.cpp
+++ b/media/codec2/hal/client/GraphicsTracker.cpp
@@ -664,11 +664,10 @@
int slotId;
uint64_t outBufferAge;
- ::android::FrameEventHistoryDelta outTimestamps;
sp<Fence> fence;
::android::status_t status = igbp->dequeueBuffer(
- &slotId, &fence, width, height, format, usage, &outBufferAge, &outTimestamps);
+ &slotId, &fence, width, height, format, usage, &outBufferAge, nullptr);
if (status < ::android::OK) {
if (status == ::android::TIMED_OUT || status == ::android::WOULD_BLOCK) {
ALOGW("BQ might not be ready for dequeueBuffer()");
diff --git a/media/codec2/hal/hidl/1.0/utils/Component.cpp b/media/codec2/hal/hidl/1.0/utils/Component.cpp
index 0259d90..62f0e25 100644
--- a/media/codec2/hal/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/Component.cpp
@@ -521,7 +521,18 @@
Return<Status> Component::stop() {
InputBufferManager::unregisterFrameData(mListener);
- return static_cast<Status>(mComponent->stop());
+ Status status = static_cast<Status>(mComponent->stop());
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) {
+ if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
+ std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+ std::static_pointer_cast<C2BufferQueueBlockPool>(it->second);
+ bqPool->clearDeferredBlocks();
+ }
+ }
+ }
+ return status;
}
Return<Status> Component::reset() {
diff --git a/media/codec2/hal/hidl/1.1/utils/Component.cpp b/media/codec2/hal/hidl/1.1/utils/Component.cpp
index d34d84e..7f2c4dd 100644
--- a/media/codec2/hal/hidl/1.1/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.1/utils/Component.cpp
@@ -527,7 +527,18 @@
Return<Status> Component::stop() {
InputBufferManager::unregisterFrameData(mListener);
- return static_cast<Status>(mComponent->stop());
+ Status status = static_cast<Status>(mComponent->stop());
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) {
+ if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
+ std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+ std::static_pointer_cast<C2BufferQueueBlockPool>(it->second);
+ bqPool->clearDeferredBlocks();
+ }
+ }
+ }
+ return status;
}
Return<Status> Component::reset() {
diff --git a/media/codec2/hal/hidl/1.2/utils/Component.cpp b/media/codec2/hal/hidl/1.2/utils/Component.cpp
index f78e827..7b0aa9b 100644
--- a/media/codec2/hal/hidl/1.2/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.2/utils/Component.cpp
@@ -523,7 +523,18 @@
Return<Status> Component::stop() {
InputBufferManager::unregisterFrameData(mListener);
- return static_cast<Status>(mComponent->stop());
+ Status status = static_cast<Status>(mComponent->stop());
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) {
+ if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
+ std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+ std::static_pointer_cast<C2BufferQueueBlockPool>(it->second);
+ bqPool->clearDeferredBlocks();
+ }
+ }
+ }
+ return status;
}
Return<Status> Component::reset() {
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index ca0aabb..39aadd7 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -2633,6 +2633,15 @@
if (config->mInputSurface == nullptr
&& (property_get_bool("debug.stagefright.ccodec_delayed_params", false)
|| comp->getName().find("c2.android.") == 0)) {
+ std::vector<std::unique_ptr<C2Param>> localConfigUpdate;
+ for (const std::unique_ptr<C2Param> ¶m : configUpdate) {
+ if (param && param->coreIndex().coreIndex() == C2StreamSurfaceScalingInfo::CORE_INDEX) {
+ localConfigUpdate.push_back(C2Param::Copy(*param));
+ }
+ }
+ if (!localConfigUpdate.empty()) {
+ (void)config->setParameters(comp, localConfigUpdate, C2_MAY_BLOCK);
+ }
mChannel->setParameters(configUpdate);
} else {
sp<AMessage> outputFormat = config->mOutputFormat;
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index e7fd14f..0987da2 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -478,13 +478,25 @@
class _C2BlockPoolCache {
public:
- _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
+ _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {
+ mBqPoolDeferDeallocAfterStop = false;
+#ifdef __ANDROID_APEX__
+ bool stopHalBeforeSurface = ::android::base::GetBoolProperty(
+ "debug.codec2.stop_hal_before_surface", false);
+ if (!stopHalBeforeSurface) {
+ mBqPoolDeferDeallocAfterStop =
+ ::android::base::GetIntProperty(
+ "debug.codec2.bqpool_dealloc_after_stop", 0) != 0;
+ }
+#endif
+ }
private:
c2_status_t _createBlockPool(
C2PlatformAllocatorDesc &allocatorParam,
std::vector<std::shared_ptr<const C2Component>> components,
C2BlockPool::local_id_t poolId,
+ bool deferDeallocAfterStop,
std::shared_ptr<C2BlockPool> *pool) {
std::shared_ptr<C2AllocatorStore> allocatorStore =
GetCodec2PlatformAllocatorStore();
@@ -548,6 +560,11 @@
if (res == C2_OK) {
std::shared_ptr<C2BlockPool> ptr(
new C2BufferQueueBlockPool(allocator, poolId), deleter);
+ if (deferDeallocAfterStop) {
+ std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+ std::static_pointer_cast<C2BufferQueueBlockPool>(ptr);
+ bqPool->setDeferDeallocationAfterStop();
+ }
*pool = ptr;
mBlockPools[poolId] = ptr;
mComponents[poolId].insert(
@@ -603,7 +620,8 @@
std::vector<std::shared_ptr<const C2Component>> components,
std::shared_ptr<C2BlockPool> *pool) {
std::unique_lock lock(mMutex);
- return _createBlockPool(allocator, components, mBlockPoolSeqId++, pool);
+ return _createBlockPool(allocator, components, mBlockPoolSeqId++,
+ mBqPoolDeferDeallocAfterStop, pool);
}
@@ -638,7 +656,7 @@
C2PlatformAllocatorDesc allocator;
allocator.allocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
return _createBlockPool(
- allocator, {component}, blockPoolId, pool);
+ allocator, {component}, blockPoolId, mBqPoolDeferDeallocAfterStop, pool);
}
return C2_NOT_FOUND;
}
@@ -651,6 +669,8 @@
std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
+
+ bool mBqPoolDeferDeallocAfterStop;
};
static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
diff --git a/media/codec2/vndk/include/C2BqBufferPriv.h b/media/codec2/vndk/include/C2BqBufferPriv.h
index 320b192..1e8dd40 100644
--- a/media/codec2/vndk/include/C2BqBufferPriv.h
+++ b/media/codec2/vndk/include/C2BqBufferPriv.h
@@ -28,6 +28,24 @@
class GraphicBuffer;
} // namespace android
+/**
+ * BufferQueue based BlockPool.
+ *
+ * This creates graphic blocks from BufferQueue. BufferQueue here is HIDL-ized IGBP.
+ * HIDL-ized IGBP enables vendor HAL to call IGBP interfaces via HIDL over process boundary.
+ * HIDL-ized IGBP is called as HGBP. HGBP had been used from multiple places in android,
+ * but now this is the only place HGBP is still used.
+ *
+ * Initially there is no HGBP configured, in the case graphic blocks are allocated
+ * from gralloc directly upon \fetchGraphicBlock() requests.
+ *
+ * HGBP can be configured as null as well, in the case graphic blocks are allocated
+ * from gralloc directly upon \fetchGraphicBlock() requests.
+ *
+ * If a specific HGBP is configured, the HGBP acts as an allocator for creating graphic blocks.
+ *
+ * TODO: add more ducumentation(graphic block life-cycle, waitable object and workaounds)
+ */
class C2BufferQueueBlockPool : public C2BlockPool {
public:
C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
@@ -77,6 +95,8 @@
* is configured as nullptr, unique id which is bundled in native_handle is zero.
*
* \param producer the IGBP, which will be used to fetch blocks
+ * This could be null, in the case this blockpool will
+ * allocate backed GraphicBuffer via allocator(gralloc).
*/
virtual void configureProducer(const android::sp<HGraphicBufferProducer> &producer);
@@ -89,6 +109,8 @@
* is configured as nullptr, unique id which is bundled in native_handle is zero.
*
* \param producer the IGBP, which will be used to fetch blocks
+ * This could be null, in the case this blockpool will
+ * allocate backed GraphicBuffer via allocator(gralloc).
* \param syncMemory Shared memory for synchronization of allocation & deallocation.
* \param bqId Id of IGBP
* \param generationId Generation Id for rendering output
@@ -110,6 +132,26 @@
*/
virtual void invalidate();
+ /**
+ * Defer deallocation of cached blocks.
+ *
+ * Deallocation of cached blocks will be deferred until
+ * \clearDeferredBlocks() is called. Or a new block allocation is
+ * requested by \fetchGraphicBlock().
+ */
+ void setDeferDeallocationAfterStop();
+
+
+ /**
+ * Clear deferred blocks.
+ *
+ * Deallocation of cached blocks can be deferred by
+ * \setDeferDeallocationAfterStop().
+ * clear(deallocate) those deferred cached blocks explicitly.
+ * Use this interface, if the blockpool could be inactive indefinitely.
+ */
+ void clearDeferredBlocks();
+
private:
const std::shared_ptr<C2Allocator> mAllocator;
const local_id_t mLocalId;
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 48157c8..665f9fc 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -588,11 +588,22 @@
return C2_BAD_VALUE;
}
+ void clearDeferredBlocks_l() {
+ if (mHavingDeallocationDeferred) {
+ mHavingDeallocationDeferred = false;
+ for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
+ mBuffersWithDeallocationDeferred[i].clear();
+ }
+ }
+ }
+
public:
Impl(const std::shared_ptr<C2Allocator> &allocator)
: mInit(C2_OK), mProducerId(0), mGeneration(0),
mConsumerUsage(0), mDqFailure(0), mLastDqTs(0),
- mLastDqLogTs(0), mAllocator(allocator), mIgbpValidityToken(std::make_shared<int>(0)) {
+ mLastDqLogTs(0), mAllocator(allocator),
+ mDeferDeallocationAfterStop(false),
+ mHavingDeallocationDeferred(false), mIgbpValidityToken(std::make_shared<int>(0)) {
}
~Impl() {
@@ -634,6 +645,7 @@
}
}
if (mProducerId == 0) {
+ clearDeferredBlocks_l();
std::shared_ptr<C2GraphicAllocation> alloc;
c2_status_t err = mAllocator->newGraphicAllocation(
width, height, format, usage, &alloc);
@@ -692,6 +704,7 @@
uint32_t generation,
uint64_t usage,
bool bqInformation) {
+ bool toNullSurface = false;
std::shared_ptr<C2SurfaceSyncMemory> c2SyncMem;
if (syncHandle) {
if (!producer) {
@@ -714,6 +727,9 @@
mProducerId = producerId;
mGeneration = bqInformation ? generation : 0;
} else {
+ if (mProducer) {
+ toNullSurface = true;
+ }
mProducer = nullptr;
mProducerId = 0;
mGeneration = 0;
@@ -760,6 +776,17 @@
// old buffers should not be cancelled since the associated IGBP
// is no longer valid.
mIgbpValidityToken = std::make_shared<int>(0);
+ if (mDeferDeallocationAfterStop) {
+ if (toNullSurface) {
+ mHavingDeallocationDeferred = true;
+ for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
+ mBuffersWithDeallocationDeferred[i] = mBuffers[i];
+ }
+ }
+ }
+ }
+ if (!toNullSurface) {
+ clearDeferredBlocks_l();
}
if (mInvalidated) {
mIgbpValidityToken = std::make_shared<int>(0);
@@ -811,6 +838,16 @@
}
}
+ void setDeferDeallocationAfterStop() {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ mDeferDeallocationAfterStop = true;
+ }
+
+ void clearDeferredBlocks() {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ clearDeferredBlocks_l();
+ }
+
private:
friend struct C2BufferQueueBlockPoolData;
@@ -833,6 +870,14 @@
sp<GraphicBuffer> mBuffers[NUM_BUFFER_SLOTS];
std::weak_ptr<C2BufferQueueBlockPoolData> mPoolDatas[NUM_BUFFER_SLOTS];
+ // In order to workaround b/322731059,
+ // deallocating buffers due to stop using the current surface
+ // could be deferred until the component calling stop or a
+ // new allocation being requested.
+ bool mDeferDeallocationAfterStop;
+ bool mHavingDeallocationDeferred;
+ sp<GraphicBuffer> mBuffersWithDeallocationDeferred[NUM_BUFFER_SLOTS];
+
std::mutex mSyncMemMutex;
std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
std::shared_ptr<C2SurfaceSyncMemory> mOldMem;
@@ -1178,3 +1223,15 @@
}
}
+void C2BufferQueueBlockPool::setDeferDeallocationAfterStop() {
+ if (mImpl) {
+ mImpl->setDeferDeallocationAfterStop();
+ }
+}
+
+void C2BufferQueueBlockPool::clearDeferredBlocks() {
+ if (mImpl) {
+ mImpl->clearDeferredBlocks();
+ }
+}
+
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index a329edf..ea6fca3 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -928,6 +928,7 @@
AudioFlingerServerAdapter::AudioFlingerServerAdapter(
const sp<AudioFlingerServerAdapter::Delegate>& delegate) : mDelegate(delegate) {
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ setInheritRt(true);
}
status_t AudioFlingerServerAdapter::onTransact(uint32_t code,
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 9c4ccb8..499ec39 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1240,13 +1240,10 @@
nsec += 1000000000;
}
- if ((sec + 1) > ((time_t)(INT_MAX / mSamplingRate))) {
- mMaxSmp = sec * mSamplingRate;
- } else {
- // mSamplingRate is always > 1000
- sec = sec * 1000 + nsec / 1000000; // duration in milliseconds
- mMaxSmp = (unsigned int)(((int64_t)sec * mSamplingRate) / 1000);
- }
+ const uint64_t msec = static_cast<uint64_t>(sec) * 1000 + nsec / 1'000'000;
+ mMaxSmp = std::min(static_cast<uint64_t>(TONEGEN_INF - 1),
+ msec * mSamplingRate / 1000);
+
ALOGV("stopTone() forcing mMaxSmp to %d, total for far %" PRIu64, mMaxSmp,
mTotalSmp);
} else {
@@ -1614,14 +1611,11 @@
mpToneDesc = mpNewToneDesc;
- if (mDurationMs == -1) {
+ if (mDurationMs < 0) { // mDurationMs is signed, treat all neg numbers as INF.
mMaxSmp = TONEGEN_INF;
} else {
- if (mDurationMs > (int)(TONEGEN_INF / mSamplingRate)) {
- mMaxSmp = (mDurationMs / 1000) * mSamplingRate;
- } else {
- mMaxSmp = (mDurationMs * mSamplingRate) / 1000;
- }
+ mMaxSmp = std::min(static_cast<uint64_t>(TONEGEN_INF - 1),
+ static_cast<uint64_t>(mDurationMs) * mSamplingRate / 1000);
ALOGV("prepareWave, duration limited to %d ms", mDurationMs);
}
@@ -1652,7 +1646,8 @@
if (mpToneDesc->segments[0].duration == TONEGEN_INF) {
mNextSegSmp = TONEGEN_INF;
} else{
- mNextSegSmp = (mpToneDesc->segments[0].duration * mSamplingRate) / 1000;
+ mNextSegSmp = std::min(static_cast<uint64_t>(TONEGEN_INF - 1),
+ static_cast<uint64_t>(mpToneDesc->segments[0].duration) * mSamplingRate / 1000);
}
return true;
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 9f21404..86dd663 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -459,13 +459,17 @@
args.portConfigId = mixPortConfig.id;
const bool isOffload = isBitPositionFlagSet(
aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
+ const bool isHwAvSync = isBitPositionFlagSet(
+ aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
std::shared_ptr<OutputStreamCallbackAidl> streamCb;
if (isOffload) {
streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
}
auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
- if (isOffload) {
+ if (isOffload || isHwAvSync) {
args.offloadInfo = aidlConfig.offloadInfo;
+ }
+ if (isOffload) {
args.callback = streamCb;
}
args.bufferSizeFrames = aidlConfig.frameCount;
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.cpp b/media/libaudiohal/impl/Hal2AidlMapper.cpp
index cbade70..052522f 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.cpp
+++ b/media/libaudiohal/impl/Hal2AidlMapper.cpp
@@ -37,6 +37,7 @@
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioGainConfig;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOutputFlags;
@@ -325,8 +326,8 @@
}
status_t Hal2AidlMapper::findOrCreateDevicePortConfig(
- const AudioDevice& device, const AudioConfig* config, AudioPortConfig* portConfig,
- bool* created) {
+ const AudioDevice& device, const AudioConfig* config, const AudioGainConfig* gainConfig,
+ AudioPortConfig* portConfig, bool* created) {
if (auto portConfigIt = findPortConfig(device); portConfigIt == mPortConfigs.end()) {
auto portsIt = findPort(device);
if (portsIt == mPorts.end()) {
@@ -339,12 +340,18 @@
if (config != nullptr) {
setPortConfigFromConfig(&requestedPortConfig, *config);
}
+ if (gainConfig != nullptr) {
+ requestedPortConfig.gain = *gainConfig;
+ }
return createOrUpdatePortConfigRetry(requestedPortConfig, portConfig, created);
} else {
AudioPortConfig requestedPortConfig = portConfigIt->second;
if (config != nullptr) {
setPortConfigFromConfig(&requestedPortConfig, *config);
}
+ if (gainConfig != nullptr) {
+ requestedPortConfig.gain = *gainConfig;
+ }
if (requestedPortConfig != portConfigIt->second) {
return createOrUpdatePortConfigRetry(requestedPortConfig, portConfig, created);
@@ -447,18 +454,26 @@
requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
portConfig, created);
} else if (requestedPortConfig.ext.getTag() == Tag::device) {
- if (const auto& p = requestedPortConfig;
- p.sampleRate.has_value() && p.channelMask.has_value() &&
- p.format.has_value()) {
- AudioConfig config;
- setConfigFromPortConfig(&config, requestedPortConfig);
+ const auto& p = requestedPortConfig;
+ const bool hasAudioConfig =
+ p.sampleRate.has_value() && p.channelMask.has_value() && p.format.has_value();
+ const bool hasGainConfig = p.gain.has_value();
+ if (hasAudioConfig || hasGainConfig) {
+ AudioConfig config, *configPtr = nullptr;
+ if (hasAudioConfig) {
+ setConfigFromPortConfig(&config, requestedPortConfig);
+ configPtr = &config;
+ }
+ const AudioGainConfig* gainConfigPtr = nullptr;
+ if (hasGainConfig) gainConfigPtr = &(*(p.gain));
return findOrCreateDevicePortConfig(
- requestedPortConfig.ext.get<Tag::device>().device, &config,
+ requestedPortConfig.ext.get<Tag::device>().device, configPtr, gainConfigPtr,
portConfig, created);
} else {
+ ALOGD("%s: device port config does not have audio or gain config specified", __func__);
return findOrCreateDevicePortConfig(
requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
- portConfig, created);
+ nullptr /*gainConfig*/, portConfig, created);
}
}
ALOGW("%s: unsupported audio port config: %s",
@@ -769,7 +784,7 @@
// then find / create a patch between them, and open a stream on the mix port.
AudioPortConfig devicePortConfig;
bool created = false;
- RETURN_STATUS_IF_ERROR(findOrCreateDevicePortConfig(device, config,
+ RETURN_STATUS_IF_ERROR(findOrCreateDevicePortConfig(device, config, nullptr /*gainConfig*/,
&devicePortConfig, &created));
LOG_ALWAYS_FATAL_IF(devicePortConfig.id == 0);
if (created) {
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.h b/media/libaudiohal/impl/Hal2AidlMapper.h
index c70c8af..710b43e 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.h
+++ b/media/libaudiohal/impl/Hal2AidlMapper.h
@@ -163,6 +163,7 @@
status_t findOrCreateDevicePortConfig(
const ::aidl::android::media::audio::common::AudioDevice& device,
const ::aidl::android::media::audio::common::AudioConfig* config,
+ const ::aidl::android::media::audio::common::AudioGainConfig* gainConfig,
::aidl::android::media::audio::common::AudioPortConfig* portConfig,
bool* created);
// If the resulting 'portConfig->id' is 0, that means the config was not created,
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
index ca6ff88..7879200 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -17,6 +17,7 @@
#include <cstdint>
#include <cstring>
#include <optional>
+#include <unordered_set>
#define LOG_TAG "AidlConversionEQ"
//#define LOG_NDEBUG 0
@@ -262,10 +263,21 @@
}
case EQ_PARAM_GET_NUM_OF_PRESETS: {
Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::presets));
- const auto& presets = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ auto presets = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
aidlParam, Equalizer, equalizer, Equalizer::presets,
std::vector<Equalizer::Preset>));
- uint16_t num = presets.size();
+ // it was assumed the presets index in the range of [0, NUM_OF_PRESETS - 1], so
+ // filter out presets out of this range (one example is preset {-1, "custom"})
+ std::erase_if(presets, [](const auto& preset) { return preset.index < 0; });
+ // validate remaining indexes are unique [0, num - 1]
+ std::unordered_set<uint16_t> uniqueIndices;
+ const uint16_t num = presets.size();
+ for (const auto& preset : presets) {
+ if (preset.index >= num || 0 != uniqueIndices.count(preset.index)) {
+ return BAD_VALUE;
+ }
+ uniqueIndices.insert(preset.index);
+ }
return param.writeToValue(&num);
}
case EQ_PARAM_GET_PRESET_NAME: {
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
index 0bd6fb0..50b748e 100644
--- a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -29,6 +29,7 @@
#include <aidl/android/hardware/audio/core/BnModule.h>
#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
+#include <aidl/android/media/audio/common/AudioGainMode.h>
#include <aidl/android/media/audio/common/Int.h>
#include <utils/Log.h>
@@ -44,6 +45,8 @@
using ::aidl::android::media::audio::common::AudioDeviceType;
using ::aidl::android::media::audio::common::AudioFormatDescription;
using ::aidl::android::media::audio::common::AudioFormatType;
+using ::aidl::android::media::audio::common::AudioGainConfig;
+using ::aidl::android::media::audio::common::AudioGainMode;
using ::aidl::android::media::audio::common::AudioIoFlags;
using ::aidl::android::media::audio::common::AudioPort;
using ::aidl::android::media::audio::common::AudioPortConfig;
@@ -179,6 +182,11 @@
primaryInMix.profiles = standardPcmAudioProfiles;
c.ports.push_back(primaryInMix);
+ AudioPort speakerOutDevice = createPort(c.nextPortId++, "Speaker", 0, false,
+ createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0));
+ speakerOutDevice.profiles = standardPcmAudioProfiles;
+ c.ports.push_back(speakerOutDevice);
+
AudioPort btOutDevice =
createPort(c.nextPortId++, "BT A2DP Out", 0, false,
createPortDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
@@ -209,6 +217,13 @@
getAudioPatches(&result);
return result;
}
+ std::optional<AudioPortConfig> getPortConfig(int32_t id) {
+ auto iter = findById<AudioPortConfig>(mConfig.portConfigs, id);
+ if (iter != mConfig.portConfigs.end()) {
+ return *iter;
+ }
+ return std::nullopt;
+ }
private:
ndk::ScopedAStatus setModuleDebug(
@@ -646,6 +661,19 @@
}
} // namespace aidl::android::hardware::audio::core
+namespace aidl::android::media::audio::common {
+template <typename P>
+std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
+ std::ostream&>
+operator<<(std::ostream& os, const P& p) {
+ return os << p.toString();
+}
+template <typename E>
+std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
+ return os << toString(e);
+}
+} // namespace aidl::android::media::audio::common
+
using namespace android;
namespace {
@@ -1214,3 +1242,55 @@
EXPECT_EQ(std::vector<int32_t>{backMicPortConfig.id}, patchIt->sourcePortConfigIds);
EXPECT_EQ(std::vector<int32_t>{mixPortConfig.id}, patchIt->sinkPortConfigIds);
}
+
+TEST_F(Hal2AidlMapperTest, SetAudioPortConfigGainChangeExistingPortConfig) {
+ // First set config, then update gain.
+ AudioPortConfig speakerPortConfig;
+ speakerPortConfig.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
+ speakerPortConfig.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO);
+ speakerPortConfig.format =
+ AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
+ speakerPortConfig.sampleRate = ::aidl::android::media::audio::common::Int(48000);
+ AudioPortConfig resultingPortConfig;
+ ASSERT_EQ(OK,
+ mMapper->setPortConfig(speakerPortConfig, std::set<int32_t>(), &resultingPortConfig));
+ EXPECT_NE(0, resultingPortConfig.id);
+ EXPECT_NE(0, resultingPortConfig.portId);
+
+ AudioPortConfig gainUpdate;
+ gainUpdate.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
+ AudioGainConfig gainConfig{.index = -1,
+ .mode = 1 << static_cast<int>(AudioGainMode::JOINT),
+ .channelMask = AudioChannelLayout{},
+ .values = std::vector<int32_t>{-3200},
+ .rampDurationMs = 0};
+ gainUpdate.gain = gainConfig;
+ AudioPortConfig resultingGainUpdate;
+ ASSERT_EQ(OK, mMapper->setPortConfig(gainUpdate, std::set<int32_t>(), &resultingGainUpdate));
+ EXPECT_EQ(resultingPortConfig.id, resultingGainUpdate.id);
+ auto updatedPortConfig = mModule->getPortConfig(resultingGainUpdate.id);
+ ASSERT_TRUE(updatedPortConfig.has_value());
+ ASSERT_TRUE(updatedPortConfig->gain.has_value());
+ EXPECT_EQ(gainConfig, updatedPortConfig->gain);
+}
+
+TEST_F(Hal2AidlMapperTest, SetAudioPortConfigGainChangeFromScratch) {
+ // Set gain as the first operation, the HAL should suggest the rest of the configuration.
+ AudioPortConfig gainSet;
+ gainSet.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
+ AudioGainConfig gainConfig{.index = -1,
+ .mode = 1 << static_cast<int>(AudioGainMode::JOINT),
+ .channelMask = AudioChannelLayout{},
+ .values = std::vector<int32_t>{-3200},
+ .rampDurationMs = 0};
+ gainSet.gain = gainConfig;
+ AudioPortConfig resultingPortConfig;
+ ASSERT_EQ(OK, mMapper->setPortConfig(gainSet, std::set<int32_t>(), &resultingPortConfig));
+ EXPECT_NE(0, resultingPortConfig.id);
+ EXPECT_NE(0, resultingPortConfig.portId);
+ auto portConfig = mModule->getPortConfig(resultingPortConfig.id);
+ ASSERT_TRUE(portConfig.has_value());
+ ASSERT_TRUE(portConfig->gain.has_value());
+ EXPECT_EQ(gainConfig, portConfig->gain);
+}
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index fff2feb..d5e3cf7 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -185,7 +185,6 @@
}
RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
- mEnabled = false;
return limitLevel();
}
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 72785d5..4e4aa75 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -882,7 +882,6 @@
inline constexpr int32_t CRYPTO_MODE_AES_CBC = 2;
inline constexpr int32_t CRYPTO_MODE_AES_CTR = 1;
inline constexpr int32_t CRYPTO_MODE_UNENCRYPTED = 0;
-inline constexpr int32_t INFO_OUTPUT_BUFFERS_CHANGED = -3;
inline constexpr int32_t INFO_OUTPUT_FORMAT_CHANGED = -2;
inline constexpr int32_t INFO_TRY_AGAIN_LATER = -1;
inline constexpr int32_t VIDEO_SCALING_MODE_SCALE_TO_FIT = 1;
diff --git a/media/module/bufferpool/2.0/AccessorImpl.cpp b/media/module/bufferpool/2.0/AccessorImpl.cpp
index 202d803..b9483bf 100644
--- a/media/module/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/module/bufferpool/2.0/AccessorImpl.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "BufferPoolAccessor2.0"
//#define LOG_NDEBUG 0
+#include <android-base/no_destructor.h>
+
#include <sys/types.h>
#include <stdint.h>
#include <time.h>
@@ -147,7 +149,25 @@
#endif
static constexpr uint32_t kSeqIdMax = 0x7fffffff;
-uint32_t Accessor::Impl::sSeqId = time(nullptr) & kSeqIdMax;
+
+Accessor::Impl::ConnectionIdGenerator::ConnectionIdGenerator() {
+ mSeqId = static_cast<uint32_t>(time(nullptr) & kSeqIdMax);
+ mPid = static_cast<int32_t>(getpid());
+}
+
+ConnectionId Accessor::Impl::ConnectionIdGenerator::getConnectionId() {
+ uint32_t seq;
+ {
+ std::lock_guard<std::mutex> l(mLock);
+ seq = mSeqId;
+ if (mSeqId == kSeqIdMax) {
+ mSeqId = 0;
+ } else {
+ ++mSeqId;
+ }
+ }
+ return (int64_t)mPid << 32 | seq | kSeqIdVndkBit;
+}
Accessor::Impl::Impl(
const std::shared_ptr<BufferPoolAllocator> &allocator)
@@ -163,13 +183,14 @@
uint32_t *pMsgId,
const StatusDescriptor** statusDescPtr,
const InvalidationDescriptor** invDescPtr) {
+ static ::android::base::NoDestructor<ConnectionIdGenerator> sConIdGenerator;
sp<Connection> newConnection = new Connection();
ResultStatus status = ResultStatus::CRITICAL_ERROR;
{
std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
if (newConnection) {
int32_t pid = getpid();
- ConnectionId id = (int64_t)pid << 32 | sSeqId | kSeqIdVndkBit;
+ ConnectionId id = sConIdGenerator->getConnectionId();
status = mBufferPool.mObserver.open(id, statusDescPtr);
if (status == ResultStatus::OK) {
newConnection->initialize(accessor, id);
@@ -179,11 +200,6 @@
mBufferPool.mConnectionIds.insert(id);
mBufferPool.mInvalidationChannel.getDesc(invDescPtr);
mBufferPool.mInvalidation.onConnect(id, observer);
- if (sSeqId == kSeqIdMax) {
- sSeqId = 0;
- } else {
- ++sSeqId;
- }
}
}
diff --git a/media/module/bufferpool/2.0/AccessorImpl.h b/media/module/bufferpool/2.0/AccessorImpl.h
index 3d39941..2366177 100644
--- a/media/module/bufferpool/2.0/AccessorImpl.h
+++ b/media/module/bufferpool/2.0/AccessorImpl.h
@@ -77,7 +77,14 @@
private:
// ConnectionId = pid : (timestamp_created + seqId)
// in order to guarantee uniqueness for each connection
- static uint32_t sSeqId;
+ struct ConnectionIdGenerator {
+ int32_t mPid;
+ uint32_t mSeqId;
+ std::mutex mLock;
+
+ ConnectionIdGenerator();
+ ConnectionId getConnectionId();
+ };
const std::shared_ptr<BufferPoolAllocator> mAllocator;
diff --git a/media/module/bufferpool/2.0/Android.bp b/media/module/bufferpool/2.0/Android.bp
index bdab103..c40603c 100644
--- a/media/module/bufferpool/2.0/Android.bp
+++ b/media/module/bufferpool/2.0/Android.bp
@@ -21,6 +21,9 @@
export_include_dirs: [
"include",
],
+ header_libs: [
+ "libbase_headers",
+ ],
shared_libs: [
"libcutils",
"libfmq",
diff --git a/media/module/foundation/tests/AData_test.cpp b/media/module/foundation/tests/AData_test.cpp
index 2628a47..87b69a6 100644
--- a/media/module/foundation/tests/AData_test.cpp
+++ b/media/module/foundation/tests/AData_test.cpp
@@ -392,7 +392,7 @@
EXPECT_EQ(2L, _shared.use_count()); // still both u and _shared contains the object
EXPECT_TRUE(u.clear());
- EXPECT_TRUE(_shared.unique()); // now only _shared contains the object
+ EXPECT_EQ(1L, _shared.use_count()); // now only _shared contains the object
EXPECT_TRUE(u.set(_constShared));
EXPECT_EQ(2L, _constShared.use_count()); // even though it is const, we can add a use count
@@ -591,7 +591,7 @@
EXPECT_EQ(2L, _shared.use_count()); // still both u and _shared contains the object
EXPECT_TRUE(u.clear());
- EXPECT_TRUE(_shared.unique()); // now only _shared contains the object
+ EXPECT_EQ(1L, _shared.use_count()); // now only _shared contains the object
EXPECT_TRUE(u.set(_constShared));
EXPECT_EQ(2L, _constShared.use_count()); // even though it is const, we can add a use count
diff --git a/media/utils/tests/static_string_view_tests.cpp b/media/utils/tests/static_string_view_tests.cpp
index c00de68..1dd2370 100644
--- a/media/utils/tests/static_string_view_tests.cpp
+++ b/media/utils/tests/static_string_view_tests.cpp
@@ -37,14 +37,12 @@
// const std::array<char,2> nonstatic = {'a', 'b'};
// static_assert(can_assign<nonstatic>::value == false);
static std::array<char, 2> nonconst = {'a', 'b'};
- static const std::array<char, 2> nonconstexpr = {'a', 'b'};
static constexpr std::array<int, 2> nonchar = {1, 2};
static constexpr size_t nonarray = 2;
static_assert(CanCreate<nonconst>::value == false);
static_assert(CanCreate<nonarray>::value == false);
static_assert(CanCreate<nonchar>::value == false);
- static_assert(CanCreate<nonconstexpr>::value == false);
static constexpr std::array<char, 2> scoped = {'a', 'b'};
constexpr StaticStringView Ticket1 = StaticStringView::create<global>();
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index c8b0aa1..adff1b5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3922,7 +3922,8 @@
patchRecord->bufferSize(),
outputFlags,
0ns /* timeout */,
- frameCountToBeReady);
+ frameCountToBeReady,
+ track->getSpeed());
status = patchTrack->initCheck();
if (status != NO_ERROR) {
ALOGE("Secondary output patchTrack init failed: %d", status);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index ae55329..b407092 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1699,6 +1699,7 @@
{
ALOGV("constructor %p client %p", this, client.get());
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ setInheritRt(true);
if (client == 0) {
return;
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
index 2302e13..0d8c01e 100644
--- a/services/audioflinger/IAfTrack.h
+++ b/services/audioflinger/IAfTrack.h
@@ -571,10 +571,11 @@
size_t bufferSize,
audio_output_flags_t flags,
const Timeout& timeout = {},
- size_t frameCountToBeReady = 1 /** Default behaviour is to start
+ size_t frameCountToBeReady = 1, /** Default behaviour is to start
* as soon as possible to have
* the lowest possible latency
- * even if it might glitch. */);
+ * even if it might glitch. */
+ float speed = 1.0f);
};
class IAfPatchRecord : public virtual IAfRecordTrack, public virtual IAfPatchTrackBase {
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 4333cc8..f57470f 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -646,7 +646,8 @@
tempRecordTrack->bufferSize(),
outputFlags,
{} /*timeout*/,
- frameCountToBeReady);
+ frameCountToBeReady,
+ 1.0f);
status = mPlayback.checkTrack(tempPatchTrack.get());
if (status != NO_ERROR) {
return status;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index b4cb805..15c786e 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -490,10 +490,11 @@
size_t bufferSize,
audio_output_flags_t flags,
const Timeout& timeout = {},
- size_t frameCountToBeReady = 1 /** Default behaviour is to start
+ size_t frameCountToBeReady = 1, /** Default behaviour is to start
* as soon as possible to have
* the lowest possible latency
- * even if it might glitch. */);
+ * even if it might glitch. */
+ float speed = 1.0f);
~PatchTrack() override;
size_t framesReady() const final;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0766a0d..2b17e92 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -691,6 +691,10 @@
}
// When Thread::requestExitAndWait is made virtual and this method is renamed to
// "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
+
+ // For TimeCheck: track waiting on the thread join of getTid().
+ audio_utils::mutex::scoped_join_wait_check sjw(getTid());
+
requestExitAndWait();
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 77abaf6..a34f6d7 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -389,6 +389,7 @@
mTrack(track)
{
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ setInheritRt(true);
}
TrackHandle::~TrackHandle() {
@@ -2441,10 +2442,11 @@
size_t bufferSize,
audio_output_flags_t flags,
const Timeout& timeout,
- size_t frameCountToBeReady /** Default behaviour is to start
+ size_t frameCountToBeReady, /** Default behaviour is to start
* as soon as possible to have
* the lowest possible latency
- * even if it might glitch. */)
+ * even if it might glitch. */
+ float speed)
{
return sp<PatchTrack>::make(
playbackThread,
@@ -2457,7 +2459,8 @@
bufferSize,
flags,
timeout,
- frameCountToBeReady);
+ frameCountToBeReady,
+ speed);
}
PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
@@ -2470,17 +2473,26 @@
size_t bufferSize,
audio_output_flags_t flags,
const Timeout& timeout,
- size_t frameCountToBeReady)
+ size_t frameCountToBeReady,
+ float speed)
: Track(playbackThread, NULL, streamType,
audio_attributes_t{} /* currently unused for patch track */,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
- TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
- PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
- : nullptr,
+ TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed),
+ PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
+ true /*clientInServer*/) : nullptr,
playbackThread, timeout)
{
+ if (mProxy != nullptr) {
+ sp<AudioTrackClientProxy>::cast(mProxy)->setPlaybackRate({
+ /* .mSpeed = */ speed,
+ /* .mPitch = */ AUDIO_TIMESTRETCH_PITCH_NORMAL,
+ /* .mStretchMode = */ AUDIO_TIMESTRETCH_STRETCH_DEFAULT,
+ /* .mFallbackMode = */ AUDIO_TIMESTRETCH_FALLBACK_FAIL
+ });
+ }
ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
__func__, mId, sampleRate,
(int)mPeerTimeout.tv_sec,
@@ -2641,6 +2653,7 @@
mRecordTrack(recordTrack)
{
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ setInheritRt(true);
}
RecordHandle::~RecordHandle() {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 15c6a75..95bbc25 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -7862,9 +7862,10 @@
}
if (Volume::getDeviceForVolume(deviceTypes) != AUDIO_DEVICE_OUT_SPEAKER
&& !Intersection(deviceTypes, {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}).empty()) {
- // on A2DP, also ensure notification volume is not too low compared to media when
- // intended to be played
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
+ AUDIO_DEVICE_OUT_BLE_HEADSET}).empty()) {
+ // on A2DP/BLE, also ensure notification volume is not too low compared to media
+ // when intended to be played.
if ((volumeDb > -96.0f) &&
(musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDb)) {
ALOGV("%s increasing volume for volume source=%d device=%s from %f to %f",
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 717640f..68a5bc9 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -227,6 +227,7 @@
mDestroyAudioPolicyManager(destroyAudioPolicyManager),
mUsecaseValidator(media::createUsecaseValidator()) {
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ setInheritRt(true);
}
void AudioPolicyService::loadAudioPolicyManager()
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index b6b9720..5e21e56 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -291,6 +291,7 @@
mPolicyCallback(callback) {
ALOGV("%s", __func__);
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ setInheritRt(true);
}
void Spatializer::onFirstRef() {