Merge "Add YCBCR_P210 format" into main
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 6862cb1..d0df90b 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -22,6 +22,11 @@
default_applicable_licenses: ["frameworks_av_camera_license"],
}
+vintf_fragment {
+ name: "manifest_android.frameworks.cameraservice.service.xml",
+ src: "manifest_android.frameworks.cameraservice.service.xml",
+}
+
cc_binary {
name: "cameraserver",
@@ -61,7 +66,7 @@
init_rc: ["cameraserver.rc"],
- vintf_fragments: [
+ vintf_fragment_modules: [
"manifest_android.frameworks.cameraservice.service.xml",
],
}
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index 81c2003..cee44b9 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -78,9 +78,6 @@
"libselinux",
"libstagefright_foundation",
],
- whole_static_libs: [
- "libc++fs",
- ],
cflags: [
"-Wall",
@@ -127,7 +124,6 @@
],
static_libs: [
- "libc++fs",
"libmediautils",
"liblog",
"libdrmframeworkcommon",
diff --git a/drm/libdrmframework/plugins/passthru/Android.bp b/drm/libdrmframework/plugins/passthru/Android.bp
index 0a6cd47..6ac7188 100644
--- a/drm/libdrmframework/plugins/passthru/Android.bp
+++ b/drm/libdrmframework/plugins/passthru/Android.bp
@@ -45,9 +45,6 @@
"libdl",
"libdrmframeworkcommon",
],
- whole_static_libs: [
- "libc++fs",
- ],
local_include_dirs: ["include"],
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index cce6338..f46409f 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -133,6 +133,7 @@
required: [
"com.android.hardware.drm.clearkey",
],
+ vendor: true,
}
cc_defaults {
diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig
index ed53fe1..b5c7edf 100644
--- a/media/aconfig/codec_fwk.aconfig
+++ b/media/aconfig/codec_fwk.aconfig
@@ -13,6 +13,14 @@
}
flag {
+ name: "apv_support"
+ is_exported: true
+ namespace: "codec_fwk"
+ description: "Feature flag for Android support for APV Content"
+ bug: "375464302"
+}
+
+flag {
name: "codec_buffer_state_cleanup"
namespace: "codec_fwk"
description: "Bugfix flag for more buffer state cleanup in MediaCodec"
@@ -126,6 +134,13 @@
}
flag {
+ name: "rendering_depth_removal"
+ namespace: "codec_fwk"
+ description: "Feature flag for removing rendering depth"
+ bug: "275527219"
+}
+
+flag {
name: "secure_codecs_require_crypto"
namespace: "codec_fwk"
description: "Bugfix flag for requiring setting crypto for secure codecs"
diff --git a/media/codec2/components/aom/C2SoftAomEnc.cpp b/media/codec2/components/aom/C2SoftAomEnc.cpp
index 722b13a..93009c4 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.cpp
+++ b/media/codec2/components/aom/C2SoftAomEnc.cpp
@@ -466,6 +466,7 @@
aom_codec_err_t C2SoftAomEnc::setupCodecParameters() {
aom_codec_err_t codec_return = AOM_CODEC_OK;
+ const int maxIntraBitratePct = mBitrateControlMode == AOM_CBR ? 300 : 450;
codec_return = aom_codec_control(mCodecContext, AV1E_SET_TARGET_SEQ_LEVEL_IDX, mAV1EncLevel);
if (codec_return != AOM_CODEC_OK) goto BailOut;
@@ -492,6 +493,10 @@
codec_return = aom_codec_control(mCodecContext, AV1E_SET_AQ_MODE, 3);
if (codec_return != AOM_CODEC_OK) goto BailOut;
+ codec_return = aom_codec_control(mCodecContext, AOME_SET_MAX_INTRA_BITRATE_PCT,
+ maxIntraBitratePct);
+ if (codec_return != AOM_CODEC_OK) goto BailOut;
+
codec_return = aom_codec_control(mCodecContext, AV1E_SET_COEFF_COST_UPD_FREQ, 3);
if (codec_return != AOM_CODEC_OK) goto BailOut;
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index 562dcf5..52920c2 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -743,6 +743,25 @@
}
status_t C2SoftMpeg2Dec::deleteDecoder() {
+ // API call to IV_CMD_RETRIEVE_MEMREC not only retrieves the memory records
+ // but also joins active threads and destroys conditional thread variables and
+ // mutex locks for each thread.
+ iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
+ iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
+
+ s_retrieve_mem_ip.pv_mem_rec_location = (iv_mem_rec_t *)mMemRecords;
+ s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
+ s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
+ s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
+
+ IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
+ &s_retrieve_mem_ip,
+ &s_retrieve_mem_op);
+ if (IV_SUCCESS != status) {
+ ALOGE("error in %s: 0x%x", __func__, s_retrieve_mem_op.u4_error_code);
+ return UNKNOWN_ERROR;
+ }
+
if (mMemRecords) {
iv_mem_rec_t *ps_mem_rec = mMemRecords;
diff --git a/media/codec2/hal/common/include/codec2/common/BqPoolInvalidateHelper.h b/media/codec2/hal/common/include/codec2/common/BqPoolInvalidateHelper.h
new file mode 100644
index 0000000..859f703
--- /dev/null
+++ b/media/codec2/hal/common/include/codec2/common/BqPoolInvalidateHelper.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <C2BqBufferPriv.h>
+#include <C2PlatformSupport.h>
+
+namespace android {
+
+// filter fn from component's blockpool container to bqpool conatainer
+static inline bool BqPoolFilterFn(
+ std::pair<const uint64_t, std::shared_ptr<C2BlockPool>> pool) {
+ return (pool.second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE);
+}
+
+// convert fn from component's blockpool container to bqpool container
+static inline std::shared_ptr<C2BufferQueueBlockPool> BqPoolConvertFn(
+ std::pair<const uint64_t, std::shared_ptr<C2BlockPool>> pool) {
+ return std::static_pointer_cast<C2BufferQueueBlockPool>(pool.second);
+}
+
+// This is similar to std::transform excpet there is \pred functor parameter.
+// The elements with \pred function value \true only will be transformed and
+// added to the dest container. (For portability std::ranges are not used.)
+template <class InputIt, class OutputIt, class Pred, class Fct>
+void transform_if(InputIt first, InputIt last, OutputIt dest, Pred pred, Fct transform)
+{
+ while (first != last) {
+ if (pred(*first)) {
+ *dest++ = transform(*first);
+ }
+ ++first;
+ }
+}
+
+} // namespace android
diff --git a/media/codec2/hal/hidl/1.0/utils/Component.cpp b/media/codec2/hal/hidl/1.0/utils/Component.cpp
index 62f0e25..162a80e 100644
--- a/media/codec2/hal/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/Component.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "Codec2-Component"
#include <android-base/logging.h>
+#include <codec2/common/BqPoolInvalidateHelper.h>
#include <codec2/hidl/1.0/Component.h>
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.0/InputBufferManager.h>
@@ -30,6 +31,7 @@
#include <utils/Timers.h>
#include <C2BqBufferPriv.h>
+#include <C2BqPoolInvalidator.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
@@ -270,16 +272,17 @@
}
void Component::onDeathReceived() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mClientDied = true;
- 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->invalidate();
- }
- }
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ bqInvalidateItem->invalidate();
}
release();
}
@@ -549,7 +552,26 @@
}
Return<Status> Component::release() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ if (!mClientDied) {
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ }
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem;
+ if (!bqPools.empty()) {
+ // handling rare cases of process death just after release() called.
+ bqInvalidateItem = std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
Status status = static_cast<Status>(mComponent->release());
+ if (bqInvalidateItem) {
+ // If release is not blocked,
+ // skip invalidation and finish ASAP.
+ bqInvalidateItem->skip();
+ }
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mBlockPools.clear();
@@ -637,6 +659,18 @@
}
Component::~Component() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ LOG(ERROR) << "blockpools are not cleared yet at dtor";
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
InputBufferManager::unregisterFrameData(mListener);
mStore->reportComponentDeath(this);
}
diff --git a/media/codec2/hal/hidl/1.1/utils/Component.cpp b/media/codec2/hal/hidl/1.1/utils/Component.cpp
index 7f2c4dd..1c2a49a 100644
--- a/media/codec2/hal/hidl/1.1/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.1/utils/Component.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "Codec2-Component@1.1"
#include <android-base/logging.h>
+#include <codec2/common/BqPoolInvalidateHelper.h>
#include <codec2/hidl/1.1/Component.h>
#include <codec2/hidl/1.1/ComponentStore.h>
#include <codec2/hidl/1.1/InputBufferManager.h>
@@ -32,6 +33,7 @@
#include <codec2/common/MultiAccessUnitHelper.h>
#include <C2BqBufferPriv.h>
+#include <C2BqPoolInvalidator.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
@@ -274,16 +276,17 @@
}
void Component::onDeathReceived() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mClientDied = true;
- 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->invalidate();
- }
- }
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ bqInvalidateItem->invalidate();
}
release();
}
@@ -555,7 +558,26 @@
}
Return<Status> Component::release() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ if (!mClientDied) {
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ }
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem;
+ if (!bqPools.empty()) {
+ // handling rare cases of process death just after release() called.
+ bqInvalidateItem = std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
Status status = static_cast<Status>(mComponent->release());
+ if (bqInvalidateItem) {
+ // If release is not blocked,
+ // skip invalidation and finish ASAP.
+ bqInvalidateItem->skip();
+ }
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mBlockPools.clear();
@@ -649,6 +671,18 @@
}
Component::~Component() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ LOG(ERROR) << "blockpools are not cleared yet at dtor";
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
InputBufferManager::unregisterFrameData(mListener);
mStore->reportComponentDeath(this);
}
diff --git a/media/codec2/hal/hidl/1.2/utils/Component.cpp b/media/codec2/hal/hidl/1.2/utils/Component.cpp
index 7b0aa9b..a15febe 100644
--- a/media/codec2/hal/hidl/1.2/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.2/utils/Component.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "Codec2-Component@1.2"
#include <android-base/logging.h>
+#include <codec2/common/BqPoolInvalidateHelper.h>
#include <codec2/hidl/1.2/Component.h>
#include <codec2/hidl/1.2/ComponentStore.h>
#include <codec2/hidl/1.2/InputBufferManager.h>
@@ -30,6 +31,7 @@
#include <utils/Timers.h>
#include <C2BqBufferPriv.h>
+#include <C2BqPoolInvalidator.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
@@ -272,16 +274,17 @@
}
void Component::onDeathReceived() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mClientDied = true;
- 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->invalidate();
- }
- }
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ bqInvalidateItem->invalidate();
}
release();
}
@@ -551,7 +554,26 @@
}
Return<Status> Component::release() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ if (!mClientDied) {
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ }
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem;
+ if (!bqPools.empty()) {
+ // handling rare cases of process death just after release() called.
+ bqInvalidateItem = std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
Status status = static_cast<Status>(mComponent->release());
+ if (bqInvalidateItem) {
+ // If release is not blocked,
+ // skip invalidation and finish ASAP.
+ bqInvalidateItem->skip();
+ }
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mBlockPools.clear();
@@ -676,6 +698,18 @@
}
Component::~Component() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> bqPools;
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ transform_if(mBlockPools.begin(), mBlockPools.end(), std::back_inserter(bqPools),
+ BqPoolFilterFn, BqPoolConvertFn);
+ }
+ if (!bqPools.empty()) {
+ LOG(ERROR) << "blockpools are not cleared yet at dtor";
+ std::shared_ptr<C2BqPoolInvalidateItem> bqInvalidateItem =
+ std::make_shared<C2BqPoolInvalidateItem>(std::move(bqPools));
+ C2BqPoolInvalidator::getInstance().queue(bqInvalidateItem);
+ }
InputBufferManager::unregisterFrameData(mListener);
mStore->reportComponentDeath(this);
}
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 3c8c1b7..4f6fe51 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -46,6 +46,7 @@
],
static_libs: [
+ "libPlatformProperties",
"libSurfaceFlingerProperties",
"aconfig_mediacodec_flags_c_lib",
"android.media.codec-aconfig-cc",
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 3ef2f84..4353521 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -38,8 +38,10 @@
#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <android/hardware/drm/1.0/types.h>
+#include <android/sysprop/MediaProperties.sysprop.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
+#include <android-base/no_destructor.h>
#include <android-base/stringprintf.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryDealer.h>
@@ -114,6 +116,109 @@
});
}
+class SurfaceCallbackHandler {
+public:
+ enum callback_type_t {
+ ON_BUFFER_RELEASED = 0,
+ ON_BUFFER_ATTACHED
+ };
+
+ void post(callback_type_t callback,
+ std::shared_ptr<Codec2Client::Component> component,
+ uint32_t generation) {
+ if (!component) {
+ ALOGW("surface callback psoted for invalid component");
+ }
+ std::shared_ptr<SurfaceCallbackItem> item =
+ std::make_shared<SurfaceCallbackItem>(callback, component, generation);
+ std::unique_lock<std::mutex> lock(mMutex);
+ mItems.emplace_back(std::move(item));
+ mCv.notify_one();
+ }
+
+ ~SurfaceCallbackHandler() {
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mDone = true;
+ mCv.notify_all();
+ }
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+ }
+
+ static SurfaceCallbackHandler& GetInstance() {
+ static base::NoDestructor<SurfaceCallbackHandler> sSurfaceCallbackHandler{};
+ return *sSurfaceCallbackHandler;
+ }
+
+private:
+ struct SurfaceCallbackItem {
+ callback_type_t mCallback;
+ std::weak_ptr<Codec2Client::Component> mComp;
+ uint32_t mGeneration;
+
+ SurfaceCallbackItem(
+ callback_type_t callback,
+ std::shared_ptr<Codec2Client::Component> comp,
+ uint32_t generation)
+ : mCallback(callback), mComp(comp), mGeneration(generation) {}
+ };
+
+ SurfaceCallbackHandler() { mThread = std::thread(&SurfaceCallbackHandler::run, this); }
+
+ void run() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (!mDone) {
+ while (!mItems.empty()) {
+ std::deque<std::shared_ptr<SurfaceCallbackItem>> items = std::move(mItems);
+ mItems.clear();
+ lock.unlock();
+ handle(items);
+ lock.lock();
+ }
+ mCv.wait(lock);
+ }
+ }
+
+ void handle(std::deque<std::shared_ptr<SurfaceCallbackItem>> &items) {
+ while (!items.empty()) {
+ std::shared_ptr<SurfaceCallbackItem> item = items.front();
+ items.pop_front();
+ switch (item->mCallback) {
+ case ON_BUFFER_RELEASED: {
+ std::shared_ptr<Codec2Client::Component> comp = item->mComp.lock();;
+ if (comp) {
+ comp->onBufferReleasedFromOutputSurface(item->mGeneration);
+ }
+ break;
+ }
+ case ON_BUFFER_ATTACHED: {
+ std::shared_ptr<Codec2Client::Component> comp = item->mComp.lock();
+ if (comp) {
+ comp->onBufferAttachedToOutputSurface(item->mGeneration);
+ }
+ break;
+ }
+ default:
+ ALOGE("Non defined surface callback message");
+ break;
+ }
+ }
+ }
+
+ std::thread mThread;
+ bool mDone = false;
+ std::deque<std::shared_ptr<SurfaceCallbackItem>> mItems;
+ std::mutex mMutex;
+ std::condition_variable mCv;
+
+
+ friend class base::NoDestructor<SurfaceCallbackHandler>;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SurfaceCallbackHandler);
+};
+
} // namespace
CCodecBufferChannel::QueueGuard::QueueGuard(
@@ -207,8 +312,18 @@
Mutexed<BlockPools>::Locked pools(mBlockPools);
pools->outputPoolId = C2BlockPool::BASIC_LINEAR;
}
- std::string value = GetServerConfigurableFlag("media_native", "ccodec_rendering_depth", "3");
- android::base::ParseInt(value, &mRenderingDepth);
+ if (android::media::codec::provider_->rendering_depth_removal()) {
+ constexpr int kAndroidApi202404 = 202404;
+ int vendorVersion = ::android::base::GetIntProperty("ro.vendor.api_level", -1);
+ using ::android::sysprop::MediaProperties::codec2_remove_rendering_depth;
+ if (vendorVersion > kAndroidApi202404 || codec2_remove_rendering_depth().value_or(false)) {
+ mRenderingDepth = 0;
+ }
+ } else {
+ std::string value = GetServerConfigurableFlag(
+ "media_native", "ccodec_rendering_depth", "3");
+ android::base::ParseInt(value, &mRenderingDepth);
+ }
mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + mRenderingDepth;
}
@@ -1492,7 +1607,8 @@
// during this interface being executed.
std::shared_ptr<Codec2Client::Component> comp = mComponent;
if (comp) {
- comp->onBufferReleasedFromOutputSurface(generation);
+ SurfaceCallbackHandler::GetInstance().post(
+ SurfaceCallbackHandler::ON_BUFFER_RELEASED, comp, generation);
}
}
@@ -1503,7 +1619,8 @@
// during this interface being executed.
std::shared_ptr<Codec2Client::Component> comp = mComponent;
if (comp) {
- comp->onBufferAttachedToOutputSurface(generation);
+ SurfaceCallbackHandler::GetInstance().post(
+ SurfaceCallbackHandler::ON_BUFFER_ATTACHED, comp, generation);
}
}
@@ -1790,6 +1907,7 @@
outputSurface = output->surface ?
output->surface->getIGraphicBufferProducer() : nullptr;
if (outputSurface) {
+ (void)SurfaceCallbackHandler::GetInstance();
output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
}
outputGeneration = output->generation;
@@ -2052,6 +2170,14 @@
status_t CCodecBufferChannel::requestInitialInputBuffers(
std::map<size_t, sp<MediaCodecBuffer>> &&clientInputBuffers) {
+ std::optional<QueueGuard> guard;
+ if (android::media::codec::provider_->codec_buffer_state_cleanup()) {
+ guard.emplace(mSync);
+ if (!guard->isRunning()) {
+ ALOGD("[%s] skip requestInitialInputBuffers when not running", mName);
+ return OK;
+ }
+ }
C2StreamBufferTypeSetting::output oStreamFormat(0u);
C2PrependHeaderModeSetting prepend(PREPEND_HEADER_TO_NONE);
c2_status_t err = mComponent->query({ &oStreamFormat, &prepend }, {}, C2_DONT_BLOCK, nullptr);
@@ -2708,6 +2834,7 @@
oldSurface = outputSurface->surface;
}
if (newSurface) {
+ (void)SurfaceCallbackHandler::GetInstance();
newSurface->setScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
newSurface->setDequeueTimeout(kDequeueTimeoutNs);
newSurface->setMaxDequeuedBufferCount(maxDequeueCount);
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index dc06ee6..9d1cbff 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -53,7 +53,7 @@
],
defaults: [
- "aconfig_lib_cc_static_link.defaults",
+ "aconfig_lib_cc_static_link.defaults",
"libcodec2_hal_selection",
],
@@ -68,6 +68,7 @@
"C2PlatformStorePluginLoader.cpp",
"C2Store.cpp",
"platform/C2BqBuffer.cpp",
+ "platform/C2BqPoolInvalidator.cpp",
"platform/C2SurfaceSyncObj.cpp",
"platform/C2IgbaBuffer.cpp",
"types.cpp",
diff --git a/media/codec2/vndk/include/C2BqPoolInvalidator.h b/media/codec2/vndk/include/C2BqPoolInvalidator.h
new file mode 100644
index 0000000..612d023
--- /dev/null
+++ b/media/codec2/vndk/include/C2BqPoolInvalidator.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/no_destructor.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#include <condition_variable>
+#include <deque>
+#include <list>
+#include <memory>
+#include <thread>
+
+class C2BufferQueueBlockPool;
+
+namespace android {
+
+/**
+ * Container class in order to invalidate C2BufferQueueBlockPool(s) and their resources
+ * when the client process is dead abruptly.
+ */
+class C2BqPoolInvalidateItem {
+public:
+
+ /**
+ * invalidate contained C2BufferQueueBlockPool(s) and their resources
+ */
+ void invalidate();
+
+ /**
+ * skip invalidate(), if it is scheduled and not yet invalidated.
+ */
+ void skip();
+
+ /**
+ * returns whether invalidate() is reuqired or not.
+ */
+ bool needsInvalidate();
+
+ C2BqPoolInvalidateItem(std::list<std::shared_ptr<C2BufferQueueBlockPool>> &&pools);
+
+ ~C2BqPoolInvalidateItem() = default;
+private:
+
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> mPools;
+ bool mNeedsInvalidate;
+ std::mutex mLock;
+
+ DISALLOW_EVIL_CONSTRUCTORS(C2BqPoolInvalidateItem);
+};
+
+/**
+ * Asynchronous C2BufferQueueBlockPool invalidator.
+ *
+ * this has C2BqPoolInvalidateItem inside. and call invalidate() from a separate
+ * thread asynchronously.
+ */
+class C2BqPoolInvalidator {
+public:
+ /**
+ * This gets the singleton instance of the class.
+ */
+ static C2BqPoolInvalidator &getInstance();
+
+ /**
+ * queue invalidation items. the item will be invalidated after certain
+ * amount of delay from a separate thread.
+ */
+ void queue(std::shared_ptr<C2BqPoolInvalidateItem> &item);
+
+ ~C2BqPoolInvalidator();
+private:
+
+ C2BqPoolInvalidator();
+
+ void run();
+
+ std::thread mThread;
+ bool mDone;
+
+ std::mutex mMutex;
+ std::condition_variable mCv;
+
+ std::deque<std::pair<int64_t, std::shared_ptr<C2BqPoolInvalidateItem>>> mItems;
+
+ friend class ::android::base::NoDestructor<C2BqPoolInvalidator>;
+
+ DISALLOW_EVIL_CONSTRUCTORS(C2BqPoolInvalidator);
+};
+
+} // namespace android
diff --git a/media/codec2/vndk/platform/C2BqPoolInvalidator.cpp b/media/codec2/vndk/platform/C2BqPoolInvalidator.cpp
new file mode 100644
index 0000000..2666cd3
--- /dev/null
+++ b/media/codec2/vndk/platform/C2BqPoolInvalidator.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "C2BqPoolInvalidator"
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <C2BqBufferPriv.h>
+#include <C2BqPoolInvalidator.h>
+
+namespace android {
+
+namespace {
+ static constexpr int64_t kBqPoolInvalidateDelayMs = 1000;
+} // anonymous namespace
+
+C2BqPoolInvalidateItem::C2BqPoolInvalidateItem(
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> &&pools) : mPools(std::move(pools)) {
+ if (!mPools.empty()) {
+ mNeedsInvalidate = true;
+ } else {
+ mNeedsInvalidate = false;
+ }
+}
+
+void C2BqPoolInvalidateItem::invalidate() {
+ std::list<std::shared_ptr<C2BufferQueueBlockPool>> pools;
+ {
+ std::unique_lock<std::mutex> l(mLock);
+ if (!mNeedsInvalidate) {
+ return;
+ }
+ pools = std::move(mPools);
+ mNeedsInvalidate = false;
+ }
+ for(auto it = pools.begin(); it != pools.end(); ++it) {
+ (*it)->invalidate();
+ }
+}
+
+void C2BqPoolInvalidateItem::skip() {
+ std::unique_lock<std::mutex> l(mLock);
+ mNeedsInvalidate = false;
+ mPools.clear();
+}
+
+bool C2BqPoolInvalidateItem::needsInvalidate() {
+ std::unique_lock<std::mutex> l(mLock);
+ return mNeedsInvalidate;
+}
+
+C2BqPoolInvalidator &C2BqPoolInvalidator::getInstance() {
+ static android::base::NoDestructor<C2BqPoolInvalidator> sInvalidator;
+ return *sInvalidator;
+}
+
+C2BqPoolInvalidator::C2BqPoolInvalidator() : mDone(false) {
+ mThread = std::thread(&C2BqPoolInvalidator::run, this);
+}
+
+C2BqPoolInvalidator::~C2BqPoolInvalidator() {
+ {
+ std::unique_lock<std::mutex> l(mMutex);
+ mDone = true;
+ mCv.notify_one();
+ }
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void C2BqPoolInvalidator::queue(std::shared_ptr<C2BqPoolInvalidateItem> &item) {
+ std::unique_lock<std::mutex> l(mMutex);
+ std::pair<int64_t, std::shared_ptr<C2BqPoolInvalidateItem>> p =
+ std::make_pair(::android::elapsedRealtime() + kBqPoolInvalidateDelayMs, item);
+ mItems.push_back(p);
+ mCv.notify_one();
+}
+
+void C2BqPoolInvalidator::run() {
+ while(true) {
+ int64_t nowMs = ::android::elapsedRealtime();
+ std::unique_lock<std::mutex> l(mMutex);
+ if (mDone) {
+ break;
+ }
+ std::list<std::shared_ptr<C2BqPoolInvalidateItem>> items;
+ while (!mItems.empty()) {
+ if (mItems.front().first <= nowMs) {
+ items.push_back(mItems.front().second);
+ mItems.pop_front();
+ } else {
+ break;
+ }
+ }
+ if (items.empty()) {
+ if (mItems.empty()) {
+ mCv.wait(l);
+ } else {
+ int64_t nextMs = mItems.front().first;
+ if (nextMs > nowMs) {
+ mCv.wait_for(l, std::chrono::milliseconds(nextMs - nowMs));
+ }
+ }
+ } else {
+ l.unlock();
+ int invalidated = 0;
+ for (auto it = items.begin(); it != items.end(); ++it, ++invalidated) {
+ (*it)->invalidate();
+ }
+ ALOGD("invalidated %d bqpool items", invalidated);
+ }
+ }
+}
+
+} // android
diff --git a/media/janitors/media_solutions_OWNERS b/media/janitors/media_solutions_OWNERS
index 17bc7dd..3243726 100644
--- a/media/janitors/media_solutions_OWNERS
+++ b/media/janitors/media_solutions_OWNERS
@@ -1,22 +1,18 @@
# Bug component: 1344
# go/android-fwk-media-solutions for info on areas of ownership.
-# MediaRouter and native mirroring only:
-adadukin@google.com
-aquilescanta@google.com
-bishoygendy@google.com
-ivanbuper@google.com
-
-# MediaMuxer, MediaRecorder, and seamless transcoding only:
andrewlewis@google.com
-claincly@google.com
-
-# Everything in go/android-fwk-media-solutions not covered above:
bachinger@google.com
-christosts@google.com
+claincly@google.com
ibaker@google.com
+ivanbuper@google.com
jbibik@google.com
michaelkatz@google.com
rohks@google.com
+sheenachhabra@google.com
+simakova@google.com
tianyifeng@google.com
tonihei@google.com
+
+# MediaRouter and native mirroring only:
+aquilescanta@google.com
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index ba231c1..b369a62 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -66,6 +66,7 @@
"libmedia_helper",
"libmediametrics",
"libprocessgroup",
+ "libprocessgroup_util",
"mediametricsservice-aidl-cpp",
"shared-file-region-aidl-cpp",
],
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index a1d5b2b..8c330d4 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -1141,11 +1141,10 @@
// start of lock scope
AutoMutex lock(mLock);
- uint32_t newSequence = mSequence;
// did previous obtainBuffer() fail due to media server death or voluntary invalidation?
if (status == DEAD_OBJECT) {
// re-create track, unless someone else has already done so
- if (newSequence == oldSequence) {
+ if (mSequence == oldSequence) {
if (!audio_is_linear_pcm(mFormat)) {
// If compressed capture, don't attempt to restore the track.
// Return a DEAD_OBJECT error and let the caller recreate.
@@ -1161,7 +1160,7 @@
}
}
}
- oldSequence = newSequence;
+ oldSequence = mSequence;
// Keep the extra references
proxy = mProxy;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index f92103b..ecf7436 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2209,11 +2209,10 @@
{ // start of lock scope
AutoMutex lock(mLock);
- uint32_t newSequence = mSequence;
// did previous obtainBuffer() fail due to media server death or voluntary invalidation?
if (status == DEAD_OBJECT) {
// re-create track, unless someone else has already done so
- if (newSequence == oldSequence) {
+ if (mSequence == oldSequence) {
status = restoreTrack_l("obtainBuffer");
if (status != NO_ERROR) {
buffer.mFrameCount = 0;
@@ -2223,7 +2222,7 @@
}
}
}
- oldSequence = newSequence;
+ oldSequence = mSequence;
if (status == NOT_ENOUGH_DATA) {
restartIfDisabled();
diff --git a/media/libaudioclient/aidl/fuzzer/Android.bp b/media/libaudioclient/aidl/fuzzer/Android.bp
index 61d5ccd..a215c0b 100644
--- a/media/libaudioclient/aidl/fuzzer/Android.bp
+++ b/media/libaudioclient/aidl/fuzzer/Android.bp
@@ -30,6 +30,7 @@
"libjsoncpp",
"libmediametricsservice",
"libprocessgroup",
+ "libprocessgroup_util",
"shared-file-region-aidl-cpp",
],
shared_libs: [
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index a95c700..8bca8df 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -46,6 +46,7 @@
"libmediametrics",
"libmediametricsservice",
"libprocessgroup",
+ "libprocessgroup_util",
"shared-file-region-aidl-cpp",
],
shared_libs: [
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 75e2c11..74a64bf 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -23,7 +23,6 @@
],
required: [
- "libaudiohal@5.0",
"libaudiohal@6.0",
"libaudiohal@7.0",
"libaudiohal@7.1",
diff --git a/media/libaudiohal/FactoryHal.cpp b/media/libaudiohal/FactoryHal.cpp
index 15cb297..2c30693 100644
--- a/media/libaudiohal/FactoryHal.cpp
+++ b/media/libaudiohal/FactoryHal.cpp
@@ -50,12 +50,11 @@
* This list need to keep sync with AudioHalVersionInfo.VERSIONS in
* media/java/android/media/AudioHalVersionInfo.java.
*/
-static const std::array<AudioHalVersionInfo, 5> sAudioHALVersions = {
+static const std::array<AudioHalVersionInfo, 4> sAudioHALVersions = {
AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, 1, 0),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 0),
AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0),
- AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 5, 0),
};
static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 1a6b949..f5dec56 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -83,32 +83,6 @@
}
cc_library_shared {
- name: "libaudiohal@5.0",
- defaults: [
- "libaudiohal_default",
- "libaudiohal_hidl_default",
- ],
- srcs: [
- ":audio_core_hal_client_sources",
- ":audio_effect_hidl_hal_client_sources",
- "EffectsFactoryHalEntry.cpp",
- ],
- shared_libs: [
- "android.hardware.audio.common@5.0",
- "android.hardware.audio.common@5.0-util",
- "android.hardware.audio.effect@5.0",
- "android.hardware.audio.effect@5.0-util",
- "android.hardware.audio@5.0",
- "android.hardware.audio@5.0-util",
- ],
- cflags: [
- "-DMAJOR_VERSION=5",
- "-DMINOR_VERSION=0",
- "-include common/all-versions/VersionMacro.h",
- ],
-}
-
-cc_library_shared {
name: "libaudiohal@6.0",
defaults: [
"libaudiohal_default",
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index d65701a..0d65f8c 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -367,8 +367,12 @@
if (!mStream) return NO_INIT;
StreamDescriptor::Reply reply;
RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply, statePositions));
- *frames = std::max<int64_t>(0, reply.observable.frames);
- *timestamp = std::max<int64_t>(0, reply.observable.timeNs);
+ if (reply.observable.frames == StreamDescriptor::Position::UNKNOWN ||
+ reply.observable.timeNs == StreamDescriptor::Position::UNKNOWN) {
+ return INVALID_OPERATION;
+ }
+ *frames = reply.observable.frames;
+ *timestamp = reply.observable.timeNs;
return OK;
}
@@ -377,8 +381,12 @@
if (!mStream) return NO_INIT;
StreamDescriptor::Reply reply;
RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
- *frames = std::max<int64_t>(0, reply.hardware.frames);
- *timestamp = std::max<int64_t>(0, reply.hardware.timeNs);
+ if (reply.hardware.frames == StreamDescriptor::Position::UNKNOWN ||
+ reply.hardware.timeNs == StreamDescriptor::Position::UNKNOWN) {
+ return INVALID_OPERATION;
+ }
+ *frames = reply.hardware.frames;
+ *timestamp = reply.hardware.timeNs;
return OK;
}
@@ -387,7 +395,10 @@
if (!mStream) return NO_INIT;
StreamDescriptor::Reply reply;
RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
- *frames = std::max<int32_t>(0, reply.xrunFrames);
+ if (reply.xrunFrames == StreamDescriptor::Position::UNKNOWN) {
+ return INVALID_OPERATION;
+ }
+ *frames = reply.xrunFrames;
return OK;
}
@@ -443,9 +454,29 @@
if (!mStream) return NO_INIT;
if (const auto state = getState(); isInPlayOrRecordState(state)) {
- return sendCommand(
- makeHalCommand<HalCommand::Tag::pause>(), reply,
+ StreamDescriptor::Reply localReply{};
+ StreamDescriptor::Reply* innerReply = reply ?: &localReply;
+ auto status = sendCommand(
+ makeHalCommand<HalCommand::Tag::pause>(), innerReply,
true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
+ if (status == STATUS_INVALID_OPERATION &&
+ !isInPlayOrRecordState(innerReply->state)) {
+ /**
+ * In case of transient states like DRAINING, the HAL may change its
+ * StreamDescriptor::State on its own and may not be in synchronization with client.
+ * Thus, client can send the unexpected command and HAL returns failure. such failure is
+ * natural. The client handles it gracefully.
+ * Example where HAL change its state,
+ * 1) DRAINING -> IDLE (on empty buffer)
+ * 2) DRAINING -> IDLE (on IStreamCallback::onDrainReady)
+ **/
+ AUGMENT_LOG(D,
+ "HAL failed to handle the 'pause' command, but stream state is in one of"
+ " the PAUSED kind of states, current state: %s",
+ toString(state).c_str());
+ return OK;
+ }
+ return status;
} else {
AUGMENT_LOG(D, "already stream in one of the PAUSED kind of states, current state: %s",
toString(state).c_str());
@@ -473,13 +504,9 @@
return INVALID_OPERATION;
}
return OK;
- } else if (state == StreamDescriptor::State::PAUSED ||
- state == StreamDescriptor::State::TRANSFER_PAUSED ||
- state == StreamDescriptor::State::DRAIN_PAUSED) {
+ } else if (isInPausedState(state)) {
return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
- } else if (state == StreamDescriptor::State::ACTIVE ||
- state == StreamDescriptor::State::TRANSFERRING ||
- state == StreamDescriptor::State::DRAINING) {
+ } else if (isInPlayOrRecordState(state)) {
AUGMENT_LOG(D, "already in stream state: %s", toString(state).c_str());
return OK;
} else {
@@ -528,7 +555,14 @@
}
void StreamHalAidl::onAsyncTransferReady() {
- if (auto state = getState(); state == StreamDescriptor::State::TRANSFERRING) {
+ StreamDescriptor::State state;
+ {
+ // Use 'mCommandReplyLock' to ensure that 'sendCommand' has finished updating the state
+ // after the reply from the 'burst' command.
+ std::lock_guard l(mCommandReplyLock);
+ state = getState();
+ }
+ if (state == StreamDescriptor::State::TRANSFERRING) {
// Retrieve the current state together with position counters unconditionally
// to ensure that the state on our side gets updated.
sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(),
@@ -539,7 +573,14 @@
}
void StreamHalAidl::onAsyncDrainReady() {
- if (auto state = getState(); state == StreamDescriptor::State::DRAINING) {
+ StreamDescriptor::State state;
+ {
+ // Use 'mCommandReplyLock' to ensure that 'sendCommand' has finished updating the state
+ // after the reply from the 'drain' command.
+ std::lock_guard l(mCommandReplyLock);
+ state = getState();
+ }
+ if (state == StreamDescriptor::State::DRAINING) {
// Retrieve the current state together with position counters unconditionally
// to ensure that the state on our side gets updated.
sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), nullptr,
@@ -547,7 +588,9 @@
// For compatibility with HIDL behavior, apply a "soft" position reset
// after receiving the "drain ready" callback.
std::lock_guard l(mLock);
- mStatePositions.framesAtFlushOrDrain = mLastReply.observable.frames;
+ if (mLastReply.observable.frames != StreamDescriptor::Position::UNKNOWN) {
+ mStatePositions.framesAtFlushOrDrain = mLastReply.observable.frames;
+ }
} else {
AUGMENT_LOG(W, "unexpected onDrainReady in the state %s", toString(state).c_str());
}
@@ -640,7 +683,8 @@
}
mLastReply = *reply;
mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs;
- if (!mIsInput && reply->status == STATUS_OK) {
+ if (!mIsInput && reply->status == STATUS_OK &&
+ reply->observable.frames != StreamDescriptor::Position::UNKNOWN) {
if (command.getTag() == StreamDescriptor::Command::standby &&
reply->state == StreamDescriptor::State::STANDBY) {
mStatePositions.framesAtStandby = reply->observable.frames;
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index fd4e615..dd14ac2 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -52,6 +52,7 @@
if (mDpFreq != nullptr) {
mDpFreq->reset();
}
+ mEngineInited = false;
return RetCode::SUCCESS;
}
diff --git a/media/libmedia/AudioCapabilities.cpp b/media/libmedia/AudioCapabilities.cpp
index e8cf517..1a92307 100644
--- a/media/libmedia/AudioCapabilities.cpp
+++ b/media/libmedia/AudioCapabilities.cpp
@@ -26,7 +26,7 @@
namespace android {
-const Range<int>& AudioCapabilities::getBitrateRange() const {
+const Range<int32_t>& AudioCapabilities::getBitrateRange() const {
return mBitrateRange;
}
@@ -86,7 +86,7 @@
}
void AudioCapabilities::initWithPlatformLimits() {
- mBitrateRange = Range<int>(0, INT_MAX);
+ mBitrateRange = Range<int>(0, INT32_MAX);
mInputChannelRanges.push_back(Range<int>(1, MAX_INPUT_CHANNEL_COUNT));
const int minSampleRate = base::GetIntProperty("ro.mediacodec.min_sample_rate", 7350);
@@ -94,30 +94,31 @@
mSampleRateRanges.push_back(Range<int>(minSampleRate, maxSampleRate));
}
-bool AudioCapabilities::supports(int sampleRate, int inputChannels) {
+bool AudioCapabilities::supports(std::optional<int> sampleRate,
+ std::optional<int> inputChannels) {
// channels and sample rates are checked orthogonally
- if (inputChannels != 0
+ if (inputChannels
&& !std::any_of(mInputChannelRanges.begin(), mInputChannelRanges.end(),
- [inputChannels](const Range<int> &a) { return a.contains(inputChannels); })) {
+ [inputChannels](const Range<int> &a) { return a.contains(inputChannels.value()); })) {
return false;
}
- if (sampleRate != 0
+ if (sampleRate
&& !std::any_of(mSampleRateRanges.begin(), mSampleRateRanges.end(),
- [sampleRate](const Range<int> &a) { return a.contains(sampleRate); })) {
+ [sampleRate](const Range<int> &a) { return a.contains(sampleRate.value()); })) {
return false;
}
return true;
}
bool AudioCapabilities::isSampleRateSupported(int sampleRate) {
- return supports(sampleRate, 0);
+ return supports(std::make_optional<int>(sampleRate), std::nullopt);
}
void AudioCapabilities::limitSampleRates(std::vector<int> rates) {
std::vector<Range<int>> sampleRateRanges;
std::sort(rates.begin(), rates.end());
for (int rate : rates) {
- if (supports(rate, 0 /* channels */)) {
+ if (supports(std::make_optional<int>(rate), std::nullopt /* channels */)) {
sampleRateRanges.push_back(Range<int>(rate, rate));
}
}
@@ -280,7 +281,7 @@
void AudioCapabilities::applyLimits(
const std::vector<Range<int>> &inputChannels,
- const std::optional<Range<int>> &bitRates) {
+ const std::optional<Range<int32_t>> &bitRates) {
// clamp & make a local copy
std::vector<Range<int>> inputChannelsCopy(inputChannels.size());
for (int i = 0; i < inputChannels.size(); i++) {
@@ -301,7 +302,7 @@
void AudioCapabilities::parseFromInfo(const sp<AMessage> &format) {
int maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
std::vector<Range<int>> channels = { Range<int>(1, maxInputChannels) };
- std::optional<Range<int>> bitRates = POSITIVE_INTEGERS;
+ std::optional<Range<int32_t>> bitRates = POSITIVE_INT32;
AString rateAString;
if (format->findString("sample-rate-ranges", &rateAString)) {
@@ -348,7 +349,7 @@
}
if (format->findString("bitrate-range", &valueStr)) {
- std::optional<Range<int>> parsedBitrate = ParseIntRange(valueStr.c_str());
+ std::optional<Range<int32_t>> parsedBitrate = ParseIntRange(valueStr.c_str());
if (parsedBitrate) {
bitRates = bitRates.value().intersect(parsedBitrate.value());
}
@@ -372,10 +373,12 @@
}
bool AudioCapabilities::supportsFormat(const sp<AMessage> &format) {
- int32_t sampleRate;
- format->findInt32(KEY_SAMPLE_RATE, &sampleRate);
- int32_t channels;
- format->findInt32(KEY_CHANNEL_COUNT, &channels);
+ int32_t sampleRateValue;
+ std::optional<int> sampleRate = format->findInt32(KEY_SAMPLE_RATE, &sampleRateValue)
+ ? std::make_optional<int>(sampleRateValue) : std::nullopt;
+ int32_t channelsValue;
+ std::optional<int> channels = format->findInt32(KEY_CHANNEL_COUNT, &channelsValue)
+ ? std::make_optional<int>(channelsValue) : std::nullopt;
if (!supports(sampleRate, channels)) {
return false;
diff --git a/media/libmedia/CodecCapabilities.cpp b/media/libmedia/CodecCapabilities.cpp
index 5bed1c4..87eb4bc 100644
--- a/media/libmedia/CodecCapabilities.cpp
+++ b/media/libmedia/CodecCapabilities.cpp
@@ -25,7 +25,7 @@
namespace android {
-bool CodecCapabilities::SupportsBitrate(Range<int> bitrateRange,
+bool CodecCapabilities::SupportsBitrate(Range<int32_t> bitrateRange,
const sp<AMessage> &format) {
// consider max bitrate over average bitrate for support
int32_t maxBitrate = 0;
diff --git a/media/libmedia/include/media/AudioCapabilities.h b/media/libmedia/include/media/AudioCapabilities.h
index 2bc3335..d2bd9d7 100644
--- a/media/libmedia/include/media/AudioCapabilities.h
+++ b/media/libmedia/include/media/AudioCapabilities.h
@@ -37,7 +37,7 @@
/**
* Returns the range of supported bitrates in bits/second.
*/
- const Range<int>& getBitrateRange() const;
+ const Range<int32_t>& getBitrateRange() const;
/**
* Returns the array of supported sample rates if the codec
@@ -110,7 +110,7 @@
std::string mMediaType;
std::vector<ProfileLevel> mProfileLevels;
- Range<int> mBitrateRange;
+ Range<int32_t> mBitrateRange;
std::vector<int> mSampleRates;
std::vector<Range<int>> mSampleRateRanges;
@@ -121,13 +121,13 @@
void init(std::string mediaType, std::vector<ProfileLevel> profLevs,
const sp<AMessage> &format);
void initWithPlatformLimits();
- bool supports(int sampleRate, int inputChannels);
+ bool supports(std::optional<int> sampleRate, std::optional<int> inputChannels);
void limitSampleRates(std::vector<int> rates);
void createDiscreteSampleRates();
void limitSampleRates(std::vector<Range<int>> rateRanges);
void applyLevelLimits();
void applyLimits(const std::vector<Range<int>> &inputChannels,
- const std::optional<Range<int>> &bitRates);
+ const std::optional<Range<int32_t>> &bitRates);
void parseFromInfo(const sp<AMessage> &format);
friend struct CodecCapabilities;
diff --git a/media/libmedia/include/media/CodecCapabilities.h b/media/libmedia/include/media/CodecCapabilities.h
index 9d1c4ea..570c8b5 100644
--- a/media/libmedia/include/media/CodecCapabilities.h
+++ b/media/libmedia/include/media/CodecCapabilities.h
@@ -34,7 +34,7 @@
struct CodecCapabilities {
- static bool SupportsBitrate(Range<int> bitrateRange,
+ static bool SupportsBitrate(Range<int32_t> bitrateRange,
const sp<AMessage> &format);
/**
diff --git a/media/libmedia/include/media/CodecCapabilitiesUtils.h b/media/libmedia/include/media/CodecCapabilitiesUtils.h
index 2bf822a..89a452c 100644
--- a/media/libmedia/include/media/CodecCapabilitiesUtils.h
+++ b/media/libmedia/include/media/CodecCapabilitiesUtils.h
@@ -118,7 +118,7 @@
T upper_;
};
-static const Range<int> POSITIVE_INTEGERS = Range<int>(1, INT_MAX);
+static const Range<int32_t> POSITIVE_INT32 = Range<int32_t>(1, INT32_MAX);
// found stuff that is not supported by framework (=> this should not happen)
constexpr int ERROR_CAPABILITIES_UNRECOGNIZED = (1 << 0);
diff --git a/media/libmedia/tests/codeccapabilities/CodecCapabilitiesTest.cpp b/media/libmedia/tests/codeccapabilities/CodecCapabilitiesTest.cpp
index 89c9739..02e43a4 100644
--- a/media/libmedia/tests/codeccapabilities/CodecCapabilitiesTest.cpp
+++ b/media/libmedia/tests/codeccapabilities/CodecCapabilitiesTest.cpp
@@ -64,7 +64,7 @@
};
TEST_F(AudioCapsAacTest, AudioCaps_Aac_Bitrate) {
- const Range<int>& bitrateRange = audioCaps->getBitrateRange();
+ const Range<int32_t>& bitrateRange = audioCaps->getBitrateRange();
EXPECT_EQ(bitrateRange.lower(), 8000) << "bitrate range1 does not match. lower: "
<< bitrateRange.lower();
EXPECT_EQ(bitrateRange.upper(), 510000) << "bitrate range1 does not match. upper: "
@@ -114,7 +114,7 @@
};
TEST_F(AudioCapsRawTest, AudioCaps_Raw_Bitrate) {
- const Range<int>& bitrateRange = audioCaps->getBitrateRange();
+ const Range<int32_t>& bitrateRange = audioCaps->getBitrateRange();
EXPECT_EQ(bitrateRange.lower(), 1);
EXPECT_EQ(bitrateRange.upper(), 10000000);
}
diff --git a/media/libmedia/xsd/vts/Android.bp b/media/libmedia/xsd/vts/Android.bp
index 83ab977..add7b51 100644
--- a/media/libmedia/xsd/vts/Android.bp
+++ b/media/libmedia/xsd/vts/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_android_kernel",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_av_media_libmedia_license"
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 10a1da7..761137e 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2514,6 +2514,15 @@
{
Mutex::Autolock lock(mLock);
track = mTrack;
+ }
+
+ // do not hold lock while joining.
+ if (track) {
+ track->stopAndJoinCallbacks();
+ }
+
+ {
+ Mutex::Autolock lock(mLock);
close_l(); // clears mTrack
}
// destruction of the track occurs outside of mutex.
diff --git a/media/libstagefright/xmlparser/vts/Android.bp b/media/libstagefright/xmlparser/vts/Android.bp
index 1e36c8f..527230c 100644
--- a/media/libstagefright/xmlparser/vts/Android.bp
+++ b/media/libstagefright/xmlparser/vts/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_android_media_codec_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index d916fd1..b5124d0 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -51,6 +51,11 @@
],
}
+vintf_fragment {
+ name: "manifest_media_c2_software.xml",
+ src: "manifest_media_c2_software.xml",
+}
+
mediaserver_cc_binary {
name: "mediaserver",
@@ -88,7 +93,7 @@
"-Wall",
],
- vintf_fragments: ["manifest_media_c2_software.xml"],
+ vintf_fragment_modules: ["manifest_media_c2_software.xml"],
soong_config_variables: {
TARGET_DYNAMIC_64_32_MEDIASERVER: {
diff --git a/media/module/codecs/amrwb/enc/Android.bp b/media/module/codecs/amrwb/enc/Android.bp
index 04f36b5..6ca3b6e 100644
--- a/media/module/codecs/amrwb/enc/Android.bp
+++ b/media/module/codecs/amrwb/enc/Android.bp
@@ -96,8 +96,6 @@
"-DARM",
"-DARMV7",
"-DASM_OPT",
- // don't actually generate neon instructions, see bug 26932980
- "-mfpu=vfpv3",
],
local_include_dirs: [
"src/asm/ARMV7",
diff --git a/media/module/extractors/extractor.aconfig b/media/module/extractors/extractor.aconfig
index c61efa4..c9bf694 100644
--- a/media/module/extractors/extractor.aconfig
+++ b/media/module/extractors/extractor.aconfig
@@ -7,6 +7,7 @@
flag {
name: "extractor_sniff_midi_optimizations"
is_exported: true
+ is_fixed_read_only: true
namespace: "media_extractor"
description: "Enable SniffMidi optimizations."
bug: "359920208"
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 3de9968..83cd024 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -73,7 +73,7 @@
bool isDirect() const final
{ return (mFlags & AUDIO_INPUT_FLAG_DIRECT) != 0; }
- void setSilenced(bool silenced) final { if (!isPatchTrack()) mSilenced = silenced; }
+ void setSilenced(bool silenced) final;
bool isSilenced() const final { return mSilenced; }
status_t getActiveMicrophones(
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 90d3ef9..b7c0bb3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4017,7 +4017,13 @@
// FIXME could this be made local to while loop?
writeFrames = 0;
- cacheParameters_l();
+ {
+ audio_utils::lock_guard l(mutex());
+
+ cacheParameters_l();
+ checkSilentMode_l();
+ }
+
mSleepTimeUs = mIdleSleepTimeUs;
if (mType == MIXER || mType == SPATIALIZER) {
@@ -4042,8 +4048,6 @@
// suspended mode (for now) to help schedule the wait time until next iteration.
nsecs_t timeLoopNextNs = 0;
- checkSilentMode_l();
-
audio_patch_handle_t lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
sendCheckOutputStageEffectsEvent();
@@ -7727,6 +7731,7 @@
ssize_t DuplicatingThread::threadLoop_write()
{
+ ATRACE_BEGIN("write");
for (size_t i = 0; i < outputTracks.size(); i++) {
const ssize_t actualWritten = outputTracks[i]->write(mSinkBuffer, writeFrames);
@@ -7745,6 +7750,7 @@
// TODO: Report correction for the other output tracks and show in the dump.
}
+ ATRACE_END();
if (mStandby) {
mThreadMetrics.logBeginInterval();
mThreadSnapshot.onBegin();
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index f5f11cc..3d4e771 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -3136,6 +3136,14 @@
*backInserter++ = metadata;
}
+void RecordTrack::setSilenced(bool silenced) {
+ if (!isPatchTrack() && mSilenced != silenced) {
+ mSilenced = silenced;
+ ALOGD("%s: track with port id: %d, (%s)", __func__, mPortId,
+ mSilenced ? "silenced" : "unsilenced");
+ }
+}
+
// ----------------------------------------------------------------------------
#undef LOG_TAG
#define LOG_TAG "AF::PatchRecord"
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 8162720..9b1125d 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -92,6 +92,10 @@
bool isDefault() const;
+ bool isPatchStrategy() const {
+ return getVolumeGroupForStreamType(AUDIO_STREAM_PATCH) != VOLUME_GROUP_NONE;
+ }
+
void dump(String8 *dst, int spaces = 0) const;
private:
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 976791f..fb8379e 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -311,6 +311,9 @@
}
StrategyVector orderedStrategies;
for (const auto &iter : strategies) {
+ if (iter.second->isPatchStrategy()) {
+ continue;
+ }
orderedStrategies.push_back(iter.second->getId());
}
return orderedStrategies;
@@ -742,6 +745,9 @@
auto defaultDevices = DeviceVector(getApmObserver()->getDefaultOutputDevice());
for (const auto &iter : getProductStrategies()) {
const auto &strategy = iter.second;
+ if (strategy->isPatchStrategy()) {
+ continue;
+ }
mDevicesForStrategies[strategy->getId()] = defaultDevices;
setStrategyDevices(strategy, defaultDevices);
}
@@ -750,6 +756,9 @@
void EngineBase::updateDeviceSelectionCache() {
for (const auto &iter : getProductStrategies()) {
const auto& strategy = iter.second;
+ if (strategy->isPatchStrategy()) {
+ continue;
+ }
auto devices = getDevicesForProductStrategy(strategy->getId());
mDevicesForStrategies[strategy->getId()] = devices;
setStrategyDevices(strategy, devices);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 3ec3fb3..354c59c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3496,6 +3496,11 @@
}
ALOGV("%s: group %d matching with %s index %d",
__FUNCTION__, group, toString(attributes).c_str(), index);
+ if (mEngine->getStreamTypeForAttributes(attributes) == AUDIO_STREAM_PATCH) {
+ ALOGV("%s: cannot change volume for PATCH stream, attrs: %s",
+ __FUNCTION__, toString(attributes).c_str());
+ return NO_ERROR;
+ }
status_t status = NO_ERROR;
IVolumeCurves &curves = getVolumeCurves(attributes);
VolumeSource vs = toVolumeSource(group);
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.h b/services/camera/virtualcamera/VirtualCameraRenderThread.h
index 5a5966b..c6b58fb 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.h
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.h
@@ -216,8 +216,8 @@
std::mutex mLock;
std::deque<std::unique_ptr<ProcessCaptureRequestTask>> mQueue GUARDED_BY(mLock);
std::condition_variable mCondVar;
- volatile bool mTextureUpdateRequested GUARDED_BY(mLock);
- volatile bool mPendingExit GUARDED_BY(mLock);
+ volatile bool GUARDED_BY(mLock) mTextureUpdateRequested = false;
+ volatile bool GUARDED_BY(mLock) mPendingExit = false;
// Acquisition timestamp of last frame.
std::atomic<uint64_t> mLastAcquisitionTimestampNanoseconds;