diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig index a2b6a8284e..b3c02ebcd9 100644 --- a/media/aconfig/codec_fwk.aconfig +++ b/media/aconfig/codec_fwk.aconfig @@ -87,6 +87,26 @@ flag { bug: "325549730" } +flag { + name: "set_callback_stall" + namespace: "codec_fwk" + description: "Bugfix flag for setCallback stall" + bug: "326010604" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "set_state_early" + namespace: "codec_fwk" + description: "Bugfix flag for setting state early to avoid a race condition" + bug: "298613711" + metadata { + purpose: PURPOSE_BUGFIX + } +} + flag { name: "teamfood" namespace: "codec_fwk" diff --git a/media/codec2/components/aom/C2SoftAomEnc.cpp b/media/codec2/components/aom/C2SoftAomEnc.cpp index 256bcb8e29..722b13a568 100644 --- a/media/codec2/components/aom/C2SoftAomEnc.cpp +++ b/media/codec2/components/aom/C2SoftAomEnc.cpp @@ -29,6 +29,12 @@ #include "C2SoftAomEnc.h" +/* Quantization param values defined by the spec */ +#define AOM_QP_MIN 0 +#define AOM_QP_MAX 63 +#define AOM_QP_DEFAULT_MIN AOM_QP_MIN +#define AOM_QP_DEFAULT_MAX AOM_QP_MAX + namespace android { constexpr char COMPONENT_NAME[] = "c2.android.av1.encoder"; @@ -175,6 +181,19 @@ C2SoftAomEnc::IntfImpl::IntfImpl(const std::shared_ptr& helpe .inRange(C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)}) .withSetter(CodedColorAspectsSetter, mColorAspects) .build()); + + addParameter( + DefineParam(mPictureQuantization, C2_PARAMKEY_PICTURE_QUANTIZATION) + .withDefault(C2StreamPictureQuantizationTuning::output::AllocShared( + 0 /* flexCount */, 0u /* stream */)) + .withFields({C2F(mPictureQuantization, m.values[0].type_).oneOf( + {C2Config::I_FRAME, C2Config::P_FRAME}), + C2F(mPictureQuantization, m.values[0].min).inRange( + AOM_QP_DEFAULT_MIN, AOM_QP_DEFAULT_MAX), + C2F(mPictureQuantization, m.values[0].max).inRange( + AOM_QP_DEFAULT_MIN, AOM_QP_DEFAULT_MAX)}) + .withSetter(PictureQuantizationSetter) + .build()); } C2R C2SoftAomEnc::IntfImpl::BitrateSetter(bool mayBlock, C2P& me) { @@ -307,6 +326,54 @@ C2R C2SoftAomEnc::IntfImpl::CodedColorAspectsSetter( return C2R::Ok(); } +C2R C2SoftAomEnc::IntfImpl::PictureQuantizationSetter( + bool mayBlock, C2P& me) { + (void)mayBlock; + int32_t iMin = AOM_QP_DEFAULT_MIN, pMin = AOM_QP_DEFAULT_MIN; + int32_t iMax = AOM_QP_DEFAULT_MAX, pMax = AOM_QP_DEFAULT_MAX; + for (size_t i = 0; i < me.v.flexCount(); ++i) { + const C2PictureQuantizationStruct &layer = me.v.m.values[i]; + // layerMin is clamped to [AOM_QP_MIN, layerMax] to avoid error + // cases where layer.min > layer.max + int32_t layerMax = std::clamp(layer.max, AOM_QP_MIN, AOM_QP_MAX); + int32_t layerMin = std::clamp(layer.min, AOM_QP_MIN, layerMax); + if (layer.type_ == C2Config::picture_type_t(I_FRAME)) { + iMax = layerMax; + iMin = layerMin; + ALOGV("iMin %d iMax %d", iMin, iMax); + } else if (layer.type_ == C2Config::picture_type_t(P_FRAME)) { + pMax = layerMax; + pMin = layerMin; + ALOGV("pMin %d pMax %d", pMin, pMax); + } + } + ALOGV("PictureQuantizationSetter(entry): i %d-%d p %d-%d", + iMin, iMax, pMin, pMax); + + // aom library takes same range for I/P picture type + int32_t maxFrameQP = std::min(iMax, pMax); + int32_t minFrameQP = std::max(iMin, pMin); + if (minFrameQP > maxFrameQP) { + minFrameQP = maxFrameQP; + } + // put them back into the structure + for (size_t i = 0; i < me.v.flexCount(); ++i) { + const C2PictureQuantizationStruct &layer = me.v.m.values[i]; + + if (layer.type_ == C2Config::picture_type_t(I_FRAME)) { + me.set().m.values[i].max = maxFrameQP; + me.set().m.values[i].min = minFrameQP; + } + else if (layer.type_ == C2Config::picture_type_t(P_FRAME)) { + me.set().m.values[i].max = maxFrameQP; + me.set().m.values[i].min = minFrameQP; + } + } + ALOGV("PictureQuantizationSetter(exit): minFrameQP = %d maxFrameQP = %d", + minFrameQP, maxFrameQP); + return C2R::Ok(); +} + uint32_t C2SoftAomEnc::IntfImpl::getLevel_l() const { return mProfileLevel->level - LEVEL_AV1_2; } @@ -558,6 +625,7 @@ status_t C2SoftAomEnc::initEncoder() { mQuality = mIntf->getQuality_l(); mComplexity = mIntf->getComplexity_l(); mAV1EncLevel = mIntf->getLevel_l(); + mQpBounds = mIntf->getPictureQuantization_l(); } @@ -575,6 +643,18 @@ status_t C2SoftAomEnc::initEncoder() { break; } + if (mQpBounds->flexCount() > 0) { + // read min max qp for sequence + for (size_t i = 0; i < mQpBounds->flexCount(); ++i) { + const C2PictureQuantizationStruct &layer = mQpBounds->m.values[i]; + if (layer.type_ == C2Config::picture_type_t(I_FRAME)) { + mMaxQuantizer = layer.max; + mMinQuantizer = layer.min; + break; + } + } + } + mCodecInterface = aom_codec_av1_cx(); if (!mCodecInterface) goto CleanUp; diff --git a/media/codec2/components/aom/C2SoftAomEnc.h b/media/codec2/components/aom/C2SoftAomEnc.h index 7e5ea63ddc..067b04f24d 100644 --- a/media/codec2/components/aom/C2SoftAomEnc.h +++ b/media/codec2/components/aom/C2SoftAomEnc.h @@ -109,6 +109,7 @@ struct C2SoftAomEnc : public SimpleC2Component { std::shared_ptr mBitrateMode; std::shared_ptr mRequestSync; std::shared_ptr mColorAspects; + std::shared_ptr mQpBounds; aom_codec_err_t setupCodecParameters(); }; @@ -126,6 +127,8 @@ class C2SoftAomEnc::IntfImpl : public SimpleInterface::BaseParams { const C2P& size, const C2P& frameRate, const C2P& bitrate); + static C2R PictureQuantizationSetter(bool mayBlock, + C2P &me); // unsafe getters std::shared_ptr getSize_l() const { return mSize; } @@ -150,6 +153,9 @@ class C2SoftAomEnc::IntfImpl : public SimpleInterface::BaseParams { std::shared_ptr getPixelFormat_l() const { return mPixelFormat; } + std::shared_ptr getPictureQuantization_l() const { + return mPictureQuantization; + } uint32_t getSyncFramePeriod() const; static C2R ColorAspectsSetter(bool mayBlock, C2P& me); static C2R CodedColorAspectsSetter(bool mayBlock, C2P& me, @@ -171,6 +177,7 @@ class C2SoftAomEnc::IntfImpl : public SimpleInterface::BaseParams { std::shared_ptr mColorAspects; std::shared_ptr mCodedColorAspects; std::shared_ptr mPixelFormat; + std::shared_ptr mPictureQuantization; }; diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp index 24098948e3..08e2fa6915 100644 --- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp +++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp @@ -354,12 +354,9 @@ uint32_t C2SoftVpxEnc::IntfImpl::getSyncFramePeriod() const { return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.); } -C2R C2SoftVpxEnc::IntfImpl::PictureQuantizationSetter(bool mayBlock, - C2P - &me) { +C2R C2SoftVpxEnc::IntfImpl::PictureQuantizationSetter( + bool mayBlock, C2P& me) { (void)mayBlock; - // these are the ones we're going to set, so want them to default - // to the DEFAULT values for the codec int32_t iMin = VPX_QP_DEFAULT_MIN, pMin = VPX_QP_DEFAULT_MIN; int32_t iMax = VPX_QP_DEFAULT_MAX, pMax = VPX_QP_DEFAULT_MAX; for (size_t i = 0; i < me.v.flexCount(); ++i) { @@ -382,8 +379,8 @@ C2R C2SoftVpxEnc::IntfImpl::PictureQuantizationSetter(bool mayBlock, iMin, iMax, pMin, pMax); // vpx library takes same range for I/P picture type - int32_t maxFrameQP = std::min({iMax, pMax}); - int32_t minFrameQP = std::max({iMin, pMin}); + int32_t maxFrameQP = std::min(iMax, pMax); + int32_t minFrameQP = std::max(iMin, pMin); if (minFrameQP > maxFrameQP) { minFrameQP = maxFrameQP; } diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp index 636c19649f..a11bea1bb5 100644 --- a/media/codec2/sfplugin/Codec2Buffer.cpp +++ b/media/codec2/sfplugin/Codec2Buffer.cpp @@ -1184,7 +1184,7 @@ c2_status_t GetHdrMetadataFromGralloc4Handle( std::optional smpte2086; status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086); - if (status != OK) { + if (status != OK || !smpte2086) { err = C2_CORRUPTED; } else { if (smpte2086) { @@ -1204,7 +1204,7 @@ c2_status_t GetHdrMetadataFromGralloc4Handle( std::optional cta861_3; status = mapper.getCta861_3(buffer.get(), &cta861_3); - if (status != OK) { + if (status != OK || !cta861_3) { err = C2_CORRUPTED; } else { if (cta861_3) { @@ -1223,7 +1223,7 @@ c2_status_t GetHdrMetadataFromGralloc4Handle( dynamicInfo->reset(); std::optional> vec; status_t status = mapper.getSmpte2094_40(buffer.get(), &vec); - if (status != OK) { + if (status != OK || !vec) { dynamicInfo->reset(); err = C2_CORRUPTED; } else { diff --git a/media/libaudioclient/aidl/fuzzer/audioflinger_aidl_fuzzer.cpp b/media/libaudioclient/aidl/fuzzer/audioflinger_aidl_fuzzer.cpp index 1d2da6a64d..c7a04da723 100644 --- a/media/libaudioclient/aidl/fuzzer/audioflinger_aidl_fuzzer.cpp +++ b/media/libaudioclient/aidl/fuzzer/audioflinger_aidl_fuzzer.cpp @@ -36,6 +36,7 @@ using android::fuzzService; [[clang::no_destroy]] static std::once_flag gSmOnce; sp gFakeServiceManager; +sp gAudioFlingerServerAdapter; bool addService(const String16& serviceName, const sp& fakeServiceManager, FuzzedDataProvider& fdp) { @@ -47,22 +48,10 @@ bool addService(const String16& serviceName, const sp& fakeS return true; } -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp(data, size); - - std::call_once(gSmOnce, [&] { - /* Create a FakeServiceManager instance and add required services */ - gFakeServiceManager = sp::make(); - setDefaultServiceManager(gFakeServiceManager); - }); - gFakeServiceManager->clear(); - - for (const char* service : {"activity", "sensor_privacy", "permission", "scheduling_policy", - "batterystats", "media.metrics"}) { - if (!addService(String16(service), gFakeServiceManager, fdp)) { - return 0; - } - } +extern "C" int LLVMFuzzerInitialize(int* /*argc*/, char*** /*argv*/) { + /* Create a FakeServiceManager instance and add required services */ + gFakeServiceManager = sp::make(); + setDefaultServiceManager(gFakeServiceManager); auto configService = ndk::SharedRefBase::make(); CHECK_EQ(NO_ERROR, AServiceManager_addService(configService.get()->asBinder().get(), @@ -80,22 +69,37 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Disable creating thread pool for fuzzer instance of audio flinger and audio policy services AudioSystem::disableThreadPool(); - const auto audioFlinger = sp::make(); - const auto afAdapter = sp::make(audioFlinger); + return 0; +} - CHECK_EQ(NO_ERROR, - gFakeServiceManager->addService( - String16(IAudioFlinger::DEFAULT_SERVICE_NAME), IInterface::asBinder(afAdapter), - false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); - const auto audioPolicyService = sp::make(); + for (const char* service : {"activity", "sensor_privacy", "permission", "scheduling_policy", + "batterystats", "media.metrics"}) { + if (!addService(String16(service), gFakeServiceManager, fdp)) { + return 0; + } + } - CHECK_EQ(NO_ERROR, - gFakeServiceManager->addService(String16("media.audio_policy"), audioPolicyService, - false /* allowIsolated */, - IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)); + // TODO(330882064) : Initialise Audio Flinger and Audio Policy services every time + std::call_once(gSmOnce, [&] { + const auto audioFlinger = sp::make(); + gAudioFlingerServerAdapter = sp::make(audioFlinger); + CHECK_EQ(NO_ERROR, + gFakeServiceManager->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME), + IInterface::asBinder(gAudioFlingerServerAdapter), + false /* allowIsolated */, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)); + + const auto audioPolicyService = sp::make(); + CHECK_EQ(NO_ERROR, + gFakeServiceManager->addService(String16("media.audio_policy"), audioPolicyService, + false /* allowIsolated */, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)); + }); - fuzzService(media::IAudioFlingerService::asBinder(afAdapter), std::move(fdp)); + fuzzService(media::IAudioFlingerService::asBinder(gAudioFlingerServerAdapter), std::move(fdp)); return 0; } diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index 2447b18d35..032533ceda 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -58,6 +58,7 @@ using aidl::android::media::audio::common::MicrophoneInfo; using aidl::android::media::audio::IHalAdapterVendorExtension; using aidl::android::hardware::audio::common::getFrameSizeInBytes; using aidl::android::hardware::audio::common::isBitPositionFlagSet; +using aidl::android::hardware::audio::common::kDumpFromAudioServerArgument; using aidl::android::hardware::audio::common::RecordTrackMetadata; using aidl::android::hardware::audio::core::sounddose::ISoundDose; using aidl::android::hardware::audio::core::AudioPatch; @@ -913,7 +914,9 @@ error::Result DeviceHalAidl::getHwAvSync() { status_t DeviceHalAidl::dump(int fd, const Vector& args) { TIME_CHECK(); if (mModule == nullptr) return NO_INIT; - return mModule->dump(fd, Args(args).args(), args.size()); + Vector newArgs = args; + newArgs.push(String16(kDumpFromAudioServerArgument)); + return mModule->dump(fd, Args(newArgs).args(), newArgs.size()); } status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) { diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h index d925b469d3..bcd495d110 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.h +++ b/media/libaudiohal/impl/DeviceHalAidl.h @@ -182,7 +182,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, status_t getAudioMixPort(const struct audio_port_v7* devicePort, struct audio_port_v7* mixPort) override; - status_t dump(int __unused, const Vector& __unused) override; + status_t dump(int fd, const Vector& args) override; private: friend class sp; diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp index af0f8f2baa..c7c65363b0 100644 --- a/media/libaudiohal/impl/EffectProxy.cpp +++ b/media/libaudiohal/impl/EffectProxy.cpp @@ -82,8 +82,7 @@ ndk::ScopedAStatus EffectProxy::destroy() { ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* offload) { const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) { const auto& desc = sub.descriptor; - return offload->isOffload == - (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL); + return offload->isOffload == desc.common.flags.offloadIndication; }); if (itor == mSubEffects.end()) { ALOGE("%s no %soffload sub-effect found", __func__, offload->isOffload ? "" : "non-"); @@ -93,7 +92,7 @@ ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* of } mActiveSubIdx = std::distance(mSubEffects.begin(), itor); - ALOGI("%s: active %soffload sub-effect %zu descriptor: %s", __func__, + ALOGI("%s: active %soffload sub-effect %zu: %s", __func__, offload->isOffload ? "" : "non-", mActiveSubIdx, ::android::audio::utils::toString(mSubEffects[mActiveSubIdx].descriptor.common.id.uuid) .c_str()); @@ -164,7 +163,7 @@ ndk::ScopedAStatus EffectProxy::close() { ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) { *desc = mSubEffects[mActiveSubIdx].descriptor; - desc->common.id.uuid = desc->common.id.proxy.value(); + desc->common = mDescriptorCommon; return ndk::ScopedAStatus::ok(); } @@ -186,42 +185,35 @@ ndk::ScopedAStatus EffectProxy::buildDescriptor(const AudioUuid& uuid, return ndk::ScopedAStatus::ok(); } +// Sub-effects are required to have identical features, so here we return the SW sub-effect +// descriptor, with the implementation UUID replaced with proxy UUID, and flags setting respect all +// sub-effects. Descriptor::Common EffectProxy::buildDescriptorCommon( const AudioUuid& uuid, const std::vector& subEffectDescs) { - // initial flag values before we know which sub-effect to active (with setOffloadParam) - // align to HIDL EffectProxy flags - Descriptor::Common common = {.flags = {.type = Flags::Type::INSERT, - .insert = Flags::Insert::LAST, - .volume = Flags::Volume::CTRL}}; - + Descriptor::Common swCommon; + const Flags& firstFlag = subEffectDescs[0].common.flags; + bool offloadExist = false; for (const auto& desc : subEffectDescs) { - if (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL) { - common.flags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL; - } - - // set indication if any sub-effect indication was set - common.flags.offloadIndication |= desc.common.flags.offloadIndication; - common.flags.deviceIndication |= desc.common.flags.deviceIndication; - common.flags.audioModeIndication |= desc.common.flags.audioModeIndication; - common.flags.audioSourceIndication |= desc.common.flags.audioSourceIndication; - // Set to NONE if any sub-effect not supporting any Volume command - if (desc.common.flags.volume == Flags::Volume::NONE) { - common.flags.volume = Flags::Volume::NONE; + if (desc.common.flags.offloadIndication) { + offloadExist = true; + } else { + swCommon = desc.common; } - // set to AUXILIARY if any sub-effect is of AUXILIARY type - if (desc.common.flags.type == Flags::Type::AUXILIARY) { - common.flags.type = Flags::Type::AUXILIARY; + if (desc.common.flags.audioModeIndication != firstFlag.audioModeIndication || + desc.common.flags.audioSourceIndication != firstFlag.audioSourceIndication || + desc.common.flags.sinkMetadataIndication != firstFlag.sinkMetadataIndication || + desc.common.flags.sourceMetadataIndication != firstFlag.sourceMetadataIndication || + desc.common.flags.deviceIndication != firstFlag.deviceIndication) { + ALOGW("Inconsistent flags %s vs %s", desc.common.flags.toString().c_str(), + firstFlag.toString().c_str()); } } - // copy type UUID from any of sub-effects, all sub-effects should have same type - common.id.type = subEffectDescs[0].common.id.type; + swCommon.flags.offloadIndication = offloadExist; // replace implementation UUID with proxy UUID. - common.id.uuid = uuid; - common.id.proxy = std::nullopt; - common.name = "Proxy"; - common.implementor = "AOSP"; - return common; + swCommon.id.uuid = uuid; + swCommon.id.proxy = std::nullopt; + return swCommon; } // Handle with active sub-effect first, only send to other sub-effects when success diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp index 3b2f344fe8..64cc7ed3d8 100644 --- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp +++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp @@ -188,7 +188,6 @@ status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t aidlEffect = ndk::SharedRefBase::make( aidlUuid, mProxyUuidDescriptorMap.at(aidlUuid) /* sub-effect descriptor list */, mFactory); - mProxyList.emplace_back(std::static_pointer_cast(aidlEffect)); } else { RETURN_STATUS_IF_ERROR( statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect))); @@ -205,15 +204,9 @@ status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t } status_t EffectsFactoryHalAidl::dumpEffects(int fd) { - status_t ret = OK; - // record the error ret and continue dump as many effects as possible - for (const auto& proxy : mProxyList) { - if (status_t temp = BAD_VALUE; proxy && (temp = proxy->dump(fd, nullptr, 0)) != OK) { - ret = temp; - } - } + // TODO: b/333803769 improve the effect dump implementation RETURN_STATUS_IF_ERROR(mFactory->dump(fd, nullptr, 0)); - return ret; + return OK; } status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp* buffer) { diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h index 73089b0088..3b8628c8fd 100644 --- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h +++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h @@ -84,9 +84,6 @@ class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface { // Query result of pre and post processing from effect factory const std::vector mAidlProcessings; - // list of the EffectProxy instances - std::list> mProxyList; - virtual ~EffectsFactoryHalAidl() = default; status_t getHalDescriptorWithImplUuid( const ::aidl::android::media::audio::common::AudioUuid& uuid, diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp index 0af164f0a7..d8a2feda90 100644 --- a/media/libaudiohal/impl/StreamHalAidl.cpp +++ b/media/libaudiohal/impl/StreamHalAidl.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "DeviceHalAidl.h" @@ -36,13 +37,14 @@ #include "StreamHalAidl.h" using ::aidl::android::aidl_utils::statusTFromBinderStatus; +using ::aidl::android::hardware::audio::common::kDumpFromAudioServerArgument; using ::aidl::android::hardware::audio::common::PlaybackTrackMetadata; using ::aidl::android::hardware::audio::common::RecordTrackMetadata; using ::aidl::android::hardware::audio::core::IStreamCommon; using ::aidl::android::hardware::audio::core::IStreamIn; using ::aidl::android::hardware::audio::core::IStreamOut; -using ::aidl::android::hardware::audio::core::StreamDescriptor; using ::aidl::android::hardware::audio::core::MmapBufferDescriptor; +using ::aidl::android::hardware::audio::core::StreamDescriptor; using ::aidl::android::media::audio::common::MicrophoneDynamicInfo; using ::aidl::android::media::audio::IHalAdapterVendorExtension; @@ -239,7 +241,9 @@ status_t StreamHalAidl::dump(int fd, const Vector& args) { ALOGD("%p %s::%s", this, getClassName().c_str(), __func__); TIME_CHECK(); if (!mStream) return NO_INIT; - status_t status = mStream->dump(fd, Args(args).args(), args.size()); + Vector newArgs = args; + newArgs.push(String16(kDumpFromAudioServerArgument)); + status_t status = mStream->dump(fd, Args(newArgs).args(), newArgs.size()); mStreamPowerLog.dump(fd); return status; } diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp index 7a734d28dc..f1d2b56f5c 100644 --- a/media/libaudioprocessing/AudioMixerBase.cpp +++ b/media/libaudioprocessing/AudioMixerBase.cpp @@ -1133,7 +1133,7 @@ void AudioMixerBase::process__genericNoResampling() aux = t->auxBuffer + numFrames; } for (int outFrames = frameCount; outFrames > 0; ) { - // t->in == nullptr can happen if the track was flushed just after having + // t->mIn == nullptr can happen if the track was flushed just after having // been enabled for mixing. if (t->mIn == nullptr) { break; diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp index 9c2b71ef13..9b493d43a8 100644 --- a/media/libeffects/visualizer/aidl/Visualizer.cpp +++ b/media/libeffects/visualizer/aidl/Visualizer.cpp @@ -72,7 +72,7 @@ const Descriptor VisualizerImpl::kDescriptor = { .uuid = getEffectImplUuidVisualizer(), .proxy = std::nullopt}, .flags = {.type = Flags::Type::INSERT, - .insert = Flags::Insert::LAST, + .insert = Flags::Insert::FIRST, .volume = Flags::Volume::NONE}, .name = VisualizerImpl::kEffectName, .implementor = "The Android Open Source Project"}, diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 1be212ce46..0c6e3973cd 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -2209,9 +2209,12 @@ void NuPlayer::updateVideoSize( displayHeight, cropLeft, cropTop); } else { - CHECK(inputFormat->findInt32("width", &displayWidth)); - CHECK(inputFormat->findInt32("height", &displayHeight)); - + if (!inputFormat->findInt32("width", &displayWidth) + || !inputFormat->findInt32("height", &displayHeight)) { + ALOGW("Either video width or video height missing, reporting 0x0!"); + notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0); + return; + } ALOGV("Video input format %d x %d", displayWidth, displayHeight); } diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 90aa39d5aa..42b5b63302 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -6082,6 +6082,10 @@ void MediaCodec::setState(State newState) { mErrorLog.clear(); } + if (android::media::codec::provider_->set_state_early()) { + mState = newState; + } + if (newState == UNINITIALIZED) { // return any straggling buffers, e.g. if we got here on an error returnBuffersToCodec(); @@ -6092,7 +6096,9 @@ void MediaCodec::setState(State newState) { mFlags &= ~kFlagSawMediaServerDie; } - mState = newState; + if (!android::media::codec::provider_->set_state_early()) { + mState = newState; + } if (mBatteryChecker != nullptr) { mBatteryChecker->setExecuting(isExecuting()); diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml index 0e89521ad2..b3be24ba34 100644 --- a/media/libstagefright/data/media_codecs_sw.xml +++ b/media/libstagefright/data/media_codecs_sw.xml @@ -216,6 +216,7 @@ + @@ -234,6 +235,7 @@ + diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp index 4218d2d7d5..3f850c2814 100644 --- a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp +++ b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp @@ -24,61 +24,64 @@ namespace android { -#define MAX_MEDIA_BUFFER_SIZE 2048 +static const android_pixel_format_t kColorFormats[] = { + HAL_PIXEL_FORMAT_RGBA_8888, + HAL_PIXEL_FORMAT_RGB_565, + HAL_PIXEL_FORMAT_BGRA_8888, + HAL_PIXEL_FORMAT_RGBA_1010102, + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, /* To cover the default case */ +}; -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - // Init our wrapper - FuzzedDataProvider fdp(data, size); +static const MediaSource::ReadOptions::SeekMode kSeekModes[] = { + MediaSource::ReadOptions::SeekMode::SEEK_PREVIOUS_SYNC, + MediaSource::ReadOptions::SeekMode::SEEK_NEXT_SYNC, + MediaSource::ReadOptions::SeekMode::SEEK_CLOSEST_SYNC, + MediaSource::ReadOptions::SeekMode::SEEK_CLOSEST, + MediaSource::ReadOptions::SeekMode::SEEK_FRAME_INDEX, +}; + +static const std::string kComponentNames[] = { + "c2.android.avc.decoder", "c2.android.hevc.decoder", "c2.android.vp8.decoder", + "c2.android.vp9.decoder", "c2.android.av1.decoder", "c2.android.mpeg4.decoder", + "c2.android.h263.decoder", +}; - std::string name = fdp.ConsumeRandomLengthString(fdp.remaining_bytes()); - AString componentName(name.c_str()); - sp trackMeta = generateMetaData(&fdp); - sp source = new IMediaSourceFuzzImpl(&fdp, MAX_MEDIA_BUFFER_SIZE); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); + std::string component = fdp.PickValueInArray(kComponentNames); + AString componentName(component.c_str()); + sp trackMeta = generateMetaData(&fdp, component); + sp source = sp::make(&fdp, gMaxMediaBufferSize); - // Image or video Decoder? - sp decoder; - bool isVideoDecoder = fdp.ConsumeBool(); - if (isVideoDecoder) { - decoder = new VideoFrameDecoder(componentName, trackMeta, source); + sp decoder = nullptr; + if (fdp.ConsumeBool()) { + decoder = sp::make(componentName, trackMeta, source); } else { - decoder = new MediaImageDecoder(componentName, trackMeta, source); + decoder = sp::make(componentName, trackMeta, source); } - while (fdp.remaining_bytes()) { - uint8_t switchCase = fdp.ConsumeIntegralInRange(0, 3); - switch (switchCase) { - case 0: { - int64_t frameTimeUs = fdp.ConsumeIntegral(); - int option = fdp.ConsumeIntegral(); - int colorFormat = fdp.ConsumeIntegral(); - decoder->init(frameTimeUs, option, colorFormat); - break; - } - case 1: - decoder->extractFrame(); - break; - case 2: { - FrameRect rect; - rect.left = fdp.ConsumeIntegral(); - rect.top = fdp.ConsumeIntegral(); - rect.right = fdp.ConsumeIntegral(); - rect.bottom = fdp.ConsumeIntegral(); - decoder->extractFrame(&rect); - break; - } - case 3: { - sp trackMeta = generateMetaData(&fdp); - decoder->getMetadataOnly(trackMeta, - /*colorFormat*/ fdp.ConsumeIntegral(), - /*thumbnail*/ fdp.ConsumeBool()); - break; - } - } + if (decoder.get() && + decoder->init(fdp.ConsumeIntegral() /* frameTimeUs */, + fdp.PickValueInArray(kSeekModes) /* option */, + fdp.PickValueInArray(kColorFormats) /* colorFormat */) == OK) { + auto frameDecoderAPI = fdp.PickValueInArray>({ + [&]() { decoder->extractFrame(); }, + [&]() { + FrameRect rect(fdp.ConsumeIntegral() /* left */, + fdp.ConsumeIntegral() /* top */, + fdp.ConsumeIntegral() /* right */, + fdp.ConsumeIntegral() /* bottom */ + ); + decoder->extractFrame(&rect); + }, + [&]() { + FrameDecoder::getMetadataOnly( + trackMeta, fdp.PickValueInArray(kColorFormats) /* colorFormat */, + fdp.ConsumeBool() /* thumbnail */); + }, + }); + frameDecoderAPI(); } - - generated_mime_types.clear(); - return 0; } diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h index 228c04a13c..5430530be9 100644 --- a/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h +++ b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h @@ -20,69 +20,100 @@ #include #include "MediaMimeTypes.h" -#define MAX_METADATA_BUF_SIZE 512 - namespace android { std::vector> generated_mime_types; +constexpr uint8_t kMinKeyHeight = 32; +constexpr uint8_t kMinKeyWidth = 32; +constexpr uint16_t kMaxKeyHeight = 2160; +constexpr uint16_t kMaxKeyWidth = 3840; +size_t gMaxMediaBufferSize = 0; + +sp generateMetaData(FuzzedDataProvider* fdp, std::string componentName = std::string()) { + sp newMeta = sp::make(); + + const char* mime; + if(!componentName.empty()) + { + auto it = decoderToMediaType.find(componentName); + mime = it->second; + } + else{ + size_t index = fdp->ConsumeIntegralInRange(0, kMimeTypes.size()); + // Let there be a chance of a true random string + if (index == kMimeTypes.size()) { + std::string mime_str = fdp->ConsumeRandomLengthString(64); + std::shared_ptr mime_cstr(new char[mime_str.length()+1]); + generated_mime_types.push_back(mime_cstr); + strncpy(mime_cstr.get(), mime_str.c_str(), mime_str.length()+1); + mime = mime_cstr.get(); + } else { + mime = kMimeTypes[index]; + } + } + newMeta->setCString(kKeyMIMEType, mime); + + auto height = fdp->ConsumeIntegralInRange(kMinKeyHeight, kMaxKeyHeight); + auto width = fdp->ConsumeIntegralInRange(kMinKeyWidth, kMaxKeyWidth); + newMeta->setInt32(kKeyHeight, height); + newMeta->setInt32(kKeyWidth, width); + + gMaxMediaBufferSize = height * width; + + if (fdp->ConsumeBool()) { + newMeta->setInt32(kKeyTileHeight, + fdp->ConsumeIntegralInRange(kMinKeyHeight, height)); + newMeta->setInt32(kKeyTileWidth, + fdp->ConsumeIntegralInRange(kMinKeyWidth, width)); + newMeta->setInt32(kKeyGridRows, fdp->ConsumeIntegral()); + newMeta->setInt32(kKeyGridCols, fdp->ConsumeIntegral()); + } + + if (fdp->ConsumeBool()) { + newMeta->setInt32(kKeySARHeight, fdp->ConsumeIntegral()); + newMeta->setInt32(kKeySARWidth, fdp->ConsumeIntegral()); + } + + if (fdp->ConsumeBool()) { + newMeta->setInt32(kKeyDisplayHeight, + fdp->ConsumeIntegralInRange(height, UINT16_MAX)); + newMeta->setInt32(kKeyDisplayWidth, + fdp->ConsumeIntegralInRange(width, UINT16_MAX)); + } + + if (fdp->ConsumeBool()) { + newMeta->setRect(kKeyCropRect, fdp->ConsumeIntegral() /* left */, + fdp->ConsumeIntegral() /* top */, + fdp->ConsumeIntegral() /* right */, + fdp->ConsumeIntegral() /* bottom */); + } + + if (fdp->ConsumeBool()) { + newMeta->setInt32(kKeyRotation, fdp->ConsumeIntegralInRange(0, 3) * 90); + } + + if (fdp->ConsumeBool()) { + newMeta->setInt64(kKeyThumbnailTime, fdp->ConsumeIntegral()); + newMeta->setInt32(kKeyThumbnailHeight, fdp->ConsumeIntegral()); + newMeta->setInt32(kKeyThumbnailWidth, fdp->ConsumeIntegral()); + + size_t thumbnailSize = fdp->ConsumeIntegral(); + std::vector thumbnailData = fdp->ConsumeBytes(thumbnailSize); + if (mime == MEDIA_MIMETYPE_VIDEO_AV1) { + newMeta->setData(kKeyThumbnailAV1C, fdp->ConsumeIntegral() /* type */, + thumbnailData.data(), thumbnailData.size()); + } else { + newMeta->setData(kKeyThumbnailHVCC, fdp->ConsumeIntegral() /* type */, + thumbnailData.data(), thumbnailData.size()); + } + } -sp generateMetaData(FuzzedDataProvider *fdp) { - sp newMeta = new MetaData(); - - // random MIME Type - const char *mime_type; - size_t index = fdp->ConsumeIntegralInRange(0, kMimeTypes.size()); - // Let there be a chance of a true random string - if (index == kMimeTypes.size()) { - std::string mime_str = fdp->ConsumeRandomLengthString(64); - std::shared_ptr mime_cstr(new char[mime_str.length()+1]); - generated_mime_types.push_back(mime_cstr); - strncpy(mime_cstr.get(), mime_str.c_str(), mime_str.length()+1); - mime_type = mime_cstr.get(); - } else { - mime_type = kMimeTypes[index]; + if (fdp->ConsumeBool()) { + size_t profileSize = fdp->ConsumeIntegral(); + std::vector profileData = fdp->ConsumeBytes(profileSize); + newMeta->setData(kKeyIccProfile, fdp->ConsumeIntegral() /* type */, + profileData.data(), profileData.size()); } - newMeta->setCString(kKeyMIMEType, mime_type); - - // Thumbnail time - newMeta->setInt64(kKeyThumbnailTime, fdp->ConsumeIntegral()); - - // Values used by allocVideoFrame - newMeta->setInt32(kKeyRotation, fdp->ConsumeIntegral()); - size_t profile_size = - fdp->ConsumeIntegralInRange(0, MAX_METADATA_BUF_SIZE); - std::vector profile_bytes = - fdp->ConsumeBytes(profile_size); - newMeta->setData(kKeyIccProfile, - fdp->ConsumeIntegral(), - profile_bytes.empty() ? nullptr : profile_bytes.data(), - profile_bytes.size()); - newMeta->setInt32(kKeySARWidth, fdp->ConsumeIntegral()); - newMeta->setInt32(kKeySARHeight, fdp->ConsumeIntegral()); - newMeta->setInt32(kKeyDisplayWidth, fdp->ConsumeIntegral()); - newMeta->setInt32(kKeyDisplayHeight, fdp->ConsumeIntegral()); - - // Values used by findThumbnailInfo - newMeta->setInt32(kKeyThumbnailWidth, fdp->ConsumeIntegral()); - newMeta->setInt32(kKeyThumbnailHeight, fdp->ConsumeIntegral()); - size_t thumbnail_size = - fdp->ConsumeIntegralInRange(0, MAX_METADATA_BUF_SIZE); - std::vector thumb_bytes = - fdp->ConsumeBytes(thumbnail_size); - newMeta->setData(kKeyThumbnailHVCC, - fdp->ConsumeIntegral(), - thumb_bytes.empty() ? nullptr : thumb_bytes.data(), - thumb_bytes.size()); - - // Values used by findGridInfo - newMeta->setInt32(kKeyTileWidth, fdp->ConsumeIntegral()); - newMeta->setInt32(kKeyTileHeight, fdp->ConsumeIntegral()); - newMeta->setInt32(kKeyGridRows, fdp->ConsumeIntegral()); - newMeta->setInt32(kKeyGridCols, fdp->ConsumeIntegral()); - - // A few functions perform a CHECK() that height/width are set - newMeta->setInt32(kKeyHeight, fdp->ConsumeIntegral()); - newMeta->setInt32(kKeyWidth, fdp->ConsumeIntegral()); return newMeta; } diff --git a/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h index e769950f82..7e6f662098 100644 --- a/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h +++ b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h @@ -19,31 +19,33 @@ #include +#define MAX_FRAMES 5 + namespace android { class IMediaSourceFuzzImpl : public IMediaSource { public: - IMediaSourceFuzzImpl(FuzzedDataProvider *_fdp, size_t _max_buffer_size) : - fdp(_fdp), - max_buffer_size(_max_buffer_size) {} - status_t start(MetaData*) override { return 0; } - status_t stop() override { return 0; } - sp getFormat() override { return nullptr; } - status_t read(MediaBufferBase**, - const MediaSource::ReadOptions*) override; - status_t readMultiple(Vector*, uint32_t, - const MediaSource::ReadOptions*) override; - bool supportReadMultiple() override { return true; } - bool supportNonblockingRead() override { return true; } - status_t pause() override { return 0; } + IMediaSourceFuzzImpl(FuzzedDataProvider* _fdp, size_t _max_buffer_size) + : frames_read(0), fdp(_fdp), min_buffer_size(32 * 32), max_buffer_size(_max_buffer_size) {} + status_t start(MetaData*) override { return 0; } + status_t stop() override { return 0; } + sp getFormat() override { return nullptr; } + status_t read(MediaBufferBase**, const MediaSource::ReadOptions*) override; + status_t readMultiple(Vector*, uint32_t, + const MediaSource::ReadOptions*) override; + bool supportReadMultiple() override { return true; } + bool supportNonblockingRead() override { return true; } + status_t pause() override { return 0; } protected: IBinder* onAsBinder() { return nullptr; } private: - FuzzedDataProvider *fdp; - std::vector> buffer_bases; - const size_t max_buffer_size; + uint8_t frames_read; + FuzzedDataProvider* fdp; + const size_t min_buffer_size; + const size_t max_buffer_size; + std::vector buf; }; // This class is simply to expose the destructor @@ -53,32 +55,41 @@ class MediaBufferFuzzImpl : public MediaBuffer { ~MediaBufferFuzzImpl() {} }; -status_t IMediaSourceFuzzImpl::read(MediaBufferBase **buffer, - const MediaSource::ReadOptions *options) { +status_t IMediaSourceFuzzImpl::read(MediaBufferBase** buffer, const MediaSource::ReadOptions*) { Vector buffers; - status_t ret = readMultiple(&buffers, 1, options); + status_t ret = readMultiple(&buffers, 1, nullptr); *buffer = buffers.empty() ? nullptr : buffers[0]; return ret; } -status_t IMediaSourceFuzzImpl::readMultiple(Vector* buffers, - uint32_t maxNumBuffers, const MediaSource::ReadOptions*) { - uint32_t num_buffers = - fdp->ConsumeIntegralInRange(0, maxNumBuffers); - for(uint32_t i = 0; i < num_buffers; i++) { - std::vector buf = fdp->ConsumeBytes( - fdp->ConsumeIntegralInRange(0, max_buffer_size)); +status_t IMediaSourceFuzzImpl::readMultiple(Vector* buffers, uint32_t, + const MediaSource::ReadOptions*) { + if (++frames_read == MAX_FRAMES) { + auto size = fdp->ConsumeIntegralInRange(min_buffer_size, max_buffer_size); + buf = fdp->ConsumeBytes(size); + if (buf.size() < size) { + buf.resize(size, 0); + } + + MediaBufferBase* mbb = new MediaBufferFuzzImpl(buf.data(), buf.size()); + mbb->meta_data().setInt64(kKeyTime, fdp->ConsumeIntegral()); + buffers->push_back(mbb); - std::shared_ptr mbb( - new MediaBufferFuzzImpl(buf.data(), buf.size())); + return ERROR_END_OF_STREAM; + } - buffer_bases.push_back(mbb); - buffers->push_back(mbb.get()); + auto size = fdp->ConsumeIntegralInRange(min_buffer_size, max_buffer_size); + buf = fdp->ConsumeBytes(size); + if (buf.size() < size) { + buf.resize(size, 0); } - // STATUS_OK - return 0; + MediaBufferBase* mbb = new MediaBufferFuzzImpl(buf.data(), buf.size()); + mbb->meta_data().setInt64(kKeyTime, fdp->ConsumeIntegral()); + buffers->push_back(mbb); + + return OK; } } // namespace android diff --git a/media/libstagefright/tests/fuzzers/MediaMimeTypes.h b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h index 9f337acc61..de7814e7c1 100644 --- a/media/libstagefright/tests/fuzzers/MediaMimeTypes.h +++ b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h @@ -18,6 +18,7 @@ #define FUZZER_MEDIAMIMETYPES_H_ #include +#include namespace android { @@ -80,6 +81,15 @@ static const std::vector kMimeTypes { MEDIA_MIMETYPE_DATA_TIMED_ID3 }; +static const std::unordered_map decoderToMediaType = { + {"c2.android.vp8.decoder", MEDIA_MIMETYPE_VIDEO_VP8}, + {"c2.android.vp9.decoder", MEDIA_MIMETYPE_VIDEO_VP9}, + {"c2.android.av1.decoder", MEDIA_MIMETYPE_VIDEO_AV1}, + {"c2.android.avc.decoder", MEDIA_MIMETYPE_VIDEO_AVC}, + {"c2.android.hevc.decoder", MEDIA_MIMETYPE_VIDEO_HEVC}, + {"c2.android.mpeg4.decoder", MEDIA_MIMETYPE_VIDEO_MPEG4}, + {"c2.android.h263.decoder", MEDIA_MIMETYPE_VIDEO_H263}}; + } // namespace android #endif // FUZZER_MEDIAMIMETYPES_H_ diff --git a/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9 b/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9 new file mode 100644 index 0000000000..652581f591 Binary files /dev/null and b/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9 differ diff --git a/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc b/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc new file mode 100644 index 0000000000..60ca169be9 Binary files /dev/null and b/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc differ diff --git a/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e b/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e new file mode 100644 index 0000000000..c03bcadc61 Binary files /dev/null and b/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e differ diff --git a/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0 b/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0 new file mode 100644 index 0000000000..52f2d5abf7 Binary files /dev/null and b/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0 differ diff --git a/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca b/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca new file mode 100644 index 0000000000..83c522f291 Binary files /dev/null and b/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca differ diff --git a/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456 b/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456 new file mode 100644 index 0000000000..62d259b81b Binary files /dev/null and b/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456 differ diff --git a/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774 b/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774 new file mode 100644 index 0000000000..db78b75b34 Binary files /dev/null and b/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774 differ diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 657f2a569c..878ab9f7f6 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -1378,6 +1378,11 @@ status_t EffectModule::setVolume(uint32_t* left, uint32_t* right, bool controlle status_t EffectModule::setVolumeInternal( uint32_t *left, uint32_t *right, bool controller) { if (mVolume.has_value() && *left == mVolume.value()[0] && *right == mVolume.value()[1]) { + LOG_ALWAYS_FATAL_IF( + !mReturnedVolume.has_value(), + "The cached returned volume must not be null when the cached volume has value"); + *left = mReturnedVolume.value()[0]; + *right = mReturnedVolume.value()[1]; return NO_ERROR; } LOG_ALWAYS_FATAL_IF(mEffectInterface == nullptr, "%s", mEffectInterfaceDebug.c_str()); @@ -1393,6 +1398,7 @@ status_t EffectModule::setVolumeInternal( mVolume = {*left, *right}; // Cache the value that has been set *left = volume[0]; *right = volume[1]; + mReturnedVolume = {*left, *right}; } return status; } diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h index 64a4e6209e..b516c37e04 100644 --- a/services/audioflinger/Effects.h +++ b/services/audioflinger/Effects.h @@ -307,7 +307,11 @@ class EffectModule : public IAfEffectModule, public EffectBase { // this tid is allowed to call setVolume() without acquiring the mutex. pid_t mSetVolumeReentrantTid = INVALID_PID; + // Cache the volume that has been set successfully. std::optional> mVolume; + // Cache the volume that returned from the effect when setting volume successfully. The value + // here is used to indicate the volume to apply before this effect. + std::optional> mReturnedVolume; // TODO: b/315995877, remove this debugging string after root cause std::string mEffectInterfaceDebug; }; diff --git a/services/audiopolicy/fuzzer/aidl/audiopolicy_aidl_fuzzer.cpp b/services/audiopolicy/fuzzer/aidl/audiopolicy_aidl_fuzzer.cpp index d582062368..f5e72f5620 100644 --- a/services/audiopolicy/fuzzer/aidl/audiopolicy_aidl_fuzzer.cpp +++ b/services/audiopolicy/fuzzer/aidl/audiopolicy_aidl_fuzzer.cpp @@ -38,6 +38,7 @@ using android::fuzzService; [[clang::no_destroy]] static std::once_flag gSmOnce; sp gFakeServiceManager; +sp gAudioPolicyService; bool addService(const String16& serviceName, const sp& fakeServiceManager, FuzzedDataProvider& fdp) { @@ -49,22 +50,10 @@ bool addService(const String16& serviceName, const sp& fakeS return true; } -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp(data, size); - - std::call_once(gSmOnce, [&] { - /* Create a FakeServiceManager instance and add required services */ - gFakeServiceManager = sp::make(); - setDefaultServiceManager(gFakeServiceManager); - }); - gFakeServiceManager->clear(); - - for (const char* service : {"activity", "sensor_privacy", "permission", "scheduling_policy", - "batterystats", "media.metrics"}) { - if (!addService(String16(service), gFakeServiceManager, fdp)) { - return 0; - } - } +extern "C" int LLVMFuzzerInitialize(int* /*argc*/, char*** /*argv*/) { + /* Create a FakeServiceManager instance and add required services */ + gFakeServiceManager = sp::make(); + setDefaultServiceManager(gFakeServiceManager); auto configService = ndk::SharedRefBase::make(); CHECK_EQ(NO_ERROR, AServiceManager_addService(configService.get()->asBinder().get(), @@ -82,22 +71,37 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Disable creating thread pool for fuzzer instance of audio flinger and audio policy services AudioSystem::disableThreadPool(); - const auto audioFlinger = sp::make(); - const auto afAdapter = sp::make(audioFlinger); + return 0; +} - CHECK_EQ(NO_ERROR, - gFakeServiceManager->addService( - String16(IAudioFlinger::DEFAULT_SERVICE_NAME), IInterface::asBinder(afAdapter), - false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); - const auto audioPolicyService = sp::make(); + for (const char* service : {"activity", "sensor_privacy", "permission", "scheduling_policy", + "batterystats", "media.metrics"}) { + if (!addService(String16(service), gFakeServiceManager, fdp)) { + return 0; + } + } - CHECK_EQ(NO_ERROR, - gFakeServiceManager->addService(String16("media.audio_policy"), audioPolicyService, - false /* allowIsolated */, - IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)); + // TODO(330882064) : Initialise Audio Flinger and Audio Policy services every time + std::call_once(gSmOnce, [&] { + const auto audioFlinger = sp::make(); + const auto audioFlingerServerAdapter = sp::make(audioFlinger); + CHECK_EQ(NO_ERROR, + gFakeServiceManager->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME), + IInterface::asBinder(audioFlingerServerAdapter), + false /* allowIsolated */, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)); + + gAudioPolicyService = sp::make(); + CHECK_EQ(NO_ERROR, + gFakeServiceManager->addService(String16("media.audio_policy"), + gAudioPolicyService, false /* allowIsolated */, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)); + }); - fuzzService(media::IAudioPolicyService::asBinder(audioPolicyService), std::move(fdp)); + fuzzService(media::IAudioPolicyService::asBinder(gAudioPolicyService), std::move(fdp)); return 0; } diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index a0e3aa69bf..9ae1a648c5 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -168,8 +168,8 @@ void AudioPolicyManager::broadcastDeviceConnectionState(const sptoAudioPort(&devicePort); if (status_t status = mpClientInterface->setDeviceConnectedState(&devicePort, state); status != OK) { - ALOGE("Error %d while setting connected state for device %s", - static_cast(state), + ALOGE("Error %d while setting connected state %d for device %s", + status, static_cast(state), device->getDeviceTypeAddr().toString(false).c_str()); } } @@ -257,9 +257,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp& device, + uint32_t * latencyMs, + audio_output_flags_t flags) override { + return mSimulateFailure ? BAD_VALUE : + AudioPolicyManagerTestClient::openOutput( + module, output, halConfig, mixerConfig, device, latencyMs, flags); + } + + status_t openInput(audio_module_handle_t module, + audio_io_handle_t *input, + audio_config_t * config, + audio_devices_t * device, + const String8 & address, + audio_source_t source, + audio_input_flags_t flags) override { + return mSimulateFailure ? BAD_VALUE : + AudioPolicyManagerTestClient::openInput( + module, input, config, device, address, source, flags); + } + + void setSimulateFailure(bool simulateFailure) { mSimulateFailure = simulateFailure; } + + private: + bool mSimulateFailure = false; +}; + +} // namespace + +using DeviceConnectionWithFormatTestParams = + std::tuple; + +class AudioPolicyManagerTestDeviceConnectionFailed : + public AudioPolicyManagerTestWithConfigurationFile, + public testing::WithParamInterface { + protected: + std::string getConfigFile() override { return sBluetoothConfig; } + AudioPolicyManagerTestClient* getClient() override { + mFullClient = new AudioPolicyManagerTestClientOpenFails; + return mFullClient; + } + void setSimulateOpenFailure(bool simulateFailure) { + mFullClient->setSimulateFailure(simulateFailure); } + + static const std::string sBluetoothConfig; + + private: + AudioPolicyManagerTestClientOpenFails* mFullClient; +}; + +const std::string AudioPolicyManagerTestDeviceConnectionFailed::sBluetoothConfig = + AudioPolicyManagerTestDeviceConnectionFailed::sExecutableDir + + "test_audio_policy_configuration_bluetooth.xml"; + +TEST_P(AudioPolicyManagerTestDeviceConnectionFailed, SetDeviceConnectedStateHasAddress) { + const audio_devices_t type = std::get<0>(GetParam()); + const std::string name = std::get<1>(GetParam()); + const std::string address = std::get<2>(GetParam()); + const audio_format_t format = std::get<3>(GetParam()); + + EXPECT_EQ(0, mClient->getConnectedDevicePortCount()); + EXPECT_EQ(0, mClient->getDisconnectedDevicePortCount()); + + setSimulateOpenFailure(true); + ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState( + type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE, + address.c_str(), name.c_str(), format)); + + // Since the failure happens when opening input/output, the device must be connected + // first and then disconnected. + EXPECT_EQ(1, mClient->getConnectedDevicePortCount()); + EXPECT_EQ(1, mClient->getDisconnectedDevicePortCount()); + + if (mClient->getConnectedDevicePortCount() > 0) { + auto port = mClient->getLastConnectedDevicePort(); + EXPECT_EQ(type, port->ext.device.type); + EXPECT_EQ(0, strncmp(port->ext.device.address, address.c_str(), + AUDIO_DEVICE_MAX_ADDRESS_LEN)) << "\"" << port->ext.device.address << "\""; + } + if (mClient->getDisconnectedDevicePortCount() > 0) { + auto port = mClient->getLastDisconnectedDevicePort(); + EXPECT_EQ(type, port->ext.device.type); + EXPECT_EQ(0, strncmp(port->ext.device.address, address.c_str(), + AUDIO_DEVICE_MAX_ADDRESS_LEN)) << "\"" << port->ext.device.address << "\""; + } +} + +INSTANTIATE_TEST_CASE_P( + DeviceConnectionFailure, + AudioPolicyManagerTestDeviceConnectionFailed, + testing::Values( + DeviceConnectionWithFormatTestParams({AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, + "bt_hfp_in", "00:11:22:33:44:55", AUDIO_FORMAT_DEFAULT}), + DeviceConnectionWithFormatTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_SCO, + "bt_hfp_out", "00:11:22:33:44:55", AUDIO_FORMAT_DEFAULT}), + DeviceConnectionWithFormatTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, + "bt_a2dp_out", "00:11:22:33:44:55", AUDIO_FORMAT_DEFAULT}), + DeviceConnectionWithFormatTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, + "bt_a2dp_out", "00:11:22:33:44:66", AUDIO_FORMAT_LDAC}) + ) + ); + class AudioPolicyManagerCarTest : public AudioPolicyManagerTestDynamicPolicy { protected: std::string getConfigFile() override { return sCarConfig; } @@ -3501,4 +3611,4 @@ TEST_F(AudioPolicyManagerPreProcEffectTest, DeviceDisconnectWhileClientActive) { // unregister effect should succeed since effect shall have been restore on the client session ASSERT_EQ(NO_ERROR, mManager->unregisterEffect(effectId)); -} \ No newline at end of file +} diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp index abf72e0170..1c191f5711 100644 --- a/services/audiopolicy/tests/resources/Android.bp +++ b/services/audiopolicy/tests/resources/Android.bp @@ -12,6 +12,7 @@ filegroup { name: "audiopolicytest_configuration_files", srcs: [ "test_audio_policy_configuration.xml", + "test_audio_policy_configuration_bluetooth.xml", "test_audio_policy_primary_only_configuration.xml", "test_car_ap_atmos_offload_configuration.xml", "test_invalid_audio_policy_configuration.xml", diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration_bluetooth.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration_bluetooth.xml new file mode 100644 index 0000000000..0cf1688088 --- /dev/null +++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration_bluetooth.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + Speaker + Built-In Mic + + Speaker + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Remote Submix In + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h index 7965474780..0e1db5c9f7 100644 --- a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h +++ b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h @@ -77,12 +77,6 @@ std::map> static_api_level_to_keys{ {34, { ANDROID_CONTROL_AUTOFRAMING_AVAILABLE, ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES, - ANDROID_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE, - ANDROID_EFV_PADDING_ZOOM_FACTOR_RANGE, - ANDROID_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL, - ANDROID_FLASH_SINGLE_STRENGTH_MAX_LEVEL, - ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL, - ANDROID_FLASH_TORCH_STRENGTH_MAX_LEVEL, ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS, ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS, @@ -91,6 +85,15 @@ std::map> static_api_level_to_keys{ ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP, } }, + {35, { + ANDROID_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE, + ANDROID_EFV_PADDING_ZOOM_FACTOR_RANGE, + ANDROID_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL, + ANDROID_FLASH_SINGLE_STRENGTH_MAX_LEVEL, + ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL, + ANDROID_FLASH_TORCH_STRENGTH_MAX_LEVEL, + ANDROID_INFO_SESSION_CONFIGURATION_QUERY_VERSION, + } }, }; /** @@ -110,9 +113,14 @@ std::map> dynamic_api_level_to_keys{ {34, { ANDROID_CONTROL_AUTOFRAMING, ANDROID_CONTROL_AUTOFRAMING_STATE, - ANDROID_CONTROL_LOW_LIGHT_BOOST_STATE, ANDROID_CONTROL_SETTINGS_OVERRIDE, ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER, + ANDROID_EXTENSION_CURRENT_TYPE, + ANDROID_EXTENSION_STRENGTH, + ANDROID_SCALER_RAW_CROP_REGION, + } }, + {35, { + ANDROID_CONTROL_LOW_LIGHT_BOOST_STATE, ANDROID_EFV_AUTO_ZOOM, ANDROID_EFV_AUTO_ZOOM_PADDING_REGION, ANDROID_EFV_MAX_PADDING_ZOOM_FACTOR, @@ -122,11 +130,8 @@ std::map> dynamic_api_level_to_keys{ ANDROID_EFV_STABILIZATION_MODE, ANDROID_EFV_TARGET_COORDINATES, ANDROID_EFV_TRANSLATE_VIEWPORT, - ANDROID_EXTENSION_CURRENT_TYPE, - ANDROID_EXTENSION_STRENGTH, ANDROID_FLASH_STRENGTH_LEVEL, ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_SENSOR_CROP_REGION, - ANDROID_SCALER_RAW_CROP_REGION, ANDROID_STATISTICS_LENS_INTRINSIC_SAMPLES, ANDROID_STATISTICS_LENS_INTRINSIC_TIMESTAMPS, } }, diff --git a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp index 433332c17d..c6793a9b69 100644 --- a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp +++ b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp @@ -33,6 +33,8 @@ using namespace android; constexpr size_t kLogItemsLowWater = 1; // high water mark constexpr size_t kLogItemsHighWater = 2; +constexpr size_t kMaxItemLength = 16; +constexpr size_t kMaxApis = 64; class MediaMetricsServiceFuzzer { public: @@ -304,10 +306,11 @@ void MediaMetricsServiceFuzzer::invokeAnalyticsAction(const uint8_t *data, size_ } FuzzedDataProvider fdp2 = FuzzedDataProvider(data, size); - - while (fdp2.remaining_bytes()) { + size_t apiCount = 0; + while (fdp2.remaining_bytes() && ++apiCount <= kMaxApis) { // make a test item - auto item = std::make_shared(fdp2.ConsumeRandomLengthString().c_str()); + auto item = std::make_shared( + fdp2.ConsumeRandomLengthString(kMaxItemLength).c_str()); (*item).set("event", fdp2.ConsumeRandomLengthString().c_str()); // get the actions and execute them