Merge changes from topic "rm_changes" into main
* changes:
resourcemanager: protect resources from concurrent access
resourcemanager: use std::vector for ResourceList
diff --git a/camera/Android.mk b/camera/Android.mk
deleted file mode 100644
index d9068c0..0000000
--- a/camera/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2010 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.
-
-include $(call all-subdir-makefiles)
diff --git a/camera/include/camera/camera2/SessionConfiguration.h b/camera/include/camera/camera2/SessionConfiguration.h
index 29913f6..73fafb4 100644
--- a/camera/include/camera/camera2/SessionConfiguration.h
+++ b/camera/include/camera/camera2/SessionConfiguration.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_HARDWARE_CAMERA2_SESSIONCONFIGURATION_H
#define ANDROID_HARDWARE_CAMERA2_SESSIONCONFIGURATION_H
+#include "OutputConfiguration.h"
+
#include <binder/Parcelable.h>
namespace android {
@@ -25,8 +27,6 @@
namespace camera2 {
namespace params {
-class OutputConfiguration;
-
class SessionConfiguration : public android::Parcelable {
public:
diff --git a/camera/tests/Android.bp b/camera/tests/Android.bp
new file mode 100644
index 0000000..65b8b41
--- /dev/null
+++ b/camera/tests/Android.bp
@@ -0,0 +1,52 @@
+// Copyright 2013 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.
+
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "frameworks_av_camera_license",
+ ],
+}
+
+cc_test {
+ name: "camera_client_test",
+ srcs: [
+ "VendorTagDescriptorTests.cpp",
+ "CameraBinderTests.cpp",
+ "CameraZSLTests.cpp",
+ "CameraCharacteristicsPermission.cpp",
+ ],
+ shared_libs: [
+ "liblog",
+ "libutils",
+ "libcutils",
+ "libcamera_metadata",
+ "libcamera_client",
+ "libgui",
+ "libsync",
+ "libui",
+ "libdl",
+ "libbinder",
+ ],
+ include_dirs: [
+ "system/media/private/camera/include",
+ "system/media/camera/tests",
+ "frameworks/av/services/camera/libcameraservice",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+}
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
deleted file mode 100644
index 7f8078e..0000000
--- a/camera/tests/Android.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2013 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_SRC_FILES:= \
- VendorTagDescriptorTests.cpp \
- CameraBinderTests.cpp \
- CameraZSLTests.cpp \
- CameraCharacteristicsPermission.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libutils \
- libcutils \
- libcamera_metadata \
- libcamera_client \
- libgui \
- libsync \
- libui \
- libdl \
- libbinder
-
-LOCAL_C_INCLUDES += \
- system/media/private/camera/include \
- system/media/camera/tests \
- frameworks/av/services/camera/libcameraservice \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-LOCAL_MODULE:= camera_client_test
-LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS:= notice
-LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../NOTICE
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_NATIVE_TEST)
diff --git a/media/aconfig/Android.bp b/media/aconfig/Android.bp
index 96bf4f5..f95d723 100644
--- a/media/aconfig/Android.bp
+++ b/media/aconfig/Android.bp
@@ -14,6 +14,7 @@
name: "aconfig_mediacodec_flags_c_lib",
min_sdk_version: "30",
vendor_available: true,
+ double_loadable: true,
apex_available: [
"//apex_available:platform",
"com.android.media.swcodec",
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index 53f529e..7cba011 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -25,6 +25,7 @@
#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_CPP
#endif // BACKEND_NDK_IMPL
+#include <functional>
#include <limits>
#include <type_traits>
#include <utility>
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index 8a894f3..b911e11 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -25,5 +25,8 @@
}
]
}
+ ],
+ "postsubmit": [
+ { "name": "c2aidl_gtracker_test"}
]
}
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
index 10e4b79..76680a3 100644
--- a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
@@ -648,6 +648,24 @@
if (res == 0) {
ALOGV("dav1d found a sequenceHeader (%dx%d) for in_frameIndex=%ld.", seq.max_width,
seq.max_height, (long)in_frameIndex);
+ if (seq.max_width != mWidth || seq.max_height != mHeight) {
+ drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
+ mWidth = seq.max_width;
+ mHeight = seq.max_height;
+
+ C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
+ if (err == C2_OK) {
+ work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(size));
+ } else {
+ ALOGE("Config update size failed");
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ return;
+ }
+ }
}
// insert OBU TD if it is not present.
@@ -921,26 +939,6 @@
return false;
}
- const int width = img.p.w;
- const int height = img.p.h;
- if (width != mWidth || height != mHeight) {
- mWidth = width;
- mHeight = height;
-
- C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
- std::vector<std::unique_ptr<C2SettingResult>> failures;
- c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
- if (err == C2_OK) {
- work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(size));
- } else {
- ALOGE("Config update size failed");
- mSignalledError = true;
- work->result = C2_CORRUPTED;
- work->workletsProcessed = 1u;
- return false;
- }
- }
-
getVuiParams(&img);
// out_frameIndex that the decoded picture returns from dav1d.
diff --git a/media/codec2/components/raw/C2SoftRawDec.cpp b/media/codec2/components/raw/C2SoftRawDec.cpp
index a03d4e2..ea13071 100644
--- a/media/codec2/components/raw/C2SoftRawDec.cpp
+++ b/media/codec2/components/raw/C2SoftRawDec.cpp
@@ -65,7 +65,7 @@
addParameter(
DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
.withDefault(new C2StreamChannelCountInfo::output(0u, 2))
- .withFields({C2F(mChannelCount, value).inRange(1, 8)})
+ .withFields({C2F(mChannelCount, value).inRange(1, 12)})
.withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
.build());
diff --git a/media/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index 7a9af18..48b6e21 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -24,7 +24,7 @@
shared_libs: [
"android.hardware.common-V2-ndk",
"android.hardware.media.bufferpool@2.0",
- "android.hardware.media.bufferpool2-V1-ndk",
+ "android.hardware.media.bufferpool2-V2-ndk",
"android.hardware.media.c2-V1-ndk",
"libbinder_ndk",
"libbase",
@@ -84,7 +84,7 @@
shared_libs: [
"android.hardware.common-V2-ndk",
- "android.hardware.media.bufferpool2-V1-ndk",
+ "android.hardware.media.bufferpool2-V2-ndk",
"android.hardware.media.c2-V1-ndk",
"libbase",
"libbinder_ndk",
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
index 4605af3..4c2d5d3 100644
--- a/media/codec2/hal/aidl/Component.cpp
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -403,6 +403,22 @@
return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
}
+ScopedAStatus Component::connectToInputSurface(
+ const std::shared_ptr<IInputSurface>& inputSurface,
+ std::shared_ptr<IInputSurfaceConnection> *connection) {
+ // TODO
+ (void)inputSurface;
+ (void)connection;
+ return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
+}
+
+ScopedAStatus Component::asInputSink(
+ std::shared_ptr<IInputSink> *sink) {
+ // TODO
+ (void)sink;
+ return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
+}
+
void Component::initListener(const std::shared_ptr<Component>& self) {
if (__builtin_available(android __ANDROID_API_T__, *)) {
std::shared_ptr<C2Component::Listener> c2listener =
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
index 58407d1..f0a1490 100644
--- a/media/codec2/hal/aidl/ComponentStore.cpp
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -273,6 +273,13 @@
return ScopedAStatus::ok();
}
+ScopedAStatus ComponentStore::createInputSurface(
+ std::shared_ptr<IInputSurface> *inputSurface) {
+ // TODO
+ (void)inputSurface;
+ return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
+}
+
void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
// invalidate unsupported struct descriptors if a new interface is loaded as it may have
// exposed new descriptors
diff --git a/media/codec2/hal/aidl/Configurable.cpp b/media/codec2/hal/aidl/Configurable.cpp
index 0326263..2daaac2 100644
--- a/media/codec2/hal/aidl/Configurable.cpp
+++ b/media/codec2/hal/aidl/Configurable.cpp
@@ -19,6 +19,7 @@
#include <android-base/logging.h>
#include <android/binder_auto_utils.h>
+#include <android-base/hex.h>
#include <codec2/aidl/Configurable.h>
#include <codec2/aidl/ParamTypes.h>
@@ -61,7 +62,7 @@
ScopedAStatus CachedConfigurable::query(
const std::vector<int32_t>& indices,
bool mayBlock,
- Params* params) {
+ QueryResult *queryResult) {
typedef C2Param::Index Index;
std::vector<Index> c2heapParamIndices(
(Index*)indices.data(),
@@ -72,13 +73,11 @@
mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
&c2heapParams);
- if (!CreateParamsBlob(params, c2heapParams)) {
+ if (!CreateParamsBlob(&(queryResult->params), c2heapParams)) {
LOG(WARNING) << "query -- invalid output params.";
}
- if (c2res == C2_OK) {
- return ScopedAStatus::ok();
- }
- return ScopedAStatus::fromServiceSpecificError(c2res);
+ queryResult->status.status = c2res;
+ return ScopedAStatus::ok();
}
ScopedAStatus CachedConfigurable::config(
@@ -115,10 +114,8 @@
if (!CreateParamsBlob(&result->params, c2params)) {
LOG(DEBUG) << "config -- invalid output params.";
}
- if (c2res == C2_OK) {
- return ScopedAStatus::ok();
- }
- return ScopedAStatus::fromServiceSpecificError(c2res);
+ result->status.status = c2res;
+ return ScopedAStatus::ok();
}
ScopedAStatus CachedConfigurable::querySupportedParams(
@@ -139,8 +136,6 @@
LOG(WARNING) << "querySupportedParams -- invalid output params.";
break;
}
- } else {
- res = Status::BAD_INDEX;
}
}
paramDesc->resize(dstIx);
@@ -153,7 +148,7 @@
ScopedAStatus CachedConfigurable::querySupportedValues(
const std::vector<FieldSupportedValuesQuery>& fields,
bool mayBlock,
- std::vector<FieldSupportedValuesQueryResult>* result) {
+ QuerySupportedValuesResult *queryValues) {
std::vector<C2FieldSupportedValuesQuery> c2fields;
{
// C2FieldSupportedValuesQuery objects are restricted in that some
@@ -173,22 +168,20 @@
c2_status_t c2res = mIntf->querySupportedValues(
c2fields,
mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK);
- result->resize(fields.size());
+ queryValues->values.resize(fields.size());
size_t dstIx = 0;
for (const C2FieldSupportedValuesQuery &res : c2fields) {
- if (ToAidl(&(*result)[dstIx], res)) {
+ if (ToAidl(&(queryValues->values[dstIx]), res)) {
++dstIx;
} else {
- result->resize(dstIx);
+ queryValues->values.resize(dstIx);
c2res = C2_CORRUPTED;
LOG(WARNING) << "querySupportedValues -- invalid output params.";
break;
}
}
- if (c2res == C2_OK) {
- return ScopedAStatus::ok();
- }
- return ScopedAStatus::fromServiceSpecificError(c2res);
+ queryValues->status.status = c2res;
+ return ScopedAStatus::ok();
}
} // namespace utils
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Component.h b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
index 4a090e9..94b760f 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/Component.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
@@ -27,6 +27,9 @@
#include <aidl/android/hardware/media/c2/IComponentInterface.h>
#include <aidl/android/hardware/media/c2/IComponentListener.h>
#include <aidl/android/hardware/media/c2/IComponentStore.h>
+#include <aidl/android/hardware/media/c2/IInputSink.h>
+#include <aidl/android/hardware/media/c2/IInputSurface.h>
+#include <aidl/android/hardware/media/c2/IInputSurfaceConnection.h>
#include <C2Component.h>
#include <C2Buffer.h>
@@ -71,6 +74,11 @@
::ndk::ScopedAStatus configureVideoTunnel(
int32_t avSyncHwId,
common::NativeHandle* handle) override;
+ ::ndk::ScopedAStatus connectToInputSurface(
+ const std::shared_ptr<IInputSurface>& inputSurface,
+ std::shared_ptr<IInputSurfaceConnection> *connection) override;
+ ::ndk::ScopedAStatus asInputSink(
+ std::shared_ptr<IInputSink> *sink) override;
protected:
c2_status_t mInit;
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
index b3c97d5..0698b0f 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
@@ -23,6 +23,7 @@
#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
#include <aidl/android/hardware/media/c2/BnComponentStore.h>
+#include <aidl/android/hardware/media/c2/IInputSurface.h>
#include <C2Component.h>
#include <C2Param.h>
@@ -85,6 +86,8 @@
std::shared_ptr<IComponentInterface> *intf) override;
virtual ::ndk::ScopedAStatus listComponents(
std::vector<IComponentStore::ComponentTraits>* traits) override;
+ virtual ::ndk::ScopedAStatus createInputSurface(
+ std::shared_ptr<IInputSurface> *inputSurface) override;
virtual ::ndk::ScopedAStatus getStructDescriptors(
const std::vector<int32_t>& indices,
std::vector<StructDescriptor> *descs) override;
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
index 6cc2c1b..96d3516 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
@@ -111,7 +111,7 @@
virtual ::ndk::ScopedAStatus query(
const std::vector<int32_t>& indices,
bool mayBlock,
- Params* params) override;
+ QueryResult* result) override;
virtual ::ndk::ScopedAStatus config(
const ::aidl::android::hardware::media::c2::Params& params,
@@ -126,7 +126,7 @@
virtual ::ndk::ScopedAStatus querySupportedValues(
const std::vector<FieldSupportedValuesQuery>& fields,
bool mayBlock,
- std::vector<FieldSupportedValuesQueryResult>* result) override;
+ QuerySupportedValuesResult* result) override;
protected:
// Common Codec2.0 interface wrapper
diff --git a/media/codec2/hal/client/Android.bp b/media/codec2/hal/client/Android.bp
index 0b5b940..af6f4ae 100644
--- a/media/codec2/hal/client/Android.bp
+++ b/media/codec2/hal/client/Android.bp
@@ -43,7 +43,7 @@
"android.hardware.media.c2@1.0",
"android.hardware.media.c2@1.1",
"android.hardware.media.c2@1.2",
- "android.hardware.media.bufferpool2-V1-ndk",
+ "android.hardware.media.bufferpool2-V2-ndk",
"android.hardware.media.c2-V1-ndk",
"libbase",
"libbinder",
diff --git a/media/codec2/hal/client/GraphicsTracker.cpp b/media/codec2/hal/client/GraphicsTracker.cpp
index 0848fc6..01b0678 100644
--- a/media/codec2/hal/client/GraphicsTracker.cpp
+++ b/media/codec2/hal/client/GraphicsTracker.cpp
@@ -174,20 +174,16 @@
GraphicsTracker::GraphicsTracker(int maxDequeueCount)
: mBufferCache(new BufferCache()), mMaxDequeue{maxDequeueCount},
- mMaxDequeueRequested{maxDequeueCount},
mMaxDequeueCommitted{maxDequeueCount},
- mMaxDequeueRequestedSeqId{0UL}, mMaxDequeueCommittedSeqId{0ULL},
mDequeueable{maxDequeueCount},
mTotalDequeued{0}, mTotalCancelled{0}, mTotalDropped{0}, mTotalReleased{0},
mInConfig{false}, mStopped{false} {
if (maxDequeueCount < kMaxDequeueMin) {
mMaxDequeue = kMaxDequeueMin;
- mMaxDequeueRequested = kMaxDequeueMin;
mMaxDequeueCommitted = kMaxDequeueMin;
mDequeueable = kMaxDequeueMin;
} else if(maxDequeueCount > kMaxDequeueMax) {
mMaxDequeue = kMaxDequeueMax;
- mMaxDequeueRequested = kMaxDequeueMax;
mMaxDequeueCommitted = kMaxDequeueMax;
mDequeueable = kMaxDequeueMax;
}
@@ -197,34 +193,36 @@
mReadPipeFd.reset(pipefd[0]);
mWritePipeFd.reset(pipefd[1]);
- mEventQueueThread = std::thread([this](){processEvent();});
- writeIncDequeueable(mDequeueable);
+ // ctor does not require lock to be held.
+ writeIncDequeueableLocked(mDequeueable);
CHECK(ret >= 0);
- CHECK(mEventQueueThread.joinable());
}
GraphicsTracker::~GraphicsTracker() {
stop();
- if (mEventQueueThread.joinable()) {
- mEventQueueThread.join();
- }
}
bool GraphicsTracker::adjustDequeueConfLocked(bool *updateDequeue) {
// TODO: can't we adjust during config? not committing it may safe?
*updateDequeue = false;
- if (!mInConfig && mMaxDequeueRequested < mMaxDequeue) {
- int delta = mMaxDequeue - mMaxDequeueRequested;
+ if (!mInConfig && mMaxDequeueRequested.has_value() && mMaxDequeueRequested < mMaxDequeue) {
+ int delta = mMaxDequeue - mMaxDequeueRequested.value();
+ int drained = 0;
// Since we are supposed to increase mDequeuable by one already
int adjustable = mDequeueable + 1;
if (adjustable >= delta) {
- mMaxDequeue = mMaxDequeueRequested;
+ mMaxDequeue = mMaxDequeueRequested.value();
mDequeueable -= (delta - 1);
+ drained = delta - 1;
} else {
mMaxDequeue -= adjustable;
+ drained = mDequeueable;
mDequeueable = 0;
}
+ if (drained > 0) {
+ drainDequeueableLocked(drained);
+ }
if (mMaxDequeueRequested == mMaxDequeue && mMaxDequeueRequested != mMaxDequeueCommitted) {
*updateDequeue = true;
}
@@ -235,6 +233,7 @@
c2_status_t GraphicsTracker::configureGraphics(
const sp<IGraphicBufferProducer>& igbp, uint32_t generation) {
+ // TODO: wait until operations to previous IGBP is completed.
std::shared_ptr<BufferCache> prevCache;
int prevDequeueCommitted;
@@ -254,14 +253,28 @@
if (igbp) {
ret = igbp->getUniqueId(&bqId);
}
- if (ret != ::android::OK || prevCache->mGeneration == generation || prevCache->mBqId == bqId) {
+ if (ret != ::android::OK ||
+ prevCache->mGeneration == generation) {
+ ALOGE("new surface configure fail due to wrong or same bqId or same generation:"
+ "igbp(%d:%llu -> %llu), gen(%lu -> %lu)", (bool)igbp,
+ (unsigned long long)prevCache->mBqId, (unsigned long long)bqId,
+ (unsigned long)prevCache->mGeneration, (unsigned long)generation);
+ std::unique_lock<std::mutex> l(mLock);
+ mInConfig = false;
return C2_BAD_VALUE;
}
- ret = igbp->setMaxDequeuedBufferCount(prevDequeueCommitted);
- if (ret != ::android::OK) {
- // TODO: sort out the error from igbp and return an error accordingly.
- return C2_CORRUPTED;
+ if (igbp) {
+ ret = igbp->setMaxDequeuedBufferCount(prevDequeueCommitted);
+ if (ret != ::android::OK) {
+ ALOGE("new surface maxDequeueBufferCount configure fail");
+ // TODO: sort out the error from igbp and return an error accordingly.
+ std::unique_lock<std::mutex> l(mLock);
+ mInConfig = false;
+ return C2_CORRUPTED;
+ }
}
+ ALOGD("new surface configured with id:%llu gen:%lu maxDequeue:%d",
+ (unsigned long long)bqId, (unsigned long)generation, prevDequeueCommitted);
std::shared_ptr<BufferCache> newCache = std::make_shared<BufferCache>(bqId, generation, igbp);
{
std::unique_lock<std::mutex> l(mLock);
@@ -283,59 +296,74 @@
// (Sometimes maxDequeueCount cannot be committed if the number of
// dequeued buffer count is bigger.)
int maxDequeueToCommit;
- // max dequeue count which is committed to IGBP currently
- // (actually mMaxDequeueCommitted, but needs to be read outside lock.)
- int curMaxDequeueCommitted;
std::unique_lock<std::mutex> cl(mConfigLock);
{
std::unique_lock<std::mutex> l(mLock);
- if (mMaxDequeueRequested == maxDequeueCount) {
+ if (mMaxDequeueRequested.has_value()) {
+ if (mMaxDequeueRequested == maxDequeueCount) {
+ ALOGD("maxDequeueCount requested with %d already", maxDequeueCount);
+ return C2_OK;
+ }
+ } else if (mMaxDequeue == maxDequeueCount) {
+ ALOGD("maxDequeueCount is already %d", maxDequeueCount);
return C2_OK;
}
mInConfig = true;
mMaxDequeueRequested = maxDequeueCount;
cache = mBufferCache;
- curMaxDequeueCommitted = mMaxDequeueCommitted;
if (mMaxDequeue <= maxDequeueCount) {
maxDequeueToCommit = maxDequeueCount;
} else {
// Since mDequeuable is decreasing,
// a delievered ready to allocate event may not be fulfilled.
// Another waiting via a waitable object may be necessary in the case.
- int delta = mMaxDequeue - maxDequeueCount;
- if (delta <= mDequeueable) {
- maxDequeueToCommit = maxDequeueCount;
- mDequeueable -= delta;
- } else {
- maxDequeueToCommit = mMaxDequeue - mDequeueable;
- mDequeueable = 0;
+ int delta = std::min(mMaxDequeue - maxDequeueCount, mDequeueable);
+ maxDequeueToCommit = mMaxDequeue - delta;
+ mDequeueable -= delta;
+ if (delta > 0) {
+ drainDequeueableLocked(delta);
}
}
}
bool committed = true;
- if (cache->mIgbp && maxDequeueToCommit != curMaxDequeueCommitted) {
+ if (cache->mIgbp && maxDequeueToCommit != mMaxDequeueCommitted) {
::android::status_t ret = cache->mIgbp->setMaxDequeuedBufferCount(maxDequeueToCommit);
committed = (ret == ::android::OK);
- if (!committed) {
+ if (committed) {
+ ALOGD("maxDequeueCount committed to IGBP: %d", maxDequeueToCommit);
+ } else {
// This should not happen.
- ALOGE("dequeueCount failed with error(%d)", (int)ret);
+ ALOGE("maxdequeueCount update to IGBP failed with error(%d)", (int)ret);
}
}
+ int oldMaxDequeue = 0;
+ int requested = 0;
{
std::unique_lock<std::mutex> l(mLock);
mInConfig = false;
+ oldMaxDequeue = mMaxDequeue;
+ mMaxDequeue = maxDequeueToCommit; // we already drained dequeueable
if (committed) {
+ clearCacheIfNecessaryLocked(cache, maxDequeueToCommit);
mMaxDequeueCommitted = maxDequeueToCommit;
- int delta = mMaxDequeueCommitted - mMaxDequeue;
+ if (mMaxDequeueRequested == mMaxDequeueCommitted &&
+ mMaxDequeueRequested == mMaxDequeue) {
+ mMaxDequeueRequested.reset();
+ }
+ if (mMaxDequeueRequested.has_value()) {
+ requested = mMaxDequeueRequested.value();
+ }
+ int delta = mMaxDequeueCommitted - oldMaxDequeue;
if (delta > 0) {
mDequeueable += delta;
- l.unlock();
- writeIncDequeueable(delta);
+ writeIncDequeueableLocked(delta);
}
}
}
+ ALOGD("maxDqueueCount change %d -> %d: pending: %d",
+ oldMaxDequeue, maxDequeueToCommit, requested);
if (!committed) {
return C2_CORRUPTED;
@@ -350,48 +378,60 @@
std::unique_lock<std::mutex> cl(mConfigLock);
{
std::unique_lock<std::mutex> l(mLock);
- if (mMaxDequeue == mMaxDequeueRequested && mMaxDequeueCommitted != mMaxDequeueRequested) {
- dequeueCommit = mMaxDequeue;
- mInConfig = true;
- cache = mBufferCache;
- } else {
+ if (!mMaxDequeueRequested.has_value() || mMaxDequeue != mMaxDequeueRequested) {
return;
}
+ if (mMaxDequeueCommitted == mMaxDequeueRequested) {
+ // already committed. may not happen.
+ mMaxDequeueRequested.reset();
+ return;
+ }
+ dequeueCommit = mMaxDequeue;
+ mInConfig = true;
+ cache = mBufferCache;
}
bool committed = true;
if (cache->mIgbp) {
::android::status_t ret = cache->mIgbp->setMaxDequeuedBufferCount(dequeueCommit);
committed = (ret == ::android::OK);
- if (!committed) {
+ if (committed) {
+ ALOGD("delayed maxDequeueCount update to IGBP: %d", dequeueCommit);
+ } else {
// This should not happen.
- ALOGE("dequeueCount failed with error(%d)", (int)ret);
+ ALOGE("delayed maxdequeueCount update to IGBP failed with error(%d)", (int)ret);
}
}
- int cleared = 0;
{
// cache == mCache here, since we locked config.
std::unique_lock<std::mutex> l(mLock);
mInConfig = false;
if (committed) {
- if (cache->mIgbp && dequeueCommit < mMaxDequeueCommitted) {
- // we are shrinking # of buffers, so clearing the cache.
- for (auto it = cache->mBuffers.begin(); it != cache->mBuffers.end();) {
- uint64_t bid = it->second->mId;
- if (mDequeued.count(bid) == 0 || mDeallocating.count(bid) > 0) {
- ++cleared;
- it = cache->mBuffers.erase(it);
- } else {
- ++it;
- }
- }
- }
+ clearCacheIfNecessaryLocked(cache, dequeueCommit);
mMaxDequeueCommitted = dequeueCommit;
}
+ mMaxDequeueRequested.reset();
}
- if (cleared > 0) {
- ALOGD("%d buffers are cleared from cache, due to IGBP capacity change", cleared);
- }
+}
+void GraphicsTracker::clearCacheIfNecessaryLocked(const std::shared_ptr<BufferCache> &cache,
+ int maxDequeueCommitted) {
+ int cleared = 0;
+ size_t origCacheSize = cache->mBuffers.size();
+ if (cache->mIgbp && maxDequeueCommitted < mMaxDequeueCommitted) {
+ // we are shrinking # of buffers in the case, so evict the previous
+ // cached buffers.
+ for (auto it = cache->mBuffers.begin(); it != cache->mBuffers.end();) {
+ uint64_t bid = it->second->mId;
+ if (mDequeued.count(bid) == 0 || mDeallocating.count(bid) > 0) {
+ ++cleared;
+ it = cache->mBuffers.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ }
+ ALOGD("Cache size %zu -> %zu: maybe_cleared(%d), dequeued(%zu)",
+ origCacheSize, cache->mBuffers.size(), cleared, mDequeued.size());
}
int GraphicsTracker::getCurDequeueable() {
@@ -400,70 +440,58 @@
}
void GraphicsTracker::stop() {
- bool expected = false;
- std::unique_lock<std::mutex> l(mEventLock);
- bool updated = mStopped.compare_exchange_strong(expected, true);
- if (updated) {
- int writeFd = mWritePipeFd.release();
+ // TODO: wait until all operation to current IGBP
+ // being completed.
+ std::unique_lock<std::mutex> l(mLock);
+ if (mStopped) {
+ return;
+ }
+ mStopped = true;
+ int writeFd = mWritePipeFd.release();
+ if (writeFd >= 0) {
::close(writeFd);
- int readFd = mReadPipeFd.release();
- ::close(readFd);
- mEventCv.notify_one();
}
}
-void GraphicsTracker::writeIncDequeueable(int inc) {
+void GraphicsTracker::writeIncDequeueableLocked(int inc) {
CHECK(inc > 0 && inc < kMaxDequeueMax);
thread_local char buf[kMaxDequeueMax];
- int diff = 0;
- {
- std::unique_lock<std::mutex> l(mEventLock);
- if (mStopped) {
- return;
- }
- CHECK(mWritePipeFd.get() >= 0);
- int ret = ::write(mWritePipeFd.get(), buf, inc);
- if (ret == inc) {
- return;
- }
- diff = ret < 0 ? inc : inc - ret;
-
- // Partial write or EINTR. This will not happen in a real scenario.
- mIncDequeueable += diff;
- if (mIncDequeueable > 0) {
- l.unlock();
- mEventCv.notify_one();
- ALOGW("updating dequeueable to pipefd pending");
- }
+ if (mStopped) { // reading end closed;
+ return;
}
+ int writeFd = mWritePipeFd.get();
+ if (writeFd < 0) {
+ // initialization fail and not valid though.
+ return;
+ }
+ int ret = ::write(writeFd, buf, inc);
+ // Since this is non-blocking i/o, it never returns EINTR.
+ //
+ // ::write() to pipe guarantee to succeed atomically if it writes less than
+ // the given PIPE_BUF. And the buffer size in pipe/fifo is at least 4K and our total
+ // max pending buffer size is 64. So it never returns EAGAIN here either.
+ // See pipe(7) for further information.
+ //
+ // Other errors are serious errors and we cannot synchronize mDequeueable to
+ // length of pending buffer in pipe/fifo anymore. So better to abort here.
+ // TODO: do not abort here. (b/318717399)
+ CHECK(ret == inc);
}
-void GraphicsTracker::processEvent() {
- // This is for partial/failed writes to the writing end.
- // This may not happen in the real scenario.
+void GraphicsTracker::drainDequeueableLocked(int dec) {
+ CHECK(dec > 0 && dec < kMaxDequeueMax);
thread_local char buf[kMaxDequeueMax];
- while (true) {
- std::unique_lock<std::mutex> l(mEventLock);
- if (mStopped) {
- break;
- }
- if (mIncDequeueable > 0) {
- int inc = mIncDequeueable > kMaxDequeueMax ? kMaxDequeueMax : mIncDequeueable;
- int ret = ::write(mWritePipeFd.get(), buf, inc);
- int written = ret <= 0 ? 0 : ret;
- mIncDequeueable -= written;
- if (mIncDequeueable > 0) {
- l.unlock();
- if (ret < 0) {
- ALOGE("write to writing end failed %d", errno);
- } else {
- ALOGW("partial write %d(%d)", inc, written);
- }
- continue;
- }
- }
- mEventCv.wait(l);
+ if (mStopped) {
+ return;
}
+ int readFd = mReadPipeFd.get();
+ if (readFd < 0) {
+ // initializationf fail and not valid though.
+ return;
+ }
+ int ret = ::read(readFd, buf, dec);
+ // TODO: no dot abort here. (b/318717399)
+ CHECK(ret == dec);
}
c2_status_t GraphicsTracker::getWaitableFd(int *pipeFd) {
@@ -539,8 +567,7 @@
return;
}
mDequeueable++;
- l.unlock();
- writeIncDequeueable(1);
+ writeIncDequeueableLocked(1);
}
}
@@ -715,14 +742,13 @@
return C2_OK;
}
mDequeueable++;
- l.unlock();
- writeIncDequeueable(1);
+ writeIncDequeueableLocked(1);
}
return C2_OK;
}
void GraphicsTracker::commitDeallocate(
- std::shared_ptr<BufferCache> &cache, int slotId, uint64_t bid) {
+ std::shared_ptr<BufferCache> &cache, int slotId, uint64_t bid, bool *updateDequeue) {
std::unique_lock<std::mutex> l(mLock);
size_t del1 = mDequeued.erase(bid);
size_t del2 = mDeallocating.erase(bid);
@@ -730,9 +756,11 @@
if (cache) {
cache->unblockSlot(slotId);
}
+ if (adjustDequeueConfLocked(updateDequeue)) {
+ return;
+ }
mDequeueable++;
- l.unlock();
- writeIncDequeueable(1);
+ writeIncDequeueableLocked(1);
}
@@ -758,7 +786,10 @@
// cache->mIgbp is not null, if completed is false.
(void)cache->mIgbp->cancelBuffer(slotId, rFence);
- commitDeallocate(cache, slotId, bid);
+ commitDeallocate(cache, slotId, bid, &updateDequeue);
+ if (updateDequeue) {
+ updateDequeueConf();
+ }
return C2_OK;
}
@@ -785,8 +816,7 @@
return C2_BAD_STATE;
}
mDequeueable++;
- l.unlock();
- writeIncDequeueable(1);
+ writeIncDequeueableLocked(1);
return C2_BAD_STATE;
}
std::shared_ptr<BufferItem> buffer = it->second;
@@ -828,8 +858,7 @@
return;
}
mDequeueable++;
- l.unlock();
- writeIncDequeueable(1);
+ writeIncDequeueableLocked(1);
return;
}
}
@@ -843,6 +872,9 @@
ALOGE("retrieving AHB-ID for GraphicBlock failed");
return C2_CORRUPTED;
}
+ std::shared_ptr<_C2BlockPoolData> poolData =
+ _C2BlockFactory::GetGraphicBlockPoolData(blk);
+ _C2BlockFactory::DisownIgbaBlock(poolData);
std::shared_ptr<BufferCache> cache;
std::shared_ptr<BufferItem> buffer;
std::shared_ptr<BufferItem> oldBuffer;
@@ -870,13 +902,19 @@
if (!gb) {
ALOGE("render: realloc-ing a new buffer for migration failed");
std::shared_ptr<BufferCache> nullCache;
- commitDeallocate(nullCache, -1, bid);
+ commitDeallocate(nullCache, -1, bid, &updateDequeue);
+ if (updateDequeue) {
+ updateDequeueConf();
+ }
return C2_REFUSED;
}
if (cache->mIgbp->attachBuffer(&(newBuffer->mSlot), gb) != ::android::OK) {
ALOGE("render: attaching a new buffer to IGBP failed");
std::shared_ptr<BufferCache> nullCache;
- commitDeallocate(nullCache, -1, bid);
+ commitDeallocate(nullCache, -1, bid, &updateDequeue);
+ if (updateDequeue) {
+ updateDequeueConf();
+ }
return C2_REFUSED;
}
cache->waitOnSlot(newBuffer->mSlot);
@@ -890,11 +928,13 @@
CHECK(renderRes != ::android::BAD_VALUE);
ALOGE("render: failed to queueBuffer() err = %d", renderRes);
(void) cache->mIgbp->cancelBuffer(buffer->mSlot, input.fence);
- commitDeallocate(cache, buffer->mSlot, bid);
+ commitDeallocate(cache, buffer->mSlot, bid, &updateDequeue);
+ if (updateDequeue) {
+ updateDequeueConf();
+ }
return C2_REFUSED;
}
- updateDequeue = false;
commitRender(cache, buffer, oldBuffer, output->bufferReplaced, &updateDequeue);
if (updateDequeue) {
updateDequeueConf();
@@ -909,8 +949,7 @@
if (mBufferCache->mGeneration == generation) {
if (!adjustDequeueConfLocked(&updateDequeue)) {
mDequeueable++;
- l.unlock();
- writeIncDequeueable(1);
+ writeIncDequeueableLocked(1);
}
}
}
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index 2d19ecc..85b5ec8 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -635,21 +635,22 @@
if (heapParams) {
heapParams->reserve(heapParams->size() + numIndices);
}
- c2_aidl::Params result;
+ c2_aidl::IConfigurable::QueryResult result;
ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
c2_status_t status = GetC2Status(transStatus, "query");
if (status != C2_OK) {
return status;
}
+ status = static_cast<c2_status_t>(result.status.status);
std::vector<C2Param*> paramPointers;
- if (!c2_aidl::utils::ParseParamsBlob(¶mPointers, result)) {
+ if (!c2_aidl::utils::ParseParamsBlob(¶mPointers, result.params)) {
LOG(ERROR) << "query -- error while parsing params.";
return C2_CORRUPTED;
}
size_t i = 0;
- for (auto it = paramPointers.begin();
- it != paramPointers.end(); ) {
+ size_t numUpdatedStackParams = 0;
+ for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
C2Param* paramPointer = *it;
if (numStackIndices > 0) {
--numStackIndices;
@@ -676,7 +677,9 @@
status = C2_BAD_INDEX;
continue;
}
- if (!stackParams[i++]->updateFrom(*paramPointer)) {
+ if (stackParams[i++]->updateFrom(*paramPointer)) {
+ ++numUpdatedStackParams;
+ } else {
LOG(WARNING) << "query -- param update failed: "
"index = "
<< paramPointer->index() << ".";
@@ -696,6 +699,13 @@
}
++it;
}
+ size_t numQueried = numUpdatedStackParams;
+ if (heapParams) {
+ numQueried += heapParams->size();
+ }
+ if (status == C2_OK && indices.size() != numQueried) {
+ status = C2_BAD_INDEX;
+ }
return status;
}
@@ -714,6 +724,7 @@
if (status != C2_OK) {
return status;
}
+ status = static_cast<c2_status_t>(result.status.status);
size_t i = failures->size();
failures->resize(i + result.failures.size());
for (const c2_aidl::SettingResult& sf : result.failures) {
@@ -764,21 +775,23 @@
}
}
- std::vector<c2_aidl::FieldSupportedValuesQueryResult> result;
+ c2_aidl::IConfigurable::QuerySupportedValuesResult result;
+
ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
inFields, (mayBlock == C2_MAY_BLOCK), &result);
c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
if (status != C2_OK) {
return status;
}
- if (result.size() != fields.size()) {
+ status = static_cast<c2_status_t>(result.status.status);
+ if (result.values.size() != fields.size()) {
LOG(ERROR) << "querySupportedValues -- "
"input and output lists "
"have different sizes.";
return C2_CORRUPTED;
}
for (size_t i = 0; i < fields.size(); ++i) {
- if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result[i])) {
+ if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result.values[i])) {
LOG(ERROR) << "querySupportedValues -- "
"invalid returned value.";
return C2_CORRUPTED;
diff --git a/media/codec2/hal/client/include/codec2/aidl/GraphicsTracker.h b/media/codec2/hal/client/include/codec2/aidl/GraphicsTracker.h
index 4640243..dd6c869 100644
--- a/media/codec2/hal/client/include/codec2/aidl/GraphicsTracker.h
+++ b/media/codec2/hal/client/include/codec2/aidl/GraphicsTracker.h
@@ -27,6 +27,7 @@
#include <mutex>
#include <set>
#include <thread>
+#include <optional>
#include <C2Buffer.h>
@@ -234,12 +235,14 @@
std::map<uint64_t, std::shared_ptr<BufferItem>> mDequeued;
std::set<uint64_t> mDeallocating;
+ // These member variables are read and modified accessed as follows.
+ // 1. mConfigLock being held
+ // Set mInConfig true with mLock in the beginning
+ // Clear mInConfig with mLock in the end
+ // 2. mLock is held and mInConfig is false.
int mMaxDequeue;
- int mMaxDequeueRequested;
int mMaxDequeueCommitted;
-
- uint32_t mMaxDequeueRequestedSeqId;
- uint32_t mMaxDequeueCommittedSeqId;
+ std::optional<int> mMaxDequeueRequested;
int mDequeueable;
@@ -271,13 +274,6 @@
::android::base::unique_fd mWritePipeFd; // The writing end file descriptor
std::atomic<bool> mStopped;
- std::thread mEventQueueThread; // Thread to handle interrupted
- // writes to the writing end.
- std::mutex mEventLock;
- std::condition_variable mEventCv;
-
- bool mStopEventThread;
- int mIncDequeueable; // pending # of write to increase dequeueable eventfd
private:
explicit GraphicsTracker(int maxDequeueCount);
@@ -289,6 +285,9 @@
bool adjustDequeueConfLocked(bool *updateDequeueConf);
void updateDequeueConf();
+ void clearCacheIfNecessaryLocked(
+ const std::shared_ptr<BufferCache> &cache,
+ int maxDequeueCommitted);
c2_status_t requestAllocate(std::shared_ptr<BufferCache> *cache);
c2_status_t requestDeallocate(uint64_t bid, const sp<Fence> &fence,
@@ -305,7 +304,9 @@
bool cached, int slotId, const sp<Fence> &fence,
std::shared_ptr<BufferItem> *buffer,
bool *updateDequeue);
- void commitDeallocate(std::shared_ptr<BufferCache> &cache, int slotId, uint64_t bid);
+ void commitDeallocate(std::shared_ptr<BufferCache> &cache,
+ int slotId, uint64_t bid,
+ bool *updateDequeue);
void commitRender(const std::shared_ptr<BufferCache> &cache,
const std::shared_ptr<BufferItem> &buffer,
const std::shared_ptr<BufferItem> &oldBuffer,
@@ -318,8 +319,8 @@
bool *cached, int *rSlotId, sp<Fence> *rFence,
std::shared_ptr<BufferItem> *buffer);
- void writeIncDequeueable(int inc);
- void processEvent();
+ void writeIncDequeueableLocked(int inc);
+ void drainDequeueableLocked(int dec);
};
} // namespace aidl::android::hardware::media::c2::implementation
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index fdb28f4..df89510 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -29,6 +29,7 @@
#include <C2BufferPriv.h>
#include <C2Config.h>
#include <C2Debug.h>
+#include <codec2/common/HalSelection.h>
#include <codec2/hidl/client.h>
#include <gui/BufferQueue.h>
#include <gui/IConsumerListener.h>
@@ -407,30 +408,45 @@
surfaceMode_t surfMode) {
using namespace android;
sp<IGraphicBufferProducer> producer = nullptr;
+ sp<IGraphicBufferConsumer> consumer = nullptr;
+ sp<GLConsumer> texture = nullptr;
+ sp<ANativeWindow> surface = nullptr;
static std::atomic_uint32_t surfaceGeneration{0};
uint32_t generation =
(getpid() << 10) |
((surfaceGeneration.fetch_add(1, std::memory_order_relaxed) + 1) & ((1 << 10) - 1));
int32_t maxDequeueBuffers = kSmoothnessFactor + kRenderingDepth;
+ C2BlockPool::local_id_t poolId = C2BlockPool::BASIC_GRAPHIC;
+ std::shared_ptr<Codec2Client::Configurable> configurable;
+ bool aidl = ::android::IsCodec2AidlHalSelected();
+ if (aidl) {
+ // AIDL does not support blockpool-less mode.
+ c2_status_t poolRet = component->createBlockPool(
+ C2PlatformAllocatorStore::IGBA, &poolId, &configurable);
+ ASSERT_EQ(poolRet, C2_OK) << "setOutputSurface failed";
+ }
+
if (surfMode == SURFACE) {
- sp<IGraphicBufferConsumer> consumer = nullptr;
BufferQueue::createBufferQueue(&producer, &consumer);
ASSERT_NE(producer, nullptr) << "createBufferQueue returned invalid producer";
ASSERT_NE(consumer, nullptr) << "createBufferQueue returned invalid consumer";
- sp<GLConsumer> texture =
+ texture =
new GLConsumer(consumer, 0 /* tex */, GLConsumer::TEXTURE_EXTERNAL,
true /* useFenceSync */, false /* isControlledByApp */);
- sp<ANativeWindow> gSurface = new Surface(producer);
- ASSERT_NE(gSurface, nullptr) << "getSurface failed";
+ surface = new Surface(producer);
+ ASSERT_NE(surface, nullptr) << "failed to create Surface object";
producer->setGenerationNumber(generation);
}
- c2_status_t err = component->setOutputSurface(C2BlockPool::BASIC_GRAPHIC, producer, generation,
+ c2_status_t err = component->setOutputSurface(poolId, producer, generation,
maxDequeueBuffers);
- ASSERT_EQ(err, C2_OK) << "setOutputSurface failed";
+ std::string surfStr = surfMode == NO_SURFACE ? "NO_SURFACE" :
+ (surfMode == NULL_SURFACE ? "NULL_SURFACE" : "WITH_SURFACE");
+
+ ASSERT_EQ(err, C2_OK) << "setOutputSurface failed, surfMode: " << surfStr;
}
void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index fbb4f18..8ecb9c0 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -19,6 +19,7 @@
#include <android-base/logging.h>
#include <android/binder_process.h>
+#include <codec2/common/HalSelection.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <stdio.h>
@@ -71,7 +72,9 @@
std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mGraphicAllocator),
C2_OK);
- mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++);
+ C2PooledBlockPool::BufferPoolVer ver = ::android::IsCodec2AidlHalSelected() ?
+ C2PooledBlockPool::VER_AIDL2 : C2PooledBlockPool::VER_HIDL;
+ mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++, ver);
ASSERT_NE(mGraphicPool, nullptr);
std::vector<std::unique_ptr<C2Param>> queried;
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 3bb6593..5c1755e 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -1049,7 +1049,11 @@
// Unwrap raw buffer handle from the C2Handle
native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
if (!nh) {
- return;
+ nh = UnwrapNativeCodec2AhwbHandle(handle);
+ if (!nh) {
+ ALOGE("handle is not compatible to neither C2HandleGralloc nor C2HandleAhwb");
+ return;
+ }
}
// Import the raw handle so IMapper can use the buffer. The imported
// handle must be freed when the client is done with the buffer.
diff --git a/media/codec2/tests/aidl/Android.bp b/media/codec2/tests/aidl/Android.bp
new file mode 100644
index 0000000..2ad245c
--- /dev/null
+++ b/media/codec2/tests/aidl/Android.bp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_test {
+ name: "c2aidl_gtracker_test",
+ test_suites: ["device-tests"],
+ defaults: [
+ "libcodec2-aidl-client-defaults",
+ ],
+
+ header_libs: [
+ "libcodec2_client_headers",
+ "libcodec2_internal",
+ "libcodec2_vndk_headers",
+ ],
+
+ srcs: [
+ "GraphicsTracker_test.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libcodec2_client",
+ "libgui",
+ "libnativewindow",
+ "libui",
+ ],
+}
diff --git a/media/codec2/tests/aidl/GraphicsTracker_test.cpp b/media/codec2/tests/aidl/GraphicsTracker_test.cpp
new file mode 100644
index 0000000..9008086
--- /dev/null
+++ b/media/codec2/tests/aidl/GraphicsTracker_test.cpp
@@ -0,0 +1,820 @@
+/*
+ * Copyright (C) 2023 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 "GraphicsTracker_test"
+#include <unistd.h>
+
+#include <android/hardware_buffer.h>
+#include <codec2/aidl/GraphicsTracker.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <gui/BufferQueue.h>
+#include <gui/IProducerListener.h>
+#include <gui/IConsumerListener.h>
+#include <gui/Surface.h>
+#include <private/android/AHardwareBufferHelpers.h>
+
+#include <C2BlockInternal.h>
+#include <C2FenceFactory.h>
+
+#include <atomic>
+#include <memory>
+#include <iostream>
+#include <thread>
+
+using ::aidl::android::hardware::media::c2::implementation::GraphicsTracker;
+using ::android::BufferItem;
+using ::android::BufferQueue;
+using ::android::Fence;
+using ::android::GraphicBuffer;
+using ::android::IGraphicBufferProducer;
+using ::android::IGraphicBufferConsumer;
+using ::android::IProducerListener;
+using ::android::IConsumerListener;
+using ::android::OK;
+using ::android::sp;
+using ::android::wp;
+
+namespace {
+struct BqStatistics {
+ std::atomic<int> mDequeued;
+ std::atomic<int> mQueued;
+ std::atomic<int> mBlocked;
+ std::atomic<int> mDropped;
+ std::atomic<int> mDiscarded;
+ std::atomic<int> mReleased;
+
+ void log() {
+ ALOGD("Dequeued: %d, Queued: %d, Blocked: %d, "
+ "Dropped: %d, Discarded %d, Released %d",
+ (int)mDequeued, (int)mQueued, (int)mBlocked,
+ (int)mDropped, (int)mDiscarded, (int)mReleased);
+ }
+
+ void clear() {
+ mDequeued = 0;
+ mQueued = 0;
+ mBlocked = 0;
+ mDropped = 0;
+ mDiscarded = 0;
+ mReleased = 0;
+ }
+};
+
+struct DummyConsumerListener : public android::BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+};
+
+struct TestConsumerListener : public android::BnConsumerListener {
+ TestConsumerListener(const sp<IGraphicBufferConsumer> &consumer)
+ : BnConsumerListener(), mConsumer(consumer) {}
+ void onFrameAvailable(const BufferItem&) override {
+ constexpr static int kRenderDelayUs = 1000000/30; // 30fps
+ BufferItem buffer;
+ // consume buffer
+ sp<IGraphicBufferConsumer> consumer = mConsumer.promote();
+ if (consumer != nullptr && consumer->acquireBuffer(&buffer, 0) == android::NO_ERROR) {
+ ::usleep(kRenderDelayUs);
+ consumer->releaseBuffer(buffer.mSlot, buffer.mFrameNumber,
+ EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, buffer.mFence);
+ }
+ }
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+
+ wp<IGraphicBufferConsumer> mConsumer;
+};
+
+struct TestProducerListener : public android::BnProducerListener {
+ TestProducerListener(std::shared_ptr<GraphicsTracker> tracker,
+ std::shared_ptr<BqStatistics> &stat,
+ uint32_t generation) : BnProducerListener(),
+ mTracker(tracker), mStat(stat), mGeneration(generation) {}
+ virtual void onBufferReleased() override {
+ auto tracker = mTracker.lock();
+ if (tracker) {
+ mStat->mReleased++;
+ tracker->onReleased(mGeneration);
+ }
+ }
+ virtual bool needsReleaseNotify() override { return true; }
+ virtual void onBuffersDiscarded(const std::vector<int32_t>&) override {}
+
+ std::weak_ptr<GraphicsTracker> mTracker;
+ std::shared_ptr<BqStatistics> mStat;
+ uint32_t mGeneration;
+};
+
+struct Frame {
+ AHardwareBuffer *buffer_;
+ sp<Fence> fence_;
+
+ Frame() : buffer_{nullptr}, fence_{nullptr} {}
+ Frame(AHardwareBuffer *buffer, sp<Fence> fence)
+ : buffer_(buffer), fence_(fence) {}
+ ~Frame() {
+ if (buffer_) {
+ AHardwareBuffer_release(buffer_);
+ }
+ }
+};
+
+struct FrameQueue {
+ bool mStopped;
+ bool mDrain;
+ std::queue<std::shared_ptr<Frame>> mQueue;
+ std::mutex mMutex;
+ std::condition_variable mCond;
+
+ FrameQueue() : mStopped{false}, mDrain{false} {}
+
+ bool queueItem(AHardwareBuffer *buffer, sp<Fence> fence) {
+ std::shared_ptr<Frame> frame = std::make_shared<Frame>(buffer, fence);
+ if (mStopped) {
+ return false;
+ }
+ if (!frame) {
+ return false;
+ }
+ std::unique_lock<std::mutex> l(mMutex);
+ mQueue.emplace(frame);
+ l.unlock();
+ mCond.notify_all();
+ return true;
+ }
+
+ void stop(bool drain = false) {
+ bool stopped = false;
+ {
+ std::unique_lock<std::mutex> l(mMutex);
+ if (!mStopped) {
+ mStopped = true;
+ mDrain = drain;
+ stopped = true;
+ }
+ l.unlock();
+ if (stopped) {
+ mCond.notify_all();
+ }
+ }
+ }
+
+ bool waitItem(std::shared_ptr<Frame> *frame) {
+ while(true) {
+ std::unique_lock<std::mutex> l(mMutex);
+ if (!mDrain && mStopped) {
+ // stop without consuming the queue.
+ return false;
+ }
+ if (!mQueue.empty()) {
+ *frame = mQueue.front();
+ mQueue.pop();
+ return true;
+ } else if (mStopped) {
+ // stop after consuming the queue.
+ return false;
+ }
+ mCond.wait(l);
+ }
+ }
+};
+
+} // namespace anonymous
+
+class GraphicsTrackerTest : public ::testing::Test {
+public:
+ const uint64_t kTestUsageFlag = GRALLOC_USAGE_SW_WRITE_OFTEN;
+
+ void queueBuffer(FrameQueue *queue) {
+ while (true) {
+ std::shared_ptr<Frame> frame;
+ if (!queue->waitItem(&frame)) {
+ break;
+ }
+ uint64_t bid;
+ if (__builtin_available(android __ANDROID_API_T__, *)) {
+ if (AHardwareBuffer_getId(frame->buffer_, &bid) !=
+ android::NO_ERROR) {
+ break;
+ }
+ } else {
+ break;
+ }
+ android::status_t ret = frame->fence_->wait(-1);
+ if (ret != android::NO_ERROR) {
+ mTracker->deallocate(bid, frame->fence_);
+ mBqStat->mDiscarded++;
+ continue;
+ }
+
+ std::shared_ptr<C2GraphicBlock> blk =
+ _C2BlockFactory::CreateGraphicBlock(frame->buffer_);
+ if (!blk) {
+ mTracker->deallocate(bid, Fence::NO_FENCE);
+ mBqStat->mDiscarded++;
+ continue;
+ }
+ IGraphicBufferProducer::QueueBufferInput input(
+ 0, false,
+ HAL_DATASPACE_UNKNOWN, android::Rect(0, 0, 1, 1),
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+ IGraphicBufferProducer::QueueBufferOutput output{};
+ c2_status_t res = mTracker->render(
+ blk->share(C2Rect(1, 1), C2Fence()),
+ input, &output);
+ if (res != C2_OK) {
+ mTracker->deallocate(bid, Fence::NO_FENCE);
+ mBqStat->mDiscarded++;
+ continue;
+ }
+ if (output.bufferReplaced) {
+ mBqStat->mDropped++;
+ }
+ mBqStat->mQueued++;
+ }
+ }
+
+ void stopTrackerAfterUs(int us) {
+ ::usleep(us);
+ mTracker->stop();
+ }
+
+protected:
+ bool init(int maxDequeueCount) {
+ mTracker = GraphicsTracker::CreateGraphicsTracker(maxDequeueCount);
+ if (!mTracker) {
+ return false;
+ }
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ if (!mProducer || !mConsumer) {
+ return false;
+ }
+ return true;
+ }
+ bool configure(sp<IProducerListener> producerListener,
+ sp<IConsumerListener> consumerListener,
+ int maxAcquiredCount = 1, bool controlledByApp = true) {
+ if (mConsumer->consumerConnect(
+ consumerListener, controlledByApp) != ::android::NO_ERROR) {
+ return false;
+ }
+ if (mConsumer->setMaxAcquiredBufferCount(maxAcquiredCount) != ::android::NO_ERROR) {
+ return false;
+ }
+ IGraphicBufferProducer::QueueBufferOutput qbo{};
+ if (mProducer->connect(producerListener,
+ NATIVE_WINDOW_API_MEDIA, true, &qbo) != ::android::NO_ERROR) {
+ return false;
+ }
+ if (mProducer->setDequeueTimeout(0) != ::android::NO_ERROR) {
+ return false;
+ }
+ return true;
+ }
+
+ virtual void TearDown() override {
+ mBqStat->log();
+ mBqStat->clear();
+
+ if (mTracker) {
+ mTracker->stop();
+ mTracker.reset();
+ }
+ if (mProducer) {
+ mProducer->disconnect(NATIVE_WINDOW_API_MEDIA);
+ }
+ mProducer.clear();
+ mConsumer.clear();
+ }
+
+protected:
+ std::shared_ptr<BqStatistics> mBqStat = std::make_shared<BqStatistics>();
+ sp<IGraphicBufferProducer> mProducer;
+ sp<IGraphicBufferConsumer> mConsumer;
+ std::shared_ptr<GraphicsTracker> mTracker;
+};
+
+
+TEST_F(GraphicsTrackerTest, AllocateAndBlockedTest) {
+ uint32_t generation = 1;
+ const int maxDequeueCount = 10;
+
+ ASSERT_TRUE(init(maxDequeueCount));
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new DummyConsumerListener()));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+ c2_status_t ret = mTracker->configureGraphics(mProducer, generation);
+ ASSERT_EQ(C2_OK, ret);
+ ASSERT_EQ(maxDequeueCount, mTracker->getCurDequeueable());
+
+ AHardwareBuffer *buf;
+ sp<Fence> fence;
+ uint64_t bid;
+
+ // Allocate and check dequeueable
+ if (__builtin_available(android __ANDROID_API_T__, *)) {
+ for (int i = 0; i < maxDequeueCount; ++i) {
+ ret = mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf, &fence);
+ ASSERT_EQ(C2_OK, ret);
+ mBqStat->mDequeued++;
+ ASSERT_EQ(maxDequeueCount - (i + 1), mTracker->getCurDequeueable());
+ ASSERT_EQ(OK, AHardwareBuffer_getId(buf, &bid));
+ ALOGD("alloced : bufferId: %llu", (unsigned long long)bid);
+ AHardwareBuffer_release(buf);
+ }
+ } else {
+ GTEST_SKIP();
+ }
+
+ // Allocate should be blocked
+ ret = mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf, &fence);
+ ALOGD("alloc : err(%d, %d)", ret, C2_BLOCKING);
+ ASSERT_EQ(C2_BLOCKING, ret);
+ mBqStat->mBlocked++;
+ ASSERT_EQ(0, mTracker->getCurDequeueable());
+}
+
+TEST_F(GraphicsTrackerTest, AllocateAndDeallocateTest) {
+ uint32_t generation = 1;
+ const int maxDequeueCount = 10;
+
+ ASSERT_TRUE(init(maxDequeueCount));
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new DummyConsumerListener()));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+ c2_status_t ret = mTracker->configureGraphics(mProducer, generation);
+ ASSERT_EQ(C2_OK, ret);
+
+ ASSERT_EQ(maxDequeueCount, mTracker->getCurDequeueable());
+ AHardwareBuffer *buf;
+ sp<Fence> fence;
+ uint64_t bid;
+ std::vector<uint64_t> bids;
+
+ // Allocate and store buffer id
+ if (__builtin_available(android __ANDROID_API_T__, *)) {
+ for (int i = 0; i < maxDequeueCount; ++i) {
+ ret = mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf, &fence);
+ ASSERT_EQ(C2_OK, ret);
+ mBqStat->mDequeued++;
+ ASSERT_EQ(OK, AHardwareBuffer_getId(buf, &bid));
+ bids.push_back(bid);
+ ALOGD("alloced : bufferId: %llu", (unsigned long long)bid);
+ AHardwareBuffer_release(buf);
+ }
+ } else {
+ GTEST_SKIP();
+ }
+
+ // Deallocate and check dequeueable
+ for (int i = 0; i < maxDequeueCount; ++i) {
+ ALOGD("dealloc : bufferId: %llu", (unsigned long long)bids[i]);
+ ret = mTracker->deallocate(bids[i], Fence::NO_FENCE);
+ ASSERT_EQ(C2_OK, ret);
+ ASSERT_EQ(i + 1, mTracker->getCurDequeueable());
+ mBqStat->mDiscarded++;
+ }
+}
+
+TEST_F(GraphicsTrackerTest, DropAndReleaseTest) {
+ uint32_t generation = 1;
+ const int maxDequeueCount = 10;
+
+ ASSERT_TRUE(init(maxDequeueCount));
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new DummyConsumerListener()));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+ c2_status_t ret = mTracker->configureGraphics(mProducer, generation);
+ ASSERT_EQ(C2_OK, ret);
+
+ ASSERT_EQ(maxDequeueCount, mTracker->getCurDequeueable());
+
+ FrameQueue frameQueue;
+ std::thread queueThread(&GraphicsTrackerTest::queueBuffer, this, &frameQueue);
+ AHardwareBuffer *buf1, *buf2;
+ sp<Fence> fence1, fence2;
+
+ ret = mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf1, &fence1);
+ ASSERT_EQ(C2_OK, ret);
+ mBqStat->mDequeued++;
+ ASSERT_EQ(maxDequeueCount - 1, mTracker->getCurDequeueable());
+
+ ret = mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf2, &fence2);
+ ASSERT_EQ(C2_OK, ret);
+ mBqStat->mDequeued++;
+ ASSERT_EQ(maxDequeueCount - 2, mTracker->getCurDequeueable());
+
+ // Queue two buffers without consuming, one should be dropped
+ ASSERT_TRUE(frameQueue.queueItem(buf1, fence1));
+ ASSERT_TRUE(frameQueue.queueItem(buf2, fence2));
+
+ frameQueue.stop(true);
+ if (queueThread.joinable()) {
+ queueThread.join();
+ }
+
+ ASSERT_EQ(maxDequeueCount - 1, mTracker->getCurDequeueable());
+
+ // Consume one buffer and release
+ BufferItem item;
+ ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+ EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence));
+ // Nothing to consume
+ ASSERT_NE(OK, mConsumer->acquireBuffer(&item, 0));
+
+ ASSERT_EQ(maxDequeueCount, mTracker->getCurDequeueable());
+ ASSERT_EQ(1, mBqStat->mReleased);
+ ASSERT_EQ(1, mBqStat->mDropped);
+}
+
+TEST_F(GraphicsTrackerTest, RenderTest) {
+ uint32_t generation = 1;
+ const int maxDequeueCount = 10;
+ const int maxNumAlloc = 20;
+
+ ASSERT_TRUE(init(maxDequeueCount));
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new TestConsumerListener(mConsumer), 1, false));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+
+ ASSERT_EQ(C2_OK, mTracker->configureGraphics(mProducer, generation));
+ ASSERT_EQ(C2_OK, mTracker->configureMaxDequeueCount(maxDequeueCount));
+
+ int waitFd = -1;
+ ASSERT_EQ(C2_OK, mTracker->getWaitableFd(&waitFd));
+ C2Fence waitFence = _C2FenceFactory::CreatePipeFence(waitFd);
+
+
+ FrameQueue frameQueue;
+ std::thread queueThread(&GraphicsTrackerTest::queueBuffer, this, &frameQueue);
+
+ int numAlloc = 0;
+
+ while (numAlloc < maxNumAlloc) {
+ AHardwareBuffer *buf;
+ sp<Fence> fence;
+ c2_status_t ret = mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf, &fence);
+ if (ret == C2_BLOCKING) {
+ mBqStat->mBlocked++;
+ c2_status_t waitRes = waitFence.wait(3000000000);
+ if (waitRes == C2_TIMED_OUT || waitRes == C2_OK) {
+ continue;
+ }
+ ALOGE("alloc wait failed: c2_err(%d)", waitRes);
+ break;
+ }
+ if (ret != C2_OK) {
+ ALOGE("alloc error: c2_err(%d)", ret);
+ break;
+ }
+ mBqStat->mDequeued++;
+ if (!frameQueue.queueItem(buf, fence)) {
+ ALOGE("queue to render failed");
+ break;
+ }
+ ++numAlloc;
+ }
+
+ frameQueue.stop(true);
+ // Wait more than enough time(1 sec) to render all queued frames for sure.
+ ::usleep(1000000);
+
+ if (queueThread.joinable()) {
+ queueThread.join();
+ }
+ ASSERT_EQ(numAlloc, maxNumAlloc);
+ ASSERT_EQ(numAlloc, mBqStat->mDequeued);
+ ASSERT_EQ(mBqStat->mDequeued, mBqStat->mQueued);
+ ASSERT_EQ(mBqStat->mDequeued, mBqStat->mReleased + mBqStat->mDropped);
+}
+
+TEST_F(GraphicsTrackerTest, StopAndWaitTest) {
+ uint32_t generation = 1;
+ const int maxDequeueCount = 2;
+
+ ASSERT_TRUE(init(maxDequeueCount));
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new TestConsumerListener(mConsumer), 1, false));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+
+ ASSERT_EQ(C2_OK, mTracker->configureGraphics(mProducer, generation));
+ ASSERT_EQ(C2_OK, mTracker->configureMaxDequeueCount(maxDequeueCount));
+
+ int waitFd = -1;
+ ASSERT_EQ(C2_OK, mTracker->getWaitableFd(&waitFd));
+ C2Fence waitFence = _C2FenceFactory::CreatePipeFence(waitFd);
+
+ AHardwareBuffer *buf1, *buf2;
+ sp<Fence> fence;
+
+ ASSERT_EQ(C2_OK, mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf1, &fence));
+ mBqStat->mDequeued++;
+ AHardwareBuffer_release(buf1);
+
+ ASSERT_EQ(C2_OK, mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf2, &fence));
+ mBqStat->mDequeued++;
+ AHardwareBuffer_release(buf2);
+
+ ASSERT_EQ(0, mTracker->getCurDequeueable());
+ ASSERT_EQ(C2_TIMED_OUT, waitFence.wait(3000000000));
+
+ std::thread stopThread(&GraphicsTrackerTest::stopTrackerAfterUs, this, 500000);
+ ASSERT_EQ(C2_BAD_STATE, waitFence.wait(3000000000));
+
+ if (stopThread.joinable()) {
+ stopThread.join();
+ }
+}
+
+TEST_F(GraphicsTrackerTest, SurfaceChangeTest) {
+ uint32_t generation = 1;
+ const int maxDequeueCount = 10;
+
+ const int maxNumAlloc = 20;
+
+ const int firstPassAlloc = 12;
+ const int firstPassRender = 8;
+
+ ASSERT_TRUE(init(maxDequeueCount));
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new TestConsumerListener(mConsumer), 1, false));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+
+ ASSERT_EQ(C2_OK, mTracker->configureGraphics(mProducer, generation));
+ ASSERT_EQ(C2_OK, mTracker->configureMaxDequeueCount(maxDequeueCount));
+
+ int waitFd = -1;
+ ASSERT_EQ(C2_OK, mTracker->getWaitableFd(&waitFd));
+ C2Fence waitFence = _C2FenceFactory::CreatePipeFence(waitFd);
+
+ AHardwareBuffer *bufs[maxNumAlloc];
+ sp<Fence> fences[maxNumAlloc];
+
+ FrameQueue frameQueue;
+ std::thread queueThread(&GraphicsTrackerTest::queueBuffer, this, &frameQueue);
+ int numAlloc = 0;
+
+ for (int i = 0; i < firstPassRender; ++i) {
+ ASSERT_EQ(C2_OK, mTracker->allocate(
+ 0, 0, 0, kTestUsageFlag, &bufs[i], &fences[i]));
+ mBqStat->mDequeued++;
+ numAlloc++;
+ ASSERT_EQ(true, frameQueue.queueItem(bufs[i], fences[i]));
+ }
+
+ while (numAlloc < firstPassAlloc) {
+ c2_status_t ret = mTracker->allocate(
+ 0, 0, 0, kTestUsageFlag, &bufs[numAlloc], &fences[numAlloc]);
+ if (ret == C2_BLOCKING) {
+ mBqStat->mBlocked++;
+ c2_status_t waitRes = waitFence.wait(3000000000);
+ if (waitRes == C2_TIMED_OUT || waitRes == C2_OK) {
+ continue;
+ }
+ ALOGE("alloc wait failed: c2_err(%d)", waitRes);
+ break;
+ }
+ if (ret != C2_OK) {
+ ALOGE("alloc error: c2_err(%d)", ret);
+ break;
+ }
+ mBqStat->mDequeued++;
+ numAlloc++;
+ }
+ ASSERT_EQ(numAlloc, firstPassAlloc);
+
+ // switching surface
+ sp<IGraphicBufferProducer> oldProducer = mProducer;
+ sp<IGraphicBufferConsumer> oldConsumer = mConsumer;
+ mProducer.clear();
+ mConsumer.clear();
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ ASSERT_TRUE((bool)mProducer && (bool)mConsumer);
+
+ generation += 1;
+
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new TestConsumerListener(mConsumer), 1, false));
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+ ASSERT_EQ(C2_OK, mTracker->configureGraphics(mProducer, generation));
+ ASSERT_EQ(C2_OK, mTracker->configureMaxDequeueCount(maxDequeueCount));
+
+ ASSERT_EQ(OK, oldProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
+ oldProducer.clear();
+ oldConsumer.clear();
+
+ for (int i = firstPassRender ; i < firstPassAlloc; ++i) {
+ ASSERT_EQ(true, frameQueue.queueItem(bufs[i], fences[i]));
+ }
+
+ while (numAlloc < maxNumAlloc) {
+ AHardwareBuffer *buf;
+ sp<Fence> fence;
+ c2_status_t ret = mTracker->allocate(0, 0, 0, kTestUsageFlag, &buf, &fence);
+ if (ret == C2_BLOCKING) {
+ mBqStat->mBlocked++;
+ c2_status_t waitRes = waitFence.wait(3000000000);
+ if (waitRes == C2_TIMED_OUT || waitRes == C2_OK) {
+ continue;
+ }
+ ALOGE("alloc wait failed: c2_err(%d)", waitRes);
+ break;
+ }
+ if (ret != C2_OK) {
+ ALOGE("alloc error: c2_err(%d)", ret);
+ break;
+ }
+ mBqStat->mDequeued++;
+ if (!frameQueue.queueItem(buf, fence)) {
+ ALOGE("queue to render failed");
+ break;
+ }
+ ++numAlloc;
+ }
+
+ ASSERT_EQ(numAlloc, maxNumAlloc);
+
+ frameQueue.stop(true);
+ // Wait more than enough time(1 sec) to render all queued frames for sure.
+ ::usleep(1000000);
+
+ if (queueThread.joinable()) {
+ queueThread.join();
+ }
+ // mReleased should not be checked. IProducerListener::onBufferReleased()
+ // from the previous Surface could be missing after a new Surface was
+ // configured. Instead check # of dequeueable and queueBuffer() calls.
+ ASSERT_EQ(numAlloc, mBqStat->mQueued);
+ ASSERT_EQ(maxDequeueCount, mTracker->getCurDequeueable());
+
+ for (int i = 0; i < maxDequeueCount; ++i) {
+ AHardwareBuffer *buf;
+ sp<Fence> fence;
+
+ ASSERT_EQ(C2_OK, mTracker->allocate(
+ 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ AHardwareBuffer_release(buf);
+ mBqStat->mDequeued++;
+ numAlloc++;
+ }
+ ASSERT_EQ(C2_BLOCKING, mTracker->allocate(
+ 0, 0, 0, kTestUsageFlag, &bufs[0], &fences[0]));
+}
+
+TEST_F(GraphicsTrackerTest, maxDequeueIncreaseTest) {
+ uint32_t generation = 1;
+ int maxDequeueCount = 10;
+ int dequeueIncrease = 4;
+
+ int numAlloc = 0;
+
+ ASSERT_TRUE(init(maxDequeueCount));
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new TestConsumerListener(mConsumer), 1, false));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+ ASSERT_EQ(C2_OK, mTracker->configureGraphics(mProducer, generation));
+
+ int waitFd = -1;
+ ASSERT_EQ(C2_OK, mTracker->getWaitableFd(&waitFd));
+ C2Fence waitFence = _C2FenceFactory::CreatePipeFence(waitFd);
+
+ AHardwareBuffer *buf;
+ sp<Fence> fence;
+ uint64_t bids[maxDequeueCount];
+ if (__builtin_available(android __ANDROID_API_T__, *)) {
+ for (int i = 0; i < maxDequeueCount; ++i) {
+ ASSERT_EQ(C2_OK, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_OK, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ ASSERT_EQ(OK, AHardwareBuffer_getId(buf, &bids[i]));
+ AHardwareBuffer_release(buf);
+ mBqStat->mDequeued++;
+ numAlloc++;
+ }
+ } else {
+ GTEST_SKIP();
+ }
+ ASSERT_EQ(C2_TIMED_OUT, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_BLOCKING, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+
+ ASSERT_EQ(C2_OK, mTracker->deallocate(bids[0], Fence::NO_FENCE));
+ mBqStat->mDiscarded++;
+
+ maxDequeueCount += dequeueIncrease;
+ ASSERT_EQ(C2_OK, mTracker->configureMaxDequeueCount(maxDequeueCount));
+ for (int i = 0; i < dequeueIncrease + 1; ++i) {
+ ASSERT_EQ(C2_OK, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_OK, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ AHardwareBuffer_release(buf);
+ mBqStat->mDequeued++;
+ numAlloc++;
+ }
+ ASSERT_EQ(C2_TIMED_OUT, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_BLOCKING, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+
+ ASSERT_EQ(C2_OK, mTracker->deallocate(bids[1], Fence::NO_FENCE));
+ mBqStat->mDiscarded++;
+
+ maxDequeueCount += dequeueIncrease;
+ ASSERT_EQ(C2_OK, mTracker->configureMaxDequeueCount(maxDequeueCount));
+ for (int i = 0; i < dequeueIncrease + 1; ++i) {
+ ASSERT_EQ(C2_OK, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_OK, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ AHardwareBuffer_release(buf);
+ mBqStat->mDequeued++;
+ numAlloc++;
+ }
+ ASSERT_EQ(C2_TIMED_OUT, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_BLOCKING, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+}
+
+TEST_F(GraphicsTrackerTest, maxDequeueDecreaseTest) {
+ uint32_t generation = 1;
+ int maxDequeueCount = 12;
+ int dequeueDecrease = 4;
+
+ int numAlloc = 0;
+
+ ASSERT_TRUE(init(maxDequeueCount));
+ ASSERT_TRUE(configure(new TestProducerListener(mTracker, mBqStat, generation),
+ new TestConsumerListener(mConsumer), 1, false));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(generation));
+ ASSERT_EQ(C2_OK, mTracker->configureGraphics(mProducer, generation));
+
+ int waitFd = -1;
+ ASSERT_EQ(C2_OK, mTracker->getWaitableFd(&waitFd));
+ C2Fence waitFence = _C2FenceFactory::CreatePipeFence(waitFd);
+
+ AHardwareBuffer *buf;
+ sp<Fence> fence;
+ uint64_t bids[maxDequeueCount];
+ if (__builtin_available(android __ANDROID_API_T__, *)) {
+ for (int i = 0; i < maxDequeueCount; ++i) {
+ ASSERT_EQ(C2_OK, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_OK, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ ASSERT_EQ(OK, AHardwareBuffer_getId(buf, &bids[i]));
+ AHardwareBuffer_release(buf);
+ mBqStat->mDequeued++;
+ numAlloc++;
+ }
+ } else {
+ GTEST_SKIP();
+ }
+ ASSERT_EQ(C2_TIMED_OUT, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_BLOCKING, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+
+ int discardIdx = 0;
+ maxDequeueCount -= dequeueDecrease;
+ ASSERT_EQ(C2_OK, mTracker->configureMaxDequeueCount(maxDequeueCount));
+ for (int i = 0; i < dequeueDecrease + 1; ++i) {
+ ASSERT_EQ(C2_TIMED_OUT, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_BLOCKING, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ ASSERT_EQ(C2_OK, mTracker->deallocate(bids[discardIdx++], Fence::NO_FENCE));
+ mBqStat->mDiscarded++;
+ }
+ ASSERT_EQ(C2_OK, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_OK, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ mBqStat->mDequeued++;
+
+ ASSERT_EQ(C2_OK, mTracker->deallocate(bids[discardIdx++], Fence::NO_FENCE));
+ mBqStat->mDiscarded++;
+ ASSERT_EQ(C2_OK, mTracker->deallocate(bids[discardIdx++], Fence::NO_FENCE));
+ mBqStat->mDiscarded++;
+ maxDequeueCount -= dequeueDecrease;
+
+ ASSERT_EQ(C2_OK, mTracker->configureMaxDequeueCount(maxDequeueCount));
+ for (int i = 0; i < dequeueDecrease - 1; ++i) {
+ ASSERT_EQ(C2_TIMED_OUT, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_BLOCKING, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ ASSERT_EQ(C2_OK, mTracker->deallocate(bids[discardIdx++], Fence::NO_FENCE));
+ mBqStat->mDiscarded++;
+ }
+ ASSERT_EQ(C2_OK, waitFence.wait(1000000000));
+ ASSERT_EQ(C2_OK, mTracker->allocate( 0, 0, 0, kTestUsageFlag, &buf, &fence));
+ mBqStat->mDequeued++;
+}
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index af2683b..9f57bfd 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -84,7 +84,7 @@
"libbase",
"libdmabufheap",
"android.hardware.media.bufferpool@2.0",
- "android.hardware.media.bufferpool2-V1-ndk",
+ "android.hardware.media.bufferpool2-V2-ndk",
],
local_include_dirs: [
@@ -102,7 +102,7 @@
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"android.hardware.media.bufferpool@2.0",
- "android.hardware.media.bufferpool2-V1-ndk",
+ "android.hardware.media.bufferpool2-V2-ndk",
"android.hardware.media.c2-V1-ndk",
"libbase",
"libbinder_ndk",
@@ -162,11 +162,12 @@
"android.hardware.graphics.bufferqueue@2.0",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
- "android.hardware.media.bufferpool2-V1-ndk",
+ "android.hardware.media.bufferpool2-V2-ndk",
"android.hardware.media.c2-V1-ndk",
],
shared_libs: [
+ "libbinder",
"libbinder_ndk",
"libui",
"libdl",
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 107ce89..60b5b29 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -383,7 +383,7 @@
}
uint8_t *pointer = nullptr;
- err = mapper.lock(handle, usage, bounds, (void **)&pointer, nullptr, nullptr);
+ err = mapper.lock(handle, usage, bounds, (void **)&pointer);
if (err != NO_ERROR || pointer == nullptr) {
return C2_CORRUPTED;
}
diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp
index 52ebe25..5d50fc3 100644
--- a/media/codec2/vndk/C2Fence.cpp
+++ b/media/codec2/vndk/C2Fence.cpp
@@ -335,7 +335,8 @@
p.reset();
}
} else {
- ALOGE("Create sync fence from invalid fd");
+ ALOGV("Create sync fence from invalid fd");
+ return C2Fence();
}
return C2Fence(p);
}
@@ -531,7 +532,9 @@
p = SyncFenceImpl::CreateFromNativeHandle(handle);
break;
default:
- ALOGD("Unsupported fence type %d", type);
+ ALOGV("Unsupported fence type %d", type);
+ // If this is malformed-handle close the handle here.
+ (void) native_handle_close(handle);
// return a null-fence in this case
break;
}
diff --git a/media/codec2/vndk/platform/C2IgbaBuffer.cpp b/media/codec2/vndk/platform/C2IgbaBuffer.cpp
index 2051e8f..eafdb22 100644
--- a/media/codec2/vndk/platform/C2IgbaBuffer.cpp
+++ b/media/codec2/vndk/platform/C2IgbaBuffer.cpp
@@ -193,7 +193,7 @@
width, height, format, usage, kBlockingFetchTimeoutNs, &origId, block, &fence);
if (res == C2_BLOCKING) {
- return C2_TIMED_OUT;
+ return C2_BLOCKING;
}
if (res != C2_OK) {
return res;
diff --git a/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp b/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
index e1ff3eb..1b06ea7 100644
--- a/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
+++ b/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
@@ -19,6 +19,8 @@
#include "aaudio/AAudioTesting.h"
#include <fuzzer/FuzzedDataProvider.h>
+#include <functional>
+
constexpr int32_t kRandomStringLength = 256;
constexpr int32_t kMaxRuns = 100;
constexpr int64_t kNanosPerMillisecond = 1000 * 1000;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index f050a20..ae37152 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1704,10 +1704,14 @@
__func__, mPortId, deviceId, mSelectedDeviceId, mRoutedDeviceId);
if (mSelectedDeviceId != deviceId) {
mSelectedDeviceId = deviceId;
- if (mStatus == NO_ERROR && mSelectedDeviceId != mRoutedDeviceId) {
+ if (mStatus == NO_ERROR) {
+ // allow track invalidation when track is not playing to propagate
+ // the updated mSelectedDeviceId
if (isPlaying_l()) {
- android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
- mProxy->interrupt();
+ if (mSelectedDeviceId != mRoutedDeviceId) {
+ android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
+ mProxy->interrupt();
+ }
} else {
// if the track is idle, try to restore now and
// defer to next start if not possible
diff --git a/media/libaudioclient/TEST_MAPPING b/media/libaudioclient/TEST_MAPPING
index bd508b3..234e858 100644
--- a/media/libaudioclient/TEST_MAPPING
+++ b/media/libaudioclient/TEST_MAPPING
@@ -41,11 +41,19 @@
}
]
}
- ]
+ ],
+ "postsubmit": [
// TODO(b/302036943): Enable once we make it pass with AIDL HAL on CF.
- // "postsubmit": [
// {
// "name": "audioeffect_analysis"
- // }
- // ]
+ // },
+ {
+ "name": "CtsVirtualDevicesTestCases",
+ "options" : [
+ {
+ "include-filter": "android.virtualdevice.cts.VirtualAudioTest"
+ }
+ ]
+ }
+ ]
}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index fc3f699..2af18cc 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -974,7 +974,7 @@
if (mModule == nullptr) return NO_INIT;
{
std::lock_guard l(mLock);
- mMapper.resetUnusedPatchesAndPortConfigs();
+ mMapper.resetUnusedPatchesPortConfigsAndPorts();
}
ModuleDebug debug{ .simulateDeviceConnections = enabled };
status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 196b432..39999a5 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -180,18 +180,6 @@
State state;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
- // in case of buffer/ioHandle re-configure for an opened effect, close it and re-open
- if (state != State::INIT && mCommon != common) {
- ALOGI("%s at state %s, common parameter change from %s to %s, closing effect", __func__,
- android::internal::ToString(state).c_str(), mCommon.toString().c_str(),
- common.toString().c_str());
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->close()));
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
- mStatusQ.reset();
- mInputQ.reset();
- mOutputQ.reset();
- }
-
if (state == State::INIT) {
ALOGI("%s at state %s, opening effect with input %s output %s", __func__,
android::internal::ToString(state).c_str(), common.input.toString().c_str(),
@@ -199,16 +187,7 @@
IEffect::OpenEffectReturn openReturn;
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn)));
-
- if (mIsProxyEffect) {
- mStatusQ = std::static_pointer_cast<EffectProxy>(mEffect)->getStatusMQ();
- mInputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getInputMQ();
- mOutputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getOutputMQ();
- } else {
- mStatusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
- mInputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
- mOutputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ);
- }
+ updateMqs(openReturn);
if (status_t status = updateEventFlags(); status != OK) {
ALOGV("%s closing at status %d", __func__, status);
@@ -225,6 +204,18 @@
return *static_cast<int32_t*>(pReplyData) = OK;
}
+void EffectConversionHelperAidl::updateMqs(const IEffect::OpenEffectReturn& ret) {
+ if (mIsProxyEffect) {
+ mStatusQ = std::static_pointer_cast<EffectProxy>(mEffect)->getStatusMQ();
+ mInputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getInputMQ();
+ mOutputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getOutputMQ();
+ } else {
+ mStatusQ = std::make_shared<StatusMQ>(ret.statusMQ);
+ mInputQ = std::make_shared<DataMQ>(ret.inputDataMQ);
+ mOutputQ = std::make_shared<DataMQ>(ret.outputDataMQ);
+ }
+}
+
status_t EffectConversionHelperAidl::handleGetConfig(uint32_t cmdSize __unused,
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
@@ -517,5 +508,13 @@
return desc;
}
+status_t EffectConversionHelperAidl::reopen() {
+ IEffect::OpenEffectReturn openReturn;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->reopen(&openReturn)));
+
+ updateMqs(openReturn);
+ return OK;
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 5db334c..8b9efb3 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -47,6 +47,7 @@
bool isBypassingOrTunnel() const;
::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
+ status_t reopen();
protected:
const int32_t mSessionId;
@@ -108,6 +109,8 @@
std::shared_ptr<android::hardware::EventFlag> mEfGroup = nullptr;
status_t updateEventFlags();
+ void updateMqs(const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn& ret);
+
status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
status_t handleSetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index f26444c..2836727 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -56,6 +56,7 @@
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::IEffect;
using ::aidl::android::hardware::audio::effect::IFactory;
+using ::aidl::android::hardware::audio::effect::kEventFlagDataMqUpdate;
using ::aidl::android::hardware::audio::effect::State;
namespace android {
@@ -165,26 +166,37 @@
// write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
status_t EffectHalAidl::process() {
+ const std::string effectName = mConversion->getDescriptor().common.name;
State state = State::INIT;
if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
state != State::PROCESSING) {
- ALOGI("%s skipping %s process because it's %s", __func__,
- mConversion->getDescriptor().common.name.c_str(),
+ ALOGI("%s skipping %s process because it's %s", __func__, effectName.c_str(),
mConversion->isBypassing()
? "bypassing"
: aidl::android::hardware::audio::effect::toString(state).c_str());
return -ENODATA;
}
+ // check if the DataMq needs any update, timeout at 1ns to avoid being blocked
+ auto efGroup = mConversion->getEventFlagGroup();
+ if (!efGroup) {
+ ALOGE("%s invalid efGroup", __func__);
+ return INVALID_OPERATION;
+ }
+
+ if (uint32_t efState = 0;
+ ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState, 1 /* ns */,
+ true /* retry */)) {
+ ALOGI("%s %s receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str());
+ mConversion->reopen();
+ }
auto statusQ = mConversion->getStatusMQ();
auto inputQ = mConversion->getInputMQ();
auto outputQ = mConversion->getOutputMQ();
- auto efGroup = mConversion->getEventFlagGroup();
if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
- !outputQ->isValid() || !efGroup) {
- ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__,
- statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0,
- outputQ ? outputQ->isValid() : 0, efGroup.get());
+ !outputQ->isValid()) {
+ ALOGE("%s invalid FMQ [Status %d I %d O %d]", __func__, statusQ ? statusQ->isValid() : 0,
+ inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0);
return INVALID_OPERATION;
}
@@ -225,8 +237,8 @@
return INVALID_OPERATION;
}
- ALOGD("%s %s consumed %zu produced %zu", __func__,
- mConversion->getDescriptor().common.name.c_str(), floatsToWrite, floatsToRead);
+ ALOGD("%s %s consumed %zu produced %zu", __func__, effectName.c_str(), floatsToWrite,
+ floatsToRead);
return OK;
}
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index aee42a9..d73a36c 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -106,8 +106,8 @@
ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common,
const std::optional<Parameter::Specific>& specific,
IEffect::OpenEffectReturn* ret __unused) {
- ndk::ScopedAStatus status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
- EX_ILLEGAL_ARGUMENT, "nullEffectHandle");
+ ndk::ScopedAStatus status =
+ ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "nullEffectHandle");
for (auto& sub : mSubEffects) {
IEffect::OpenEffectReturn openReturn;
if (!sub.handle || !(status = sub.handle->open(common, specific, &openReturn)).isOk()) {
@@ -130,6 +130,31 @@
return status;
}
+ndk::ScopedAStatus EffectProxy::reopen(OpenEffectReturn* ret __unused) {
+ ndk::ScopedAStatus status =
+ ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "nullEffectHandle");
+ for (auto& sub : mSubEffects) {
+ IEffect::OpenEffectReturn openReturn;
+ if (!sub.handle || !(status = sub.handle->reopen(&openReturn)).isOk()) {
+ ALOGE("%s: failed to open %p UUID %s", __func__, sub.handle.get(),
+ ::android::audio::utils::toString(sub.descriptor.common.id.uuid).c_str());
+ break;
+ }
+ sub.effectMq.statusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
+ sub.effectMq.inputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
+ sub.effectMq.outputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ);
+ }
+
+ // close all opened effects if failure
+ if (!status.isOk()) {
+ ALOGE("%s: closing all sub-effects with error %s", __func__,
+ status.getDescription().c_str());
+ close();
+ }
+
+ return status;
+}
+
ndk::ScopedAStatus EffectProxy::close() {
return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
return effect->close();
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
index 0d62642..9b9e8f1 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -62,6 +62,8 @@
specific,
::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn* ret) override;
ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus reopen(
+ ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn* ret) override;
ndk::ScopedAStatus getDescriptor(
::aidl::android::hardware::audio::effect::Descriptor* desc) override;
ndk::ScopedAStatus command(::aidl::android::hardware::audio::effect::CommandId id) override;
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.cpp b/media/libaudiohal/impl/Hal2AidlMapper.cpp
index 63ace8c..2b7f298 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.cpp
+++ b/media/libaudiohal/impl/Hal2AidlMapper.cpp
@@ -238,6 +238,29 @@
return OK;
}
+status_t Hal2AidlMapper::createOrUpdatePortConfigRetry(
+ const AudioPortConfig& requestedPortConfig, AudioPortConfig* result, bool* created) {
+ AudioPortConfig suggestedOrAppliedPortConfig;
+ RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig,
+ &suggestedOrAppliedPortConfig, created));
+ if (suggestedOrAppliedPortConfig.id == 0) {
+ // Try again with the suggested config
+ suggestedOrAppliedPortConfig.id = requestedPortConfig.id;
+ AudioPortConfig appliedPortConfig;
+ RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(suggestedOrAppliedPortConfig,
+ &appliedPortConfig, created));
+ if (appliedPortConfig.id == 0) {
+ ALOGE("%s: module %s did not apply suggested config %s", __func__,
+ mInstance.c_str(), suggestedOrAppliedPortConfig.toString().c_str());
+ return NO_INIT;
+ }
+ *result = appliedPortConfig;
+ } else {
+ *result = suggestedOrAppliedPortConfig;
+ }
+ return OK;
+}
+
void Hal2AidlMapper::eraseConnectedPort(int32_t portId) {
mPorts.erase(portId);
mConnectedPorts.erase(portId);
@@ -247,6 +270,7 @@
ALOGD("%s: disconnected port replacement: %s", __func__, port.toString().c_str());
mDisconnectedPortReplacement = std::pair<int32_t, AudioPort>();
}
+ updateDynamicMixPorts();
}
status_t Hal2AidlMapper::findOrCreatePatch(
@@ -294,27 +318,19 @@
if (config != nullptr) {
setPortConfigFromConfig(&requestedPortConfig, *config);
}
- AudioPortConfig suggestedOrAppliedPortConfig;
- RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig,
- &suggestedOrAppliedPortConfig, created));
- if (suggestedOrAppliedPortConfig.id == 0) {
- // Try again with the suggested config
- suggestedOrAppliedPortConfig.id = requestedPortConfig.id;
- AudioPortConfig appliedPortConfig;
- RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(suggestedOrAppliedPortConfig,
- &appliedPortConfig, created));
- if (appliedPortConfig.id == 0) {
- ALOGE("%s: module %s did not apply suggested config %s", __func__,
- mInstance.c_str(), suggestedOrAppliedPortConfig.toString().c_str());
- return NO_INIT;
- }
- *portConfig = appliedPortConfig;
- } else {
- *portConfig = suggestedOrAppliedPortConfig;
- }
+ return createOrUpdatePortConfigRetry(requestedPortConfig, portConfig, created);
} else {
- *portConfig = portConfigIt->second;
- *created = false;
+ AudioPortConfig requestedPortConfig = portConfigIt->second;
+ if (config != nullptr) {
+ setPortConfigFromConfig(&requestedPortConfig, *config);
+ }
+
+ if (requestedPortConfig != portConfigIt->second) {
+ return createOrUpdatePortConfigRetry(requestedPortConfig, portConfig, created);
+ } else {
+ *portConfig = portConfigIt->second;
+ *created = false;
+ }
}
return OK;
}
@@ -370,12 +386,12 @@
return BAD_VALUE;
} else {
AudioPortConfig requestedPortConfig = portConfigIt->second;
- if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
- AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
- if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
- source != AudioSource::SYS_RESERVED_INVALID) {
- mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
- }
+ setPortConfigFromConfig(&requestedPortConfig, config);
+
+ AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
+ if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
+ source != AudioSource::SYS_RESERVED_INVALID) {
+ mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
}
if (requestedPortConfig != portConfigIt->second) {
@@ -410,9 +426,19 @@
requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
portConfig, created);
} else if (requestedPortConfig.ext.getTag() == Tag::device) {
- return findOrCreateDevicePortConfig(
- requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
- portConfig, created);
+ if (const auto& p = requestedPortConfig;
+ p.sampleRate.has_value() && p.channelMask.has_value() &&
+ p.format.has_value()) {
+ AudioConfig config;
+ setConfigFromPortConfig(&config, requestedPortConfig);
+ return findOrCreateDevicePortConfig(
+ requestedPortConfig.ext.get<Tag::device>().device, &config,
+ portConfig, created);
+ } else {
+ return findOrCreateDevicePortConfig(
+ requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
+ portConfig, created);
+ }
}
ALOGW("%s: unsupported audio port config: %s",
__func__, requestedPortConfig.toString().c_str());
@@ -704,7 +730,7 @@
this, __func__, ioHandle, device.toString().c_str(),
flags.toString().c_str(), toString(source).c_str(),
config->toString().c_str(), mixPortConfig->toString().c_str());
- resetUnusedPatchesAndPortConfigs();
+ resetUnusedPatchesPortConfigsAndPorts();
const AudioConfig initialConfig = *config;
// Find / create AudioPortConfigs for the device port and the mix port,
// then find / create a patch between them, and open a stream on the mix port.
@@ -832,7 +858,7 @@
result = BAD_VALUE;
}
}
- resetUnusedPortConfigs();
+ resetUnusedPortConfigsAndPorts();
return result;
}
@@ -849,7 +875,7 @@
ALOGE("%s: port config id %d not found", __func__, portConfigId);
}
-void Hal2AidlMapper::resetUnusedPatchesAndPortConfigs() {
+void Hal2AidlMapper::resetUnusedPatchesPortConfigsAndPorts() {
// Since patches can be created independently of streams via 'createOrUpdatePatch',
// here we only clean up patches for released streams.
std::set<int32_t> patchesToRelease;
@@ -863,11 +889,11 @@
it = mStreams.erase(it);
}
}
- // 'releaseAudioPatches' also resets unused port configs.
+ // 'releaseAudioPatches' also resets unused port configs and ports.
releaseAudioPatches(patchesToRelease);
}
-void Hal2AidlMapper::resetUnusedPortConfigs() {
+void Hal2AidlMapper::resetUnusedPortConfigsAndPorts() {
// The assumption is that port configs are used to create patches
// (or to open streams, but that involves creation of patches, too). Thus,
// orphaned port configs can and should be reset.
@@ -908,6 +934,7 @@
}
status_t Hal2AidlMapper::setDevicePortConnectedState(const AudioPort& devicePort, bool connected) {
+ resetUnusedPatchesPortConfigsAndPorts();
if (connected) {
AudioDevice matchDevice = devicePort.ext.get<AudioPortExt::device>().device;
std::optional<AudioPort> templatePort;
@@ -942,7 +969,6 @@
}
templatePort = portsIt->second;
}
- resetUnusedPatchesAndPortConfigs();
// Use the ID of the "template" port, use all the information from the provided port.
AudioPort connectedPort = devicePort;
@@ -969,7 +995,6 @@
ALOGD("%s: device port for device %s found in the module %s",
__func__, matchDevice.toString().c_str(), mInstance.c_str());
}
- resetUnusedPatchesAndPortConfigs();
// Disconnection of remote submix out with address "0" is a special case. We need to replace
// the connected port entry with the "augmented template".
@@ -1002,6 +1027,9 @@
if (status == OK) {
auto portIt = mPorts.find(portId);
if (portIt != mPorts.end()) {
+ if (port->ext.getTag() == AudioPortExt::Tag::mix && portIt->second != *port) {
+ mDynamicMixPortIds.insert(portId);
+ }
portIt->second = *port;
} else {
ALOGW("%s, port(%d) returned successfully from the HAL but not it is not cached",
@@ -1050,4 +1078,15 @@
return OK;
}
+void Hal2AidlMapper::updateDynamicMixPorts() {
+ for (int32_t portId : mDynamicMixPortIds) {
+ if (auto it = mPorts.find(portId); it != mPorts.end()) {
+ updateAudioPort(portId, &it->second);
+ } else {
+ // This must not happen
+ ALOGE("%s, cannot find port for id=%d", __func__, portId);
+ }
+ }
+}
+
} // namespace android
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.h b/media/libaudiohal/impl/Hal2AidlMapper.h
index 21cfd5a..f937173 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.h
+++ b/media/libaudiohal/impl/Hal2AidlMapper.h
@@ -91,7 +91,7 @@
::aidl::android::media::audio::common::AudioPortConfig* portConfig,
Cleanups* cleanups = nullptr);
status_t releaseAudioPatch(int32_t patchId);
- void resetUnusedPatchesAndPortConfigs();
+ void resetUnusedPatchesPortConfigsAndPorts();
status_t setDevicePortConnectedState(
const ::aidl::android::media::audio::common::AudioPort& devicePort, bool connected);
@@ -126,6 +126,9 @@
status_t createOrUpdatePortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
::aidl::android::media::audio::common::AudioPortConfig* result, bool *created);
+ status_t createOrUpdatePortConfigRetry(
+ const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+ ::aidl::android::media::audio::common::AudioPortConfig* result, bool *created);
void eraseConnectedPort(int32_t portId);
status_t findOrCreatePatch(
const std::set<int32_t>& sourcePortConfigIds,
@@ -181,10 +184,11 @@
status_t releaseAudioPatches(const std::set<int32_t>& patchIds);
void resetPatch(int32_t patchId) { (void)releaseAudioPatch(patchId); }
void resetPortConfig(int32_t portConfigId);
- void resetUnusedPortConfigs();
+ void resetUnusedPortConfigsAndPorts();
status_t updateAudioPort(
int32_t portId, ::aidl::android::media::audio::common::AudioPort* port);
status_t updateRoutes();
+ void updateDynamicMixPorts();
Ports mPorts;
// Remote submix "template" ports (no address specified, no profiles).
@@ -202,6 +206,7 @@
ConnectedPorts mConnectedPorts;
std::pair<int32_t, ::aidl::android::media::audio::common::AudioPort>
mDisconnectedPortReplacement;
+ std::set<int32_t> mDynamicMixPortIds;
};
} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 378d919..5f525d7 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -234,7 +234,9 @@
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
- return mStream->dump(fd, Args(args).args(), args.size());
+ status_t status = mStream->dump(fd, Args(args).args(), args.size());
+ mStreamPowerLog.dump(fd);
+ return status;
}
status_t StreamHalAidl::start() {
@@ -808,6 +810,7 @@
mOffloadMetadata.channelMask = VALUE_OR_RETURN_STATUS(
::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
channel_mask, false /*isInput*/));
+ return OK;
}
return BAD_VALUE;
}))) {
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index 37633ae..b56872c 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -69,6 +69,6 @@
],
relative_install_path: "soundfx",
visibility: [
- "//hardware/interfaces/audio/aidl/default",
+ "//hardware/interfaces/audio/aidl/default:__subpackages__",
],
}
diff --git a/media/libeffects/downmix/aidl/DownmixContext.cpp b/media/libeffects/downmix/aidl/DownmixContext.cpp
index 13e0e5a..5fb44b5 100644
--- a/media/libeffects/downmix/aidl/DownmixContext.cpp
+++ b/media/libeffects/downmix/aidl/DownmixContext.cpp
@@ -111,7 +111,6 @@
}
IEffect::Status DownmixContext::downmixProcess(float* in, float* out, int samples) {
- LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
if (in == nullptr || out == nullptr ||
@@ -132,7 +131,6 @@
bool accumulate = false;
int frames = samples * sizeof(float) / getInputFrameSize();
if (mType == Downmix::Type::STRIP) {
- int inputChannelCount = getChannelCount(mChMask);
while (frames) {
if (accumulate) {
out[0] = std::clamp(out[0] + in[0], -1.f, 1.f);
@@ -141,7 +139,7 @@
out[0] = in[0];
out[1] = in[1];
}
- in += inputChannelCount;
+ in += mInputChannelCount;
out += 2;
frames--;
}
@@ -153,8 +151,11 @@
return status;
}
}
- LOG(DEBUG) << __func__ << " done processing";
- return {STATUS_OK, samples, samples};
+ int producedSamples = (samples / mInputChannelCount) << 1;
+ LOG(DEBUG) << __func__ << " done processing " << samples << " samples, generated "
+ << producedSamples << " frameSize: " << getInputFrameSize() << " - "
+ << getOutputFrameSize();
+ return {STATUS_OK, samples, producedSamples};
}
void DownmixContext::init_params(const Parameter::Common& common) {
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.cpp b/media/libeffects/downmix/aidl/EffectDownmix.cpp
index 702a6f0..c82c23b 100644
--- a/media/libeffects/downmix/aidl/EffectDownmix.cpp
+++ b/media/libeffects/downmix/aidl/EffectDownmix.cpp
@@ -71,42 +71,6 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus DownmixImpl::setParameterCommon(const Parameter& param) {
- RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-
- auto tag = param.getTag();
- switch (tag) {
- case Parameter::common:
- RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
- EX_ILLEGAL_ARGUMENT, "setCommFailed");
- break;
- case Parameter::deviceDescription:
- RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
- RetCode::SUCCESS,
- EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
- break;
- case Parameter::mode:
- RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
- EX_ILLEGAL_ARGUMENT, "setModeFailed");
- break;
- case Parameter::source:
- RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
- EX_ILLEGAL_ARGUMENT, "setSourceFailed");
- break;
- case Parameter::volumeStereo:
- RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
- RetCode::SUCCESS,
- EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
- break;
- default: {
- LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
- "commonParamNotSupported");
- }
- }
- return ndk::ScopedAStatus::ok();
-}
-
ndk::ScopedAStatus DownmixImpl::commandImpl(CommandId command) {
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
switch (command) {
@@ -206,6 +170,43 @@
return RetCode::SUCCESS;
}
+void DownmixImpl::process() {
+ /**
+ * wait for the EventFlag without lock, it's ok because the mEfGroup pointer will not change
+ * in the life cycle of workerThread (threadLoop).
+ */
+ uint32_t efState = 0;
+ if (!mEventFlag || ::android::OK != mEventFlag->wait(kEventFlagNotEmpty, &efState)) {
+ LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag invalid";
+ }
+
+ {
+ std::lock_guard lg(mImplMutex);
+ RETURN_VALUE_IF(!mImplContext, void(), "nullContext");
+ auto statusMQ = mImplContext->getStatusFmq();
+ auto inputMQ = mImplContext->getInputDataFmq();
+ auto outputMQ = mImplContext->getOutputDataFmq();
+ auto buffer = mImplContext->getWorkBuffer();
+ if (!inputMQ || !outputMQ) {
+ return;
+ }
+
+ const auto availableToRead = inputMQ->availableToRead();
+ const auto availableToWrite = outputMQ->availableToWrite() *
+ mImplContext->getInputFrameSize() /
+ mImplContext->getOutputFrameSize();
+ auto processSamples = std::min(availableToRead, availableToWrite);
+ if (processSamples) {
+ inputMQ->read(buffer, processSamples);
+ IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
+ outputMQ->write(buffer, status.fmqProduced);
+ statusMQ->writeBlocking(&status, 1);
+ LOG(VERBOSE) << getEffectName() << __func__ << ": done processing, effect consumed "
+ << status.fmqConsumed << " produced " << status.fmqProduced;
+ }
+ }
+}
+
// Processing method running in EffectWorker thread.
IEffect::Status DownmixImpl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
if (!mContext) {
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.h b/media/libeffects/downmix/aidl/EffectDownmix.h
index 812d26b..54557dc 100644
--- a/media/libeffects/downmix/aidl/EffectDownmix.h
+++ b/media/libeffects/downmix/aidl/EffectDownmix.h
@@ -34,21 +34,26 @@
LOG(DEBUG) << __func__;
}
- ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
- ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
- ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
- ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
- Parameter::Specific* specific) override;
- IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
- std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
- RetCode releaseContext() override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process)
+ REQUIRES(mImplMutex) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+ REQUIRES(mImplMutex) override;
+ RetCode releaseContext() REQUIRES(mImplMutex) override;
- std::shared_ptr<EffectContext> getContext() override { return mContext; }
std::string getEffectName() override { return kEffectName; }
+ // downmix override the process because of different input/output sample size requirement
+ void process() override;
+
private:
- std::shared_ptr<DownmixContext> mContext;
- ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific);
+ std::shared_ptr<DownmixContext> mContext GUARDED_BY(mImplMutex);
+ ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/Android.bp b/media/libeffects/dynamicsproc/Android.bp
index 9e154cf..e93a4e6 100644
--- a/media/libeffects/dynamicsproc/Android.bp
+++ b/media/libeffects/dynamicsproc/Android.bp
@@ -95,6 +95,6 @@
],
visibility: [
- "//hardware/interfaces/audio/aidl/default",
+ "//hardware/interfaces/audio/aidl/default:__subpackages__",
],
}
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index 85ea53a..1fedea4 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -211,11 +211,12 @@
RETURN_IF(common.input.base.format.pcm != common.output.base.format.pcm ||
common.input.base.format.pcm != PcmType::FLOAT_32_BIT,
EX_ILLEGAL_ARGUMENT, "dataMustBe32BitsFloat");
+ std::lock_guard lg(mImplMutex);
RETURN_OK_IF(mState != State::INIT);
- auto context = createContext(common);
- RETURN_IF(!context, EX_NULL_POINTER, "createContextFailed");
+ mImplContext = createContext(common);
+ RETURN_IF(!mContext || !mImplContext, EX_NULL_POINTER, "createContextFailed");
+ mEventFlag = mImplContext->getStatusEventFlag();
- RETURN_IF_ASTATUS_NOT_OK(setParameterCommon(common), "setCommParamErr");
if (specific.has_value()) {
RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr");
} else {
@@ -227,8 +228,8 @@
}
mState = State::IDLE;
- context->dupeFmq(ret);
- RETURN_IF(createThread(context, getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
+ mContext->dupeFmq(ret);
+ RETURN_IF(createThread(getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
"FailedToCreateWorker");
return ndk::ScopedAStatus::ok();
}
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
index 1e1e72e..4897888 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -39,22 +39,25 @@
ndk::ScopedAStatus open(const Parameter::Common& common,
const std::optional<Parameter::Specific>& specific,
OpenEffectReturn* ret) override;
- ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
- ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
- ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
- Parameter::Specific* specific) override;
- IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
- std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
- RetCode releaseContext() override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process)
+ REQUIRES(mImplMutex) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+ REQUIRES(mImplMutex) override;
+ RetCode releaseContext() REQUIRES(mImplMutex) override;
- std::shared_ptr<EffectContext> getContext() override { return mContext; }
std::string getEffectName() override { return kEffectName; }
private:
- std::shared_ptr<DynamicsProcessingContext> mContext;
+ std::shared_ptr<DynamicsProcessingContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
- Parameter::Specific* specific);
+ Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
bool isParamInRange(const Parameter::Specific& specific);
};
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index f3a3860..042b063 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -63,6 +63,9 @@
}
RetCode DynamicsProcessingContext::setCommon(const Parameter::Common& common) {
+ if(auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
+ return ret;
+ }
mCommon = common;
init();
LOG(INFO) << __func__ << common.toString();
@@ -312,7 +315,9 @@
void DynamicsProcessingContext::init() {
std::lock_guard lg(mMutex);
- mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
+ if (mState == DYNAMICS_PROCESSING_STATE_UNINITIALIZED) {
+ mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
+ }
mChannelCount = static_cast<int>(::aidl::android::hardware::audio::common::getChannelCount(
mCommon.input.base.channelMask));
}
diff --git a/media/libeffects/hapticgenerator/Android.bp b/media/libeffects/hapticgenerator/Android.bp
index cc19a80..7d96b53 100644
--- a/media/libeffects/hapticgenerator/Android.bp
+++ b/media/libeffects/hapticgenerator/Android.bp
@@ -84,6 +84,6 @@
],
visibility: [
- "//hardware/interfaces/audio/aidl/default",
+ "//hardware/interfaces/audio/aidl/default:__subpackages__",
],
}
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
index fe9616a..53dcd49 100644
--- a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
@@ -33,16 +33,18 @@
LOG(DEBUG) << __func__;
}
- ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
- ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
- ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
- Parameter::Specific* specific) override;
- IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
- std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
- RetCode releaseContext() override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process)
+ REQUIRES(mImplMutex) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+ REQUIRES(mImplMutex) override;
+ RetCode releaseContext() REQUIRES(mImplMutex) override;
- std::shared_ptr<EffectContext> getContext() override { return mContext; }
std::string getEffectName() override { return kEffectName; }
private:
diff --git a/media/libeffects/loudness/Android.bp b/media/libeffects/loudness/Android.bp
index 05bbec3..46e4669 100644
--- a/media/libeffects/loudness/Android.bp
+++ b/media/libeffects/loudness/Android.bp
@@ -69,6 +69,6 @@
],
relative_install_path: "soundfx",
visibility: [
- "//hardware/interfaces/audio/aidl/default",
+ "//hardware/interfaces/audio/aidl/default:__subpackages__",
],
}
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
index 5b9e924..e2e716c 100644
--- a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
@@ -33,22 +33,25 @@
LOG(DEBUG) << __func__;
}
- ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
- ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
- ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
- Parameter::Specific* specific) override;
- IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
- std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
- RetCode releaseContext() override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process)
+ REQUIRES(mImplMutex) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+ REQUIRES(mImplMutex) override;
+ RetCode releaseContext() REQUIRES(mImplMutex) override;
- std::shared_ptr<EffectContext> getContext() override { return mContext; }
std::string getEffectName() override { return kEffectName; }
private:
- std::shared_ptr<LoudnessEnhancerContext> mContext;
+ std::shared_ptr<LoudnessEnhancerContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
- Parameter::Specific* specific);
+ Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index 71bb2ef..bb7e4c6 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -20,6 +20,7 @@
#define LOG_TAG "BundleContext"
#include <android-base/logging.h>
#include <audio_utils/power.h>
+#include <media/AidlConversionCppNdk.h>
#include <Utils.h>
#include "BundleContext.h"
@@ -36,9 +37,10 @@
const lvm::BundleEffectType& type)
: EffectContext(statusDepth, common), mType(type) {
LOG(DEBUG) << __func__ << type;
- int channelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+
+ int inputChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
common.input.base.channelMask);
- mSamplesPerSecond = common.input.base.sampleRate * channelCount;
+ mSamplesPerSecond = common.input.base.sampleRate * inputChannelCount;
}
BundleContext::~BundleContext() {
@@ -50,9 +52,15 @@
std::lock_guard lg(mMutex);
// init with pre-defined preset NORMAL
for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- mBandGainMdB[i] = lvm::kSoftPresets[0 /* normal */][i] * 100;
+ mBandGainmB[i] = lvm::kSoftPresets[0 /* normal */][i] * 100;
}
+ // Initialise control params
+ LVM_ControlParams_t controlParams;
+ RetCode retStatus = initControlParameter(controlParams);
+ RETURN_VALUE_IF(retStatus != RetCode::SUCCESS, RetCode::ERROR_ILLEGAL_PARAMETER,
+ " UnsupportedParams");
+
// allocate lvm instance
LVM_ReturnStatus_en status;
LVM_InstParams_t params = {.BufferMode = LVM_UNMANAGED_BUFFERS,
@@ -63,8 +71,6 @@
GOTO_IF_LVM_ERROR(status, deinit, "LVM_GetInstanceHandleFailed");
// set control
- LVM_ControlParams_t controlParams;
- initControlParameter(controlParams);
status = LVM_SetControlParameters(mInstance, &controlParams);
GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetControlParametersFailed");
@@ -227,8 +233,8 @@
bool viEnabled = params.VirtualizerOperatingMode == LVM_MODE_ON;
if (eqEnabled) {
- for (size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- float bandFactor = mBandGainMdB[i] / 1500.0;
+ for (unsigned int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ float bandFactor = mBandGainmB[i] / 1500.0;
float bandCoefficient = lvm::kBandEnergyCoefficient[i];
float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
if (bandEnergy > 0) energyContribution += bandEnergy;
@@ -236,9 +242,9 @@
// cross EQ coefficients
float bandFactorSum = 0;
- for (size_t i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
- float bandFactor1 = mBandGainMdB[i] / 1500.0;
- float bandFactor2 = mBandGainMdB[i + 1] / 1500.0;
+ for (unsigned int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
+ float bandFactor1 = mBandGainmB[i] / 1500.0;
+ float bandFactor2 = mBandGainmB[i + 1] / 1500.0;
if (bandFactor1 > 0 && bandFactor2 > 0) {
float crossEnergy =
@@ -259,8 +265,8 @@
energyContribution += boostFactor * boostCoefficient * boostCoefficient;
if (eqEnabled) {
- for (size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- float bandFactor = mBandGainMdB[i] / 1500.0;
+ for (unsigned int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ float bandFactor = mBandGainmB[i] / 1500.0;
float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
if (bandEnergy > 0) energyBassBoost += bandEnergy;
@@ -312,7 +318,9 @@
device != AudioDeviceDescription{AudioDeviceType::OUT_CARKIT,
AudioDeviceDescription::CONNECTION_BT_SCO} &&
device != AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER,
- AudioDeviceDescription::CONNECTION_BT_A2DP}) {
+ AudioDeviceDescription::CONNECTION_BT_A2DP} &&
+ device != AudioDeviceDescription{AudioDeviceType::OUT_SUBMIX,
+ AudioDeviceDescription::CONNECTION_VIRTUAL}) {
return false;
}
}
@@ -329,7 +337,9 @@
device != AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
AudioDeviceDescription::CONNECTION_BT_A2DP} &&
device != AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_USB}) {
+ AudioDeviceDescription::CONNECTION_USB} &&
+ device != AudioDeviceDescription{AudioDeviceType::OUT_SUBMIX,
+ AudioDeviceDescription::CONNECTION_VIRTUAL}) {
return false;
}
}
@@ -469,6 +479,7 @@
RetCode BundleContext::setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
RETURN_VALUE_IF(bandLevels.size() > lvm::MAX_NUM_BANDS || bandLevels.empty(),
RetCode::ERROR_ILLEGAL_PARAMETER, "sizeExceedMax");
+
RetCode ret = updateControlParameter(bandLevels);
if (RetCode::SUCCESS == ret) {
mCurPresetIdx = lvm::PRESET_CUSTOM;
@@ -483,15 +494,13 @@
std::vector<Equalizer::BandLevel> bandLevels;
bandLevels.reserve(lvm::MAX_NUM_BANDS);
for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- bandLevels.emplace_back(
- Equalizer::BandLevel{static_cast<int32_t>(i), mBandGainMdB[i]});
+ bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i), mBandGainmB[i]});
}
return bandLevels;
}
std::vector<int32_t> BundleContext::getEqualizerCenterFreqs() {
std::vector<int32_t> freqs;
-
LVM_ControlParams_t params;
{
std::lock_guard lg(mMutex);
@@ -518,7 +527,7 @@
RETURN_VALUE_IF(!isBandLevelIndexInRange(bandLevels), RetCode::ERROR_ILLEGAL_PARAMETER,
"indexOutOfRange");
- std::array<int, lvm::MAX_NUM_BANDS> tempLevel(mBandGainMdB);
+ std::array<int, lvm::MAX_NUM_BANDS> tempLevel(mBandGainmB);
for (const auto& it : bandLevels) {
tempLevel[it.index] = it.levelMb;
}
@@ -539,8 +548,8 @@
RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
}
- mBandGainMdB = tempLevel;
- LOG(DEBUG) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGainMdB)
+ mBandGainmB = tempLevel;
+ LOG(DEBUG) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGainmB)
<< "mdB";
return RetCode::SUCCESS;
@@ -618,11 +627,30 @@
return RetCode::SUCCESS;
}
-void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
+RetCode BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
+ int outputChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+ mCommon.output.base.channelMask);
+ auto outputChannelMaskConv = aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ mCommon.output.base.channelMask, /*isInput*/ false);
+ RETURN_VALUE_IF(!outputChannelMaskConv.ok(), RetCode::ERROR_ILLEGAL_PARAMETER,
+ " outputChannelMaskNotValid");
+
+ params.NrChannels = outputChannelCount;
+ params.ChMask = outputChannelMaskConv.value();
+ params.SampleRate = lvmFsForSampleRate(mCommon.input.base.sampleRate);
+
+ int inputChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+ mCommon.input.base.channelMask);
+ if (inputChannelCount == 1) {
+ params.SourceFormat = LVM_MONO;
+ } else if (inputChannelCount == 2) {
+ params.SourceFormat = LVM_STEREO;
+ } else if (inputChannelCount > 2 && inputChannelCount <= LVM_MAX_CHANNELS) {
+ params.SourceFormat = LVM_MULTICHANNEL;
+ }
+
/* General parameters */
params.OperatingMode = LVM_MODE_ON;
- params.SampleRate = LVM_FS_44100;
- params.SourceFormat = LVM_STEREO;
params.SpeakerType = LVM_HEADPHONES;
/* Concert Sound parameters */
@@ -657,13 +685,7 @@
params.PSA_Enable = LVM_PSA_OFF;
params.PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
- /* TE Control parameters */
- params.TE_OperatingMode = LVM_TE_OFF;
- params.TE_EffectLevel = 0;
-
- params.NrChannels = audio_channel_count_from_out_mask(AUDIO_CHANNEL_OUT_STEREO);
- params.ChMask = AUDIO_CHANNEL_OUT_STEREO;
- params.SourceFormat = LVM_STEREO;
+ return RetCode::SUCCESS;
}
void BundleContext::initHeadroomParameter(LVM_HeadroomParams_t& params) const {
@@ -832,13 +854,13 @@
LOG(DEBUG) << "Effect_process() processing last frame";
}
mNumberEffectsCalled = 0;
- LVM_UINT16 frames = samples * sizeof(float) / frameSize;
float* outTmp = (accumulate ? getWorkBuffer() : out);
/* Process the samples */
LVM_ReturnStatus_en lvmStatus;
{
std::lock_guard lg(mMutex);
- lvmStatus = LVM_Process(mInstance, in, outTmp, frames, 0);
+
+ lvmStatus = LVM_Process(mInstance, in, outTmp, inputFrameCount, 0);
if (lvmStatus != LVM_SUCCESS) {
LOG(ERROR) << __func__ << lvmStatus;
return {EX_UNSUPPORTED_OPERATION, 0, 0};
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index 779d53a..809f402 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -41,15 +41,6 @@
RetCode disable();
RetCode disableOperatingMode();
- void setSampleRate(const int sampleRate) { mSampleRate = sampleRate; }
- int getSampleRate() const { return mSampleRate; }
-
- void setChannelMask(const aidl::android::media::audio::common::AudioChannelLayout& chMask) {
- mChMask = chMask;
- }
- aidl::android::media::audio::common::AudioChannelLayout getChannelMask() const {
- return mChMask;
- }
bool isDeviceSupportedBassBoost(
const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>&
devices);
@@ -105,9 +96,7 @@
LVM_Handle_t mInstance GUARDED_BY(mMutex);
aidl::android::media::audio::common::AudioDeviceDescription mVirtualizerForcedDevice;
- aidl::android::media::audio::common::AudioChannelLayout mChMask;
- int mSampleRate = LVM_FS_44100;
int mSamplesPerSecond = 0;
int mSamplesToExitCountEq = 0;
int mSamplesToExitCountBb = 0;
@@ -129,7 +118,7 @@
int mBassStrengthSaved = 0;
// Equalizer
int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */
- std::array<int, lvm::MAX_NUM_BANDS> mBandGainMdB; /* band gain in millibels */
+ std::array<int, lvm::MAX_NUM_BANDS> mBandGainmB; /* band gain in millibels */
// Virtualizer
int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
bool mVirtualizerTempDisabled = false;
@@ -139,7 +128,7 @@
float mVolume = 0;
bool mMuteEnabled = false; /* Must store as mute = -96dB level */
- void initControlParameter(LVM_ControlParams_t& params) const;
+ RetCode initControlParameter(LVM_ControlParams_t& params) const;
void initHeadroomParameter(LVM_HeadroomParams_t& params) const;
RetCode limitLevel();
static float VolToDb(float vol);
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index 3148d36..257e972 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -425,10 +425,6 @@
return mContext;
}
-std::shared_ptr<EffectContext> EffectBundleAidl::getContext() {
- return mContext;
-}
-
RetCode EffectBundleAidl::releaseContext() {
if (mContext) {
GlobalSession::getGlobalSession().releaseSession(mType, mContext->getSessionId());
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
index ec1abe8..429e941 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -36,41 +36,47 @@
~EffectBundleAidl() override;
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
- ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
- ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
- ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
- Parameter::Specific* specific) override;
+ ndk::ScopedAStatus setParameterCommon(const Parameter& param) REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex) override;
- std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
- std::shared_ptr<EffectContext> getContext() override;
- RetCode releaseContext() override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+ REQUIRES(mImplMutex) override;
+ RetCode releaseContext() REQUIRES(mImplMutex) override;
- IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples)
+ REQUIRES(mImplMutex) override;
- ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
std::string getEffectName() override { return *mEffectName; }
private:
- std::shared_ptr<BundleContext> mContext;
+ std::shared_ptr<BundleContext> mContext GUARDED_BY(mImplMutex);
const Descriptor* mDescriptor;
const std::string* mEffectName;
lvm::BundleEffectType mType = lvm::BundleEffectType::EQUALIZER;
IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
- ndk::ScopedAStatus setParameterBassBoost(const Parameter::Specific& specific);
- ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Id& id,
- Parameter::Specific* specific);
+ ndk::ScopedAStatus setParameterBassBoost(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
+ ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
- ndk::ScopedAStatus setParameterEqualizer(const Parameter::Specific& specific);
- ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Id& id,
- Parameter::Specific* specific);
- ndk::ScopedAStatus setParameterVolume(const Parameter::Specific& specific);
- ndk::ScopedAStatus getParameterVolume(const Volume::Id& id, Parameter::Specific* specific);
- ndk::ScopedAStatus setParameterVirtualizer(const Parameter::Specific& specific);
+ ndk::ScopedAStatus setParameterEqualizer(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
+ ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
+ ndk::ScopedAStatus setParameterVolume(const Parameter::Specific& specific) REQUIRES(mImplMutex);
+ ndk::ScopedAStatus getParameterVolume(const Volume::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
+ ndk::ScopedAStatus setParameterVirtualizer(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Id& id,
- Parameter::Specific* specific);
+ Parameter::Specific* specific) REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index 5fb3966..a50ba93 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -118,14 +118,19 @@
"libhardware_headers",
],
shared_libs: [
+ "libaudio_aidl_conversion_common_ndk",
+ "libaudioutils",
+ "libbinder",
"liblog",
+ "libstagefright_foundation",
],
cflags: [
"-Wthread-safety",
+ "-DBACKEND_NDK",
],
relative_install_path: "soundfx",
visibility: [
- "//hardware/interfaces/audio/aidl/default",
+ "//hardware/interfaces/audio/aidl/default:__subpackages__",
],
}
@@ -156,6 +161,6 @@
],
relative_install_path: "soundfx",
visibility: [
- "//hardware/interfaces/audio/aidl/default",
+ "//hardware/interfaces/audio/aidl/default:__subpackages__",
],
}
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
index b49d109..f9afe69 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
@@ -358,10 +358,6 @@
return mContext;
}
-std::shared_ptr<EffectContext> EffectReverb::getContext() {
- return mContext;
-}
-
RetCode EffectReverb::releaseContext() {
if (mContext) {
mContext.reset();
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
index d7d2bbd..e0771a1 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
@@ -30,35 +30,41 @@
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
- ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
- ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
- Parameter::Specific* specific) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex) override;
- std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
- std::shared_ptr<EffectContext> getContext() override;
- RetCode releaseContext() override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+ REQUIRES(mImplMutex) override;
+ RetCode releaseContext() REQUIRES(mImplMutex) override;
- IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples)
+ REQUIRES(mImplMutex) override;
- ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
std::string getEffectName() override { return *mEffectName; }
private:
- std::shared_ptr<ReverbContext> mContext;
+ std::shared_ptr<ReverbContext> mContext GUARDED_BY(mImplMutex);
const Descriptor* mDescriptor;
const std::string* mEffectName;
lvm::ReverbEffectType mType;
IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
- ndk::ScopedAStatus setParameterPresetReverb(const Parameter::Specific& specific);
+ ndk::ScopedAStatus setParameterPresetReverb(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
ndk::ScopedAStatus getParameterPresetReverb(const PresetReverb::Id& id,
- Parameter::Specific* specific);
+ Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
- ndk::ScopedAStatus setParameterEnvironmentalReverb(const Parameter::Specific& specific);
+ ndk::ScopedAStatus setParameterEnvironmentalReverb(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
ndk::ScopedAStatus getParameterEnvironmentalReverb(const EnvironmentalReverb::Id& id,
- Parameter::Specific* specific);
+ Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index 564eb36..994b061 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -89,6 +89,6 @@
],
relative_install_path: "soundfx",
visibility: [
- "//hardware/interfaces/audio/aidl/default",
+ "//hardware/interfaces/audio/aidl/default:__subpackages__",
],
}
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
index e8ae8b3..7552804 100644
--- a/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
@@ -412,10 +412,6 @@
return mContext;
}
-std::shared_ptr<EffectContext> EffectPreProcessing::getContext() {
- return mContext;
-}
-
RetCode EffectPreProcessing::releaseContext() {
if (mContext) {
PreProcessingSession::getPreProcessingSession().releaseSession(mType,
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.h b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
index fad848a..9ce5597 100644
--- a/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
@@ -31,41 +31,51 @@
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
- ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
- ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
- Parameter::Specific* specific) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex) override;
- std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
- std::shared_ptr<EffectContext> getContext() override;
- RetCode releaseContext() override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+ REQUIRES(mImplMutex) override;
+ RetCode releaseContext() REQUIRES(mImplMutex) override;
- IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples)
+ REQUIRES(mImplMutex) override;
- ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
std::string getEffectName() override { return *mEffectName; }
private:
- std::shared_ptr<PreProcessingContext> mContext;
+ std::shared_ptr<PreProcessingContext> mContext GUARDED_BY(mImplMutex);
const Descriptor* mDescriptor;
const std::string* mEffectName;
PreProcessingEffectType mType;
- ndk::ScopedAStatus setParameterAcousticEchoCanceler(const Parameter::Specific& specific);
+ ndk::ScopedAStatus setParameterAcousticEchoCanceler(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
ndk::ScopedAStatus getParameterAcousticEchoCanceler(const AcousticEchoCanceler::Id& id,
- Parameter::Specific* specific);
+ Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
- ndk::ScopedAStatus setParameterAutomaticGainControlV1(const Parameter::Specific& specific);
+ ndk::ScopedAStatus setParameterAutomaticGainControlV1(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
ndk::ScopedAStatus getParameterAutomaticGainControlV1(const AutomaticGainControlV1::Id& id,
- Parameter::Specific* specific);
+ Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
- ndk::ScopedAStatus setParameterAutomaticGainControlV2(const Parameter::Specific& specific);
+ ndk::ScopedAStatus setParameterAutomaticGainControlV2(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
ndk::ScopedAStatus getParameterAutomaticGainControlV2(const AutomaticGainControlV2::Id& id,
- Parameter::Specific* specific);
+ Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
- ndk::ScopedAStatus setParameterNoiseSuppression(const Parameter::Specific& specific);
+ ndk::ScopedAStatus setParameterNoiseSuppression(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex);
ndk::ScopedAStatus getParameterNoiseSuppression(const NoiseSuppression::Id& id,
- Parameter::Specific* specific);
+ Parameter::Specific* specific)
+ REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
index c1e4eda..2c44e5c 100644
--- a/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
@@ -141,6 +141,9 @@
}
RetCode PreProcessingContext::setCommon(const Parameter::Common& common) {
+ if(auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
+ return ret;
+ }
mCommon = common;
updateConfigs(common);
return RetCode::SUCCESS;
diff --git a/media/libeffects/visualizer/Android.bp b/media/libeffects/visualizer/Android.bp
index a8b665b..66ceadf 100644
--- a/media/libeffects/visualizer/Android.bp
+++ b/media/libeffects/visualizer/Android.bp
@@ -70,6 +70,6 @@
],
relative_install_path: "soundfx",
visibility: [
- "//hardware/interfaces/audio/aidl/default",
+ "//hardware/interfaces/audio/aidl/default:__subpackages__",
],
}
diff --git a/media/libeffects/visualizer/aidl/Visualizer.h b/media/libeffects/visualizer/aidl/Visualizer.h
index ec725db..b48c85e 100644
--- a/media/libeffects/visualizer/aidl/Visualizer.h
+++ b/media/libeffects/visualizer/aidl/Visualizer.h
@@ -35,23 +35,25 @@
LOG(DEBUG) << __func__;
}
- ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
- ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
- ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
- Parameter::Specific* specific) override;
- IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
- std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
- RetCode releaseContext() override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+ REQUIRES(mImplMutex) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+ REQUIRES(mImplMutex) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process)
+ REQUIRES(mImplMutex) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+ REQUIRES(mImplMutex) override;
+ RetCode releaseContext() REQUIRES(mImplMutex) override;
- std::shared_ptr<EffectContext> getContext() override { return mContext; }
std::string getEffectName() override { return kEffectName; }
private:
static const std::vector<Range::VisualizerRange> kRanges;
- std::shared_ptr<VisualizerContext> mContext;
+ std::shared_ptr<VisualizerContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
- Parameter::Specific* specific);
+ Parameter::Specific* specific) REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp
index e33cc0f..4436fb9 100644
--- a/media/libmedia/CharacterEncodingDetector.cpp
+++ b/media/libmedia/CharacterEncodingDetector.cpp
@@ -198,7 +198,9 @@
ALOGV("@@@ checking %s", name);
const char *s = mValues.getEntry(i);
int32_t inputLength = strlen(s);
- const char *enc;
+ // Use encoding determined from the combination of artist/album/title etc.
+ // as default if there is no better match found.
+ const char *enc = combinedenc;
if (!allprintable && (!strcmp(name, "artist") ||
!strcmp(name, "albumartist") ||
@@ -216,13 +218,12 @@
const UCharsetMatch** ucma = ucsdet_detectAll(csd, &matches, &status);
const UCharsetMatch* bestSingleMatch = getPreferred(s, inputLength,
ucma, matches, &goodmatchSingle, &highestSingle);
- if (goodmatchSingle || highestSingle > highest)
- enc = ucsdet_getName(bestSingleMatch, &status);
- else
- enc = combinedenc;
- } else {
- // use encoding determined from the combination of artist/album/title etc.
- enc = combinedenc;
+ // getPreferred could return a null. Check for null before calling
+ // ucsdet_getName.
+ if (bestSingleMatch != NULL) {
+ if (goodmatchSingle || highestSingle > highest)
+ enc = ucsdet_getName(bestSingleMatch, &status);
+ }
}
} else {
if (isPrintableAscii(s, inputLength)) {
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 0af9d12..712b405 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -137,7 +137,7 @@
cflags: [
"-DDISABLE_AUDIO_SYSTEM_OFFLOAD",
],
- }
+ },
},
}
@@ -273,7 +273,7 @@
"VideoFrameSchedulerBase.cpp",
"VideoFrameScheduler.cpp",
"VideoRenderQualityTracker.cpp",
- ],
+ ],
shared_libs: [
"libstagefright_framecapture_utils",
@@ -330,7 +330,7 @@
"libmedia_ndkformatpriv",
],
- header_libs:[
+ header_libs: [
"libmediadrm_headers",
"libnativeloader-headers",
"libstagefright_xmlparser_headers",
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index f16e635..604dcb0 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -298,6 +298,11 @@
ALOGE("error pushing blank frames: lock failed: %s (%d)", strerror(-err), -err);
break;
}
+ if (img == nullptr) {
+ (void)buf->unlock(); // Since lock() was successful.
+ ALOGE("error pushing blank frames: lock succeeded: buf mapping is nullptr");
+ break;
+ }
*img = 0;
diff --git a/media/libstagefright/colorconversion/fuzzer/Android.bp b/media/libstagefright/colorconversion/fuzzer/Android.bp
index 76b054a..237e715 100644
--- a/media/libstagefright/colorconversion/fuzzer/Android.bp
+++ b/media/libstagefright/colorconversion/fuzzer/Android.bp
@@ -47,9 +47,15 @@
],
fuzz_config: {
cc: [
- "android-media-fuzzing-reports@google.com",
+ "android-fwk-video@google.com",
],
- componentid: 155276,
+ componentid: 42195,
+ hotlists: ["4593311"],
+ description: "The fuzzer targets the APIs of libstagefright_color_conversion",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/libstagefright/data/media_codecs_google_c2_audio.xml b/media/libstagefright/data/media_codecs_google_c2_audio.xml
index 509f7a9..0d9e0ec 100644
--- a/media/libstagefright/data/media_codecs_google_c2_audio.xml
+++ b/media/libstagefright/data/media_codecs_google_c2_audio.xml
@@ -66,7 +66,7 @@
</MediaCodec>
<MediaCodec name="c2.android.raw.decoder" type="audio/raw">
<Alias name="OMX.google.raw.decoder" />
- <Limit name="channel-count" max="8" />
+ <Limit name="channel-count" max="12" />
<Limit name="sample-rate" ranges="8000-192000" />
<Limit name="bitrate" range="1-10000000" />
</MediaCodec>
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index ee41867..24020d1 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -80,7 +80,7 @@
</MediaCodec>
<MediaCodec name="c2.android.raw.decoder" type="audio/raw">
<Alias name="OMX.google.raw.decoder" />
- <Limit name="channel-count" max="8" />
+ <Limit name="channel-count" max="12" />
<Limit name="sample-rate" ranges="8000-192000" />
<Limit name="bitrate" range="1-10000000" />
<Attribute name="software-codec" />
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 3c95c6d..f4c40e1 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -810,6 +810,9 @@
inline constexpr char KEY_MAX_FPS_TO_ENCODER[] = "max-fps-to-encoder";
inline constexpr char KEY_MAX_HEIGHT[] = "max-height";
inline constexpr char KEY_MAX_INPUT_SIZE[] = "max-input-size";
+inline constexpr char KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE[] = "buffer-batch-max-output-size";
+inline constexpr char KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE[] =
+ "buffer-batch-threshold-output-size";
inline constexpr char KEY_MAX_OUTPUT_CHANNEL_COUNT[] = "max-output-channel-count";
inline constexpr char KEY_MAX_PTS_GAP_TO_ENCODER[] = "max-pts-gap-to-encoder";
inline constexpr char KEY_MAX_WIDTH[] = "max-width";
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 54c5697..79ab009 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -184,6 +184,9 @@
cc_defaults {
name: "libstagefright_softomx-defaults",
+ // TODO (b/316432618) Software OMX codecs are no longer used, disable building them till
+ // this code is removed completely.
+ enabled: false,
vendor_available: true,
cflags: [
diff --git a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
index 65d537b..f95fc4d 100644
--- a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
+++ b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
@@ -148,6 +148,11 @@
return C2_TRANSACTION_FAILED;
}
}
+ status = static_cast<c2_status_t>(configResult.status.status);
+ if (status != C2_BAD_INDEX) {
+ LOG(DEBUG) << "config -- call failed: "
+ << status << ".";
+ }
size_t i = failures->size();
failures->resize(i + configResult.failures.size());
for (const c2_aidl::SettingResult& sf : configResult.failures) {
@@ -320,8 +325,8 @@
heapParams->reserve(heapParams->size() + numIndices);
}
c2_status_t status = C2_OK;
- c2_aidl::Params aidlParams;
- ScopedAStatus transResult = mAidlConfigurable->query(indices, true, &aidlParams);
+ c2_aidl::IConfigurable::QueryResult aidlResult;
+ ScopedAStatus transResult = mAidlConfigurable->query(indices, true, &aidlResult);
if (!transResult.isOk()) {
if (transResult.getExceptionCode() == EX_SERVICE_SPECIFIC) {
status = c2_status_t(transResult.getServiceSpecificError());
@@ -332,8 +337,12 @@
return C2_TRANSACTION_FAILED;
}
}
+ status = static_cast<c2_status_t>(aidlResult.status.status);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "query -- call failed: " << status << ".";
+ }
std::vector<C2Param*> paramPointers;
- if (!c2_aidl::utils::ParseParamsBlob(¶mPointers, aidlParams)) {
+ if (!c2_aidl::utils::ParseParamsBlob(¶mPointers, aidlResult.params)) {
LOG(ERROR) << "query -- error while parsing params.";
return C2_CORRUPTED;
}
@@ -488,9 +497,9 @@
}
c2_status_t status = C2_OK;
- std::vector<c2_aidl::FieldSupportedValuesQueryResult> queryResults;
+ c2_aidl::IConfigurable::QuerySupportedValuesResult queryResult;
ScopedAStatus transResult = mAidlConfigurable->querySupportedValues(
- aidlFields, true, &queryResults);
+ aidlFields, true, &queryResult);
if (!transResult.isOk()) {
if (transResult.getExceptionCode() == EX_SERVICE_SPECIFIC) {
status = c2_status_t(transResult.getServiceSpecificError());
@@ -502,14 +511,19 @@
return C2_TRANSACTION_FAILED;
}
}
- if (queryResults.size() != fields.size()) {
+ status = static_cast<c2_status_t>(queryResult.status.status);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "querySupportedValues -- call failed: "
+ << status << ".";
+ }
+ if (queryResult.values.size() != fields.size()) {
LOG(ERROR) << "querySupportedValues -- "
"input and output lists "
"have different sizes.";
return C2_CORRUPTED;
}
for (size_t i = 0; i < fields.size(); ++i) {
- if (!c2_aidl::utils::FromAidl(&fields[i], aidlFields[i], queryResults[i])) {
+ if (!c2_aidl::utils::FromAidl(&fields[i], aidlFields[i], queryResult.values[i])) {
LOG(ERROR) << "querySupportedValues -- "
"invalid returned value.";
return C2_CORRUPTED;
@@ -803,6 +817,7 @@
}
}
+ bool registered = false;
if (platformVersion >= __ANDROID_API_V__) {
if (!aidlStore) {
aidlStore = ::ndk::SharedRefBase::make<c2_aidl::utils::ComponentStore>(
@@ -812,23 +827,27 @@
std::string(c2_aidl::IComponentStore::descriptor) + "/software";
binder_exception_t ex = AServiceManager_addService(
aidlStore->asBinder().get(), serviceName.c_str());
- if (ex != EX_NONE) {
+ if (ex == EX_NONE) {
+ registered = true;
+ } else {
LOG(ERROR) << "Cannot register software Codec2 AIDL service.";
- return;
}
}
if (!hidlStore) {
- hidlStore = ::android::sp<V1_0::utils::ComponentStore>::make(
+ hidlStore = ::android::sp<V1_2::utils::ComponentStore>::make(
std::make_shared<H2C2ComponentStore>(nullptr));
- hidlVer = "1.0";
+ hidlVer = "1.2";
}
- if (hidlStore->registerAsService("software") != android::OK) {
+ if (hidlStore->registerAsService("software") == android::OK) {
+ registered = true;
+ } else {
LOG(ERROR) << "Cannot register software Codec2 v" << hidlVer << " service.";
- return;
}
- LOG(INFO) << "Software Codec2 service created and registered.";
+ if (registered) {
+ LOG(INFO) << "Software Codec2 service created and registered.";
+ }
ABinderProcess_joinThreadPool();
::android::hardware::joinRpcThreadpool();
diff --git a/media/module/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
index 0a8d2ab..d096d63 100644
--- a/media/module/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -189,6 +189,8 @@
],
dictionary: "mkv_extractor_fuzzer.dict",
+
+ corpus: ["corpus/*"],
}
cc_fuzz {
diff --git a/media/module/extractors/fuzzers/corpus/103c24dec0f5da3638a771e451cecfe38339b29c b/media/module/extractors/fuzzers/corpus/103c24dec0f5da3638a771e451cecfe38339b29c
new file mode 100755
index 0000000..8b31683
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/103c24dec0f5da3638a771e451cecfe38339b29c
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/2e532f8eb60e1c757f4399377e8f563a3cf3abf2e b/media/module/extractors/fuzzers/corpus/2e532f8eb60e1c757f4399377e8f563a3cf3abf2e
new file mode 100755
index 0000000..f4d475d
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/2e532f8eb60e1c757f4399377e8f563a3cf3abf2e
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/45e6a4014883a7e1f1200e2a53eabb4f0109aec3 b/media/module/extractors/fuzzers/corpus/45e6a4014883a7e1f1200e2a53eabb4f0109aec3
new file mode 100755
index 0000000..8438e66
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/45e6a4014883a7e1f1200e2a53eabb4f0109aec3
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/465b39984b71d8b4c2b80072993fb7ec73b4af69 b/media/module/extractors/fuzzers/corpus/465b39984b71d8b4c2b80072993fb7ec73b4af69
new file mode 100755
index 0000000..2f622cd
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/465b39984b71d8b4c2b80072993fb7ec73b4af69
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/4ef9546eab199719aadead2d26d3c1d72f42e600 b/media/module/extractors/fuzzers/corpus/4ef9546eab199719aadead2d26d3c1d72f42e600
new file mode 100755
index 0000000..f053c01
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/4ef9546eab199719aadead2d26d3c1d72f42e600
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/6b35d5a3af88baf240293ff1b8adf0b774055e65 b/media/module/extractors/fuzzers/corpus/6b35d5a3af88baf240293ff1b8adf0b774055e65
new file mode 100755
index 0000000..872451c
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/6b35d5a3af88baf240293ff1b8adf0b774055e65
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/7e798d68a1bf154e079227ee43e69ea27844b7e8 b/media/module/extractors/fuzzers/corpus/7e798d68a1bf154e079227ee43e69ea27844b7e8
new file mode 100755
index 0000000..2f7e3ea
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/7e798d68a1bf154e079227ee43e69ea27844b7e8
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/d2fd225343c99872f5a825f7f06b8c1dac0e8687 b/media/module/extractors/fuzzers/corpus/d2fd225343c99872f5a825f7f06b8c1dac0e8687
new file mode 100755
index 0000000..10b5f9a
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/d2fd225343c99872f5a825f7f06b8c1dac0e8687
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/d5602e69abf068ed8f1277e412149b8664d06620 b/media/module/extractors/fuzzers/corpus/d5602e69abf068ed8f1277e412149b8664d06620
new file mode 100755
index 0000000..969b7a2
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/d5602e69abf068ed8f1277e412149b8664d06620
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/e73fa90346e7287b7e923b0ebf07ce8988d94498 b/media/module/extractors/fuzzers/corpus/e73fa90346e7287b7e923b0ebf07ce8988d94498
new file mode 100755
index 0000000..bd146b1
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/e73fa90346e7287b7e923b0ebf07ce8988d94498
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus/f1ee160337d3a467402a2217897477f0fab15da b/media/module/extractors/fuzzers/corpus/f1ee160337d3a467402a2217897477f0fab15da
new file mode 100755
index 0000000..7cf844e
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus/f1ee160337d3a467402a2217897477f0fab15da
Binary files differ
diff --git a/media/module/extractors/wav/WAVExtractor.cpp b/media/module/extractors/wav/WAVExtractor.cpp
index 9c3bac6..d278103 100644
--- a/media/module/extractors/wav/WAVExtractor.cpp
+++ b/media/module/extractors/wav/WAVExtractor.cpp
@@ -219,7 +219,7 @@
mNumChannels = U16_LE_AT(&formatSpec[2]);
- if (mNumChannels < 1 || mNumChannels > FCC_8) {
+ if (mNumChannels < 1 || mNumChannels > FCC_12) {
ALOGE("Unsupported number of channels (%d)", mNumChannels);
return AMEDIA_ERROR_UNSUPPORTED;
}
diff --git a/media/module/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml b/media/module/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
index c3a0ced..f8906dc 100644
--- a/media/module/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
+++ b/media/module/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
@@ -15,6 +15,7 @@
-->
<configuration description="Unit test configuration for {MODULE}">
<option name="test-suite-tag" value="TranscoderTests" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="false" />
<option name="push-file" key="TranscodingTestAssets" value="/data/local/tmp/TranscodingTestAssets" />
diff --git a/media/module/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
index 88c3fd3..fed8fc9 100644
--- a/media/module/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
+++ b/media/module/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
@@ -20,6 +20,7 @@
#define LOG_TAG "VideoTrackTranscoderTests"
#include <android-base/logging.h>
+#include <android/binder_process.h>
#include <fcntl.h>
#include <gtest/gtest.h>
#include <media/MediaSampleReaderNDK.h>
@@ -221,5 +222,6 @@
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
}
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 8b9dde3..9ec7700 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -208,19 +208,21 @@
}
cc_test {
- name: "AImageReaderWindowHandleTest",
+ name: "AImageReaderWindowTest",
test_suites: ["device-tests"],
- srcs: ["tests/AImageReaderWindowHandleTest.cpp"],
+ srcs: ["tests/AImageReaderWindowTest.cpp"],
shared_libs: [
"libbinder",
"libmediandk",
"libmediautils",
"libnativewindow",
"libgui",
+ "libhidlbase",
"libutils",
"libui",
"libcutils",
"android.hardware.graphics.bufferqueue@1.0",
+ "android.hidl.token@1.0",
],
header_libs: [
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 9de511e..a26681e 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -450,6 +450,10 @@
EXPORT const char* AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_HEIGHT = "max-height";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size";
+EXPORT const char* AMEDIAFORMAT_KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE =
+ "buffer-batch-max-output-size";
+EXPORT const char* AMEDIAFORMAT_KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE =
+ "buffer-batch-threshold-output-size";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER = "max-pts-gap-to-encoder";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width";
EXPORT const char* AMEDIAFORMAT_KEY_MIME = "mime";
diff --git a/media/ndk/TEST_MAPPING b/media/ndk/TEST_MAPPING
index e420812..1a15728 100644
--- a/media/ndk/TEST_MAPPING
+++ b/media/ndk/TEST_MAPPING
@@ -1,7 +1,7 @@
// mappings for frameworks/av/media/ndk
{
"presubmit": [
- { "name": "AImageReaderWindowHandleTest" },
+ { "name": "AImageReaderWindowTest" },
{ "name": "libmediandk_test" }
]
}
diff --git a/media/ndk/fuzzer/ndk_crypto_fuzzer.cpp b/media/ndk/fuzzer/ndk_crypto_fuzzer.cpp
index 2b22f0f..fcb0520 100644
--- a/media/ndk/fuzzer/ndk_crypto_fuzzer.cpp
+++ b/media/ndk/fuzzer/ndk_crypto_fuzzer.cpp
@@ -16,6 +16,9 @@
#include <fuzzer/FuzzedDataProvider.h>
#include <media/NdkMediaCrypto.h>
+#include <functional>
+
+#include <functional>
constexpr size_t kMaxString = 256;
constexpr size_t kMinBytes = 0;
diff --git a/media/ndk/fuzzer/ndk_image_reader_fuzzer.cpp b/media/ndk/fuzzer/ndk_image_reader_fuzzer.cpp
index 6c11798..6450742 100644
--- a/media/ndk/fuzzer/ndk_image_reader_fuzzer.cpp
+++ b/media/ndk/fuzzer/ndk_image_reader_fuzzer.cpp
@@ -18,6 +18,7 @@
#include <fuzzer/FuzzedDataProvider.h>
#include <gui/BufferQueue.h>
#include <media/NdkImageReader.h>
+#include <functional>
constexpr int32_t kMaxSize = INT_MAX;
constexpr int32_t kMinSize = 1;
diff --git a/media/ndk/include/media/NdkImageReader.h b/media/ndk/include/media/NdkImageReader.h
index b722b74..4fc9918 100644
--- a/media/ndk/include/media/NdkImageReader.h
+++ b/media/ndk/include/media/NdkImageReader.h
@@ -534,7 +534,8 @@
* Get the native_handle_t corresponding to the ANativeWindow owned by the
* AImageReader provided.
*
- * This is deprecated in API level 35 and will return AMEDIA_ERROR_UNKNOWN.
+ * This is deprecated on devices with vendor API level greater than 34 and
+ * will return AMEDIA_ERROR_UNKNOWN on those devices.
* The native_handle_t is no longer used with AIDL interfaces and
* ANativeWindow is used directly instead.
* Use AImageRead_getWindow to get the ANativeWindow and use that object.
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 24a10dc..cc1dd9f 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -187,6 +187,8 @@
extern const char* AMEDIAFORMAT_KEY_MAX_B_FRAMES __INTRODUCED_IN(34);
extern const char* AMEDIAFORMAT_KEY_MAX_HEIGHT __INTRODUCED_IN(21);
extern const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE __INTRODUCED_IN(21);
+extern const char* AMEDIAFORMAT_KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE __INTRODUCED_IN(35);
+extern const char* AMEDIAFORMAT_KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE __INTRODUCED_IN(35);
extern const char* AMEDIAFORMAT_KEY_MAX_WIDTH __INTRODUCED_IN(21);
extern const char* AMEDIAFORMAT_KEY_MIME __INTRODUCED_IN(21);
extern const char* AMEDIAFORMAT_KEY_MPEG_USER_DATA __INTRODUCED_IN(28);
diff --git a/media/ndk/tests/AImageReaderWindowHandleTest.cpp b/media/ndk/tests/AImageReaderWindowHandleTest.cpp
deleted file mode 100644
index 27864c2..0000000
--- a/media/ndk/tests/AImageReaderWindowHandleTest.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#include <gtest/gtest.h>
-#include <media/NdkImageReader.h>
-#include <media/NdkImage.h>
-#include <mediautils/AImageReaderUtils.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
-#include <NdkImagePriv.h>
-#include <NdkImageReaderPriv.h>
-#include <vndk/hardware_buffer.h>
-#include <memory>
-
-namespace android {
-
-using HGraphicBufferProducer = hardware::graphics::bufferqueue::V1_0::
- IGraphicBufferProducer;
-using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
-using aimg::AImageReader_getHGBPFromHandle;
-
-typedef IGraphicBufferProducer::QueueBufferInput QueueBufferInput;
-typedef IGraphicBufferProducer::QueueBufferOutput QueueBufferOutput;
-
-static constexpr uint64_t kImageBufferUsage =
- AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
-static constexpr int kImageWidth = 640;
-static constexpr int kImageHeight = 480;
-static constexpr int kImageFormat = AIMAGE_FORMAT_RGBA_8888;
-static constexpr int kMaxImages = 1;
-
-static constexpr int64_t kQueueBufferInputTimeStamp = 1384888611;
-static constexpr bool kQueueBufferInputIsAutoTimeStamp = false;
-static constexpr android_dataspace kQueueBufferInputDataspace = HAL_DATASPACE_UNKNOWN;
-static const Rect kQueueBufferInputRect = Rect(kImageWidth, kImageHeight);
-static constexpr int kQueueBufferInputScalingMode = 0;
-static constexpr int kQueueBufferInputTransform = 0;
-static const sp<Fence> kQueueBufferInputFence = Fence::NO_FENCE;
-
-static constexpr int kOnImageAvailableWaitUs = 100 * 1000;
-
-class AImageReaderWindowHandleTest : public ::testing::Test {
- public:
- void SetUp() override {
- AImageReader_newWithUsage(kImageWidth, kImageHeight, kImageFormat,
- kImageBufferUsage , kMaxImages, &imageReader_);
- media_status_t ret = AMEDIA_ERROR_UNKNOWN;
- ASSERT_NE(imageReader_, nullptr);
- ret = AImageReader_setImageListener(imageReader_,
- &imageReaderAvailableCb_);
- ASSERT_EQ(ret, AMEDIA_OK);
- ret = AImageReader_setBufferRemovedListener(imageReader_,
- &imageReaderDetachedCb_);
- ASSERT_EQ(ret, AMEDIA_OK);
- }
- void TearDown() override {
- if (imageReader_) {
- AImageReader_delete(imageReader_);
- }
- }
-
- void HandleImageAvailable() {
- AImage *outImage = nullptr;
- media_status_t ret = AMEDIA_OK;
- auto imageDeleter = [](AImage *img) { AImage_delete(img); };
- std::unique_ptr<AImage, decltype(imageDeleter)> img(nullptr, imageDeleter);
-
- // Test that the image can be acquired.
- ret = AImageReader_acquireNextImage(imageReader_, &outImage);
- ASSERT_EQ(ret, AMEDIA_OK);
- img.reset(outImage);
- ASSERT_NE(img, nullptr);
-
- // Test that we can get a handle to the image's hardware buffer and a
- // native handle to it.
- AHardwareBuffer *hardwareBuffer = nullptr;
- ret = AImage_getHardwareBuffer(img.get(), &hardwareBuffer);
- ASSERT_EQ(ret, AMEDIA_OK);
- ASSERT_NE(hardwareBuffer, nullptr);
- const native_handle_t *nh = AHardwareBuffer_getNativeHandle(hardwareBuffer);
- ASSERT_NE(nh, nullptr);
- std::unique_lock<std::mutex> lock(imageAvailableMutex_);
- imageAvailable_ = true;
- imageCondVar_.notify_one();
- }
-
- static void onImageAvailable(void *context, AImageReader *reader) {
- (void)reader;
- AImageReaderWindowHandleTest *thisContext =
- reinterpret_cast<AImageReaderWindowHandleTest *>(context);
- thisContext->HandleImageAvailable();
- }
-
- static void onBufferRemoved(void *, AImageReader *, AHardwareBuffer *) {
- }
-
- AImageReader *imageReader_ = nullptr;
- AImageReader_ImageListener imageReaderAvailableCb_{this, onImageAvailable};
- AImageReader_BufferRemovedListener imageReaderDetachedCb_{this, onBufferRemoved};
- std::mutex imageAvailableMutex_;
- std::condition_variable imageCondVar_;
- bool imageAvailable_ = false;
-};
-
-static void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
- const size_t PIXEL_SIZE = 4;
- for (int x = 0; x < w; x++) {
- for (int y = 0; y < h; y++) {
- off_t offset = (y * stride + x) * PIXEL_SIZE;
- for (int c = 0; c < 4; c++) {
- int parityX = (x / (1 << (c+2))) & 1;
- int parityY = (y / (1 << (c+2))) & 1;
- buf[offset + c] = (parityX ^ parityY) ? 231 : 35;
- }
- }
- }
-}
-
-TEST_F(AImageReaderWindowHandleTest, CreateWindowNativeHandle) {
- // Check that we can create a native_handle_t corresponding to the
- // AImageReader.
- native_handle_t *nh = nullptr;
- AImageReader_getWindowNativeHandle(imageReader_, &nh);
- ASSERT_NE(nh, nullptr);
-
- // Check that there are only ints in the handle.
- ASSERT_EQ(nh->numFds, 0);
- ASSERT_NE(nh->numInts, 0);
-
- // Check that the HGBP can be retrieved from the handle.
- sp<HGraphicBufferProducer> hgbp = AImageReader_getHGBPFromHandle(nh);
- ASSERT_NE(hgbp, nullptr);
- sp<IGraphicBufferProducer> igbp = new H2BGraphicBufferProducer(hgbp);
- int dequeuedSlot = -1;
- sp<Fence> dequeuedFence;
- IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, igbp->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
-
- // Test that we can dequeue a buffer.
- ASSERT_EQ(OK,
- ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
- (igbp->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
- kImageWidth, kImageHeight,
- kImageFormat, kImageBufferUsage,
- nullptr, nullptr)));
- EXPECT_LE(0, dequeuedSlot);
- EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
-
- sp<GraphicBuffer> dequeuedBuffer;
- igbp->requestBuffer(dequeuedSlot, &dequeuedBuffer);
- uint8_t* img = nullptr;
- ASSERT_EQ(NO_ERROR, dequeuedBuffer->lock(kImageBufferUsage, (void**)(&img)));
-
- // Write in some dummy image data.
- fillRGBA8Buffer(img, dequeuedBuffer->getWidth(), dequeuedBuffer->getHeight(),
- dequeuedBuffer->getStride());
- ASSERT_EQ(NO_ERROR, dequeuedBuffer->unlock());
- QueueBufferInput queueBufferInput(kQueueBufferInputTimeStamp,
- kQueueBufferInputIsAutoTimeStamp,
- kQueueBufferInputDataspace,
- kQueueBufferInputRect,
- kQueueBufferInputScalingMode,
- kQueueBufferInputTransform,
- kQueueBufferInputFence);
- QueueBufferOutput queueBufferOutput;
- ASSERT_EQ(OK, igbp->queueBuffer(dequeuedSlot, queueBufferInput,
- &queueBufferOutput));
- // wait until the onImageAvailable callback is called, or timeout completes.
- std::unique_lock<std::mutex> lock(imageAvailableMutex_);
- imageCondVar_.wait_for(lock, std::chrono::microseconds(kOnImageAvailableWaitUs),
- [this]{ return this->imageAvailable_;});
- EXPECT_TRUE(imageAvailable_) << "Timed out waiting for image data to be handled!\n";
-}
-
-class AImageReaderPrivateFormatTest : public ::testing::Test {
- public:
- void SetUp() override {
- auto status = AImageReader_new(kImageWidth, kImageHeight, AIMAGE_FORMAT_RAW_DEPTH,
- kMaxImages, &imgReader);
- EXPECT_TRUE(status == AMEDIA_OK);
- }
-
- void TearDown() override {
- if (imgReader) {
- AImageReader_delete(imgReader);
- }
- }
- AImageReader *imgReader = nullptr;
-};
-
-TEST_F(AImageReaderPrivateFormatTest, CreateTest) {
- EXPECT_TRUE(imgReader != nullptr);
-}
-
-
-} // namespace android
diff --git a/media/ndk/tests/AImageReaderWindowTest.cpp b/media/ndk/tests/AImageReaderWindowTest.cpp
new file mode 100644
index 0000000..650b990
--- /dev/null
+++ b/media/ndk/tests/AImageReaderWindowTest.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#include <android/hidl/token/1.0/ITokenManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <hidl/ServiceManagement.h>
+#include <media/NdkImageReader.h>
+#include <media/NdkImage.h>
+#include <mediautils/AImageReaderUtils.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
+#include <NdkImagePriv.h>
+#include <NdkImageReaderPriv.h>
+#include <vndk/hardware_buffer.h>
+#include <memory>
+
+namespace android {
+
+using HGraphicBufferProducer = hardware::graphics::bufferqueue::V1_0::
+ IGraphicBufferProducer;
+using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
+using hidl::manager::V1_2::IServiceManager;
+using hidl::token::V1_0::ITokenManager;
+using aimg::AImageReader_getHGBPFromHandle;
+
+typedef IGraphicBufferProducer::QueueBufferInput QueueBufferInput;
+typedef IGraphicBufferProducer::QueueBufferOutput QueueBufferOutput;
+
+static constexpr uint64_t kImageBufferUsage =
+ AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+static constexpr int kImageWidth = 640;
+static constexpr int kImageHeight = 480;
+static constexpr int kImageFormat = AIMAGE_FORMAT_RGBA_8888;
+static constexpr int kMaxImages = 1;
+
+static constexpr int64_t kQueueBufferInputTimeStamp = 1384888611;
+static constexpr bool kQueueBufferInputIsAutoTimeStamp = false;
+static constexpr android_dataspace kQueueBufferInputDataspace = HAL_DATASPACE_UNKNOWN;
+static const Rect kQueueBufferInputRect = Rect(kImageWidth, kImageHeight);
+static constexpr int kQueueBufferInputScalingMode = 0;
+static constexpr int kQueueBufferInputTransform = 0;
+static const sp<Fence> kQueueBufferInputFence = Fence::NO_FENCE;
+
+static constexpr int kOnImageAvailableWaitUs = 100 * 1000;
+
+class AImageReaderWindowTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ AImageReader_newWithUsage(kImageWidth, kImageHeight, kImageFormat,
+ kImageBufferUsage , kMaxImages, &imageReader_);
+ media_status_t ret = AMEDIA_ERROR_UNKNOWN;
+ ASSERT_NE(imageReader_, nullptr);
+ ret = AImageReader_setImageListener(imageReader_,
+ &imageReaderAvailableCb_);
+ ASSERT_EQ(ret, AMEDIA_OK);
+ ret = AImageReader_setBufferRemovedListener(imageReader_,
+ &imageReaderDetachedCb_);
+ ASSERT_EQ(ret, AMEDIA_OK);
+ }
+ void TearDown() override {
+ if (imageReader_) {
+ AImageReader_delete(imageReader_);
+ }
+ }
+
+ void HandleImageAvailable() {
+ AImage *outImage = nullptr;
+ media_status_t ret = AMEDIA_OK;
+ auto imageDeleter = [](AImage *img) { AImage_delete(img); };
+ std::unique_ptr<AImage, decltype(imageDeleter)> img(nullptr, imageDeleter);
+
+ // Test that the image can be acquired.
+ ret = AImageReader_acquireNextImage(imageReader_, &outImage);
+ ASSERT_EQ(ret, AMEDIA_OK);
+ img.reset(outImage);
+ ASSERT_NE(img, nullptr);
+
+ // Test that we can get a handle to the image's hardware buffer and a
+ // native handle to it.
+ AHardwareBuffer *hardwareBuffer = nullptr;
+ ret = AImage_getHardwareBuffer(img.get(), &hardwareBuffer);
+ ASSERT_EQ(ret, AMEDIA_OK);
+ ASSERT_NE(hardwareBuffer, nullptr);
+ const native_handle_t *nh = AHardwareBuffer_getNativeHandle(hardwareBuffer);
+ ASSERT_NE(nh, nullptr);
+ std::unique_lock<std::mutex> lock(imageAvailableMutex_);
+ imageAvailable_ = true;
+ imageCondVar_.notify_one();
+ }
+
+ static void onImageAvailable(void *context, AImageReader *reader) {
+ (void)reader;
+ AImageReaderWindowTest *thisContext =
+ reinterpret_cast<AImageReaderWindowTest *>(context);
+ thisContext->HandleImageAvailable();
+ }
+
+ static void onBufferRemoved(void *, AImageReader *, AHardwareBuffer *) {
+ }
+
+ static void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
+ const size_t PIXEL_SIZE = 4;
+ for (int x = 0; x < w; x++) {
+ for (int y = 0; y < h; y++) {
+ off_t offset = (y * stride + x) * PIXEL_SIZE;
+ for (int c = 0; c < 4; c++) {
+ int parityX = (x / (1 << (c+2))) & 1;
+ int parityY = (y / (1 << (c+2))) & 1;
+ buf[offset + c] = (parityX ^ parityY) ? 231 : 35;
+ }
+ }
+ }
+ }
+
+ void validateIGBP(sp<IGraphicBufferProducer>& igbp) {
+ int dequeuedSlot = -1;
+ sp<Fence> dequeuedFence;
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_EQ(OK, igbp->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
+
+ // Test that we can dequeue a buffer.
+ ASSERT_EQ(OK,
+ ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (igbp->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+ kImageWidth, kImageHeight,
+ kImageFormat, kImageBufferUsage,
+ nullptr, nullptr)));
+ EXPECT_LE(0, dequeuedSlot);
+ EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
+
+ sp<GraphicBuffer> dequeuedBuffer;
+ igbp->requestBuffer(dequeuedSlot, &dequeuedBuffer);
+ uint8_t* img = nullptr;
+ ASSERT_EQ(NO_ERROR, dequeuedBuffer->lock(kImageBufferUsage, (void**)(&img)));
+
+ // Write in some placeholder image data.
+ fillRGBA8Buffer(img, dequeuedBuffer->getWidth(), dequeuedBuffer->getHeight(),
+ dequeuedBuffer->getStride());
+ ASSERT_EQ(NO_ERROR, dequeuedBuffer->unlock());
+ QueueBufferInput queueBufferInput(kQueueBufferInputTimeStamp,
+ kQueueBufferInputIsAutoTimeStamp,
+ kQueueBufferInputDataspace,
+ kQueueBufferInputRect,
+ kQueueBufferInputScalingMode,
+ kQueueBufferInputTransform,
+ kQueueBufferInputFence);
+ QueueBufferOutput queueBufferOutput;
+ ASSERT_EQ(OK, igbp->queueBuffer(dequeuedSlot, queueBufferInput,
+ &queueBufferOutput));
+ // wait until the onImageAvailable callback is called, or timeout completes.
+ std::unique_lock<std::mutex> lock(imageAvailableMutex_);
+ imageCondVar_.wait_for(lock, std::chrono::microseconds(kOnImageAvailableWaitUs),
+ [this]{ return this->imageAvailable_;});
+ EXPECT_TRUE(imageAvailable_) << "Timed out waiting for image data to be handled!\n";
+ }
+
+ AImageReader *imageReader_ = nullptr;
+ AImageReader_ImageListener imageReaderAvailableCb_{this, onImageAvailable};
+ AImageReader_BufferRemovedListener imageReaderDetachedCb_{this, onBufferRemoved};
+ std::mutex imageAvailableMutex_;
+ std::condition_variable imageCondVar_;
+ bool imageAvailable_ = false;
+};
+
+
+TEST_F(AImageReaderWindowTest, CreateWindowNativeHandle) {
+ // Check that we can create a native_handle_t corresponding to the
+ // AImageReader.
+ native_handle_t *nh = nullptr;
+ media_status_t status = AImageReader_getWindowNativeHandle(imageReader_, &nh);
+
+ // On newer devices without the HIDL TokenManager service this API is
+ // deprecated and will return an error.
+ if (IServiceManager::Transport::EMPTY ==
+ hardware::defaultServiceManager1_2()->getTransport(ITokenManager::descriptor, "default")) {
+ EXPECT_EQ(status, AMEDIA_ERROR_UNKNOWN);
+ return;
+ }
+ ASSERT_NE(nh, nullptr);
+
+ // Check that there are only ints in the handle.
+ ASSERT_EQ(nh->numFds, 0);
+ ASSERT_NE(nh->numInts, 0);
+
+ // Check that the HGBP can be retrieved from the handle.
+ sp<HGraphicBufferProducer> hgbp = AImageReader_getHGBPFromHandle(nh);
+ ASSERT_NE(hgbp, nullptr);
+ sp<IGraphicBufferProducer> igbp = new H2BGraphicBufferProducer(hgbp);
+
+ validateIGBP(igbp);
+}
+
+TEST_F(AImageReaderWindowTest, CreateWindow) {
+ ANativeWindow* window = nullptr;
+ media_status_t status = AImageReader_getWindow(imageReader_, &window);
+
+ ASSERT_NE(window, nullptr);
+
+ sp<IGraphicBufferProducer> igbp = Surface::getIGraphicBufferProducer(window);
+
+ validateIGBP(igbp);
+}
+
+class AImageReaderPrivateFormatTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ auto status = AImageReader_new(kImageWidth, kImageHeight, AIMAGE_FORMAT_RAW_DEPTH,
+ kMaxImages, &imgReader);
+ EXPECT_TRUE(status == AMEDIA_OK);
+ }
+
+ void TearDown() override {
+ if (imgReader) {
+ AImageReader_delete(imgReader);
+ }
+ }
+ AImageReader *imgReader = nullptr;
+};
+
+TEST_F(AImageReaderPrivateFormatTest, CreateTest) {
+ EXPECT_TRUE(imgReader != nullptr);
+}
+
+
+} // namespace android
diff --git a/media/utils/include/mediautils/ExtendedAccumulator.h b/media/utils/include/mediautils/ExtendedAccumulator.h
index 7e3e170..30045f3 100644
--- a/media/utils/include/mediautils/ExtendedAccumulator.h
+++ b/media/utils/include/mediautils/ExtendedAccumulator.h
@@ -48,9 +48,9 @@
public:
enum class Wrap {
- NORMAL = 0,
- UNDERFLOW = 1,
- OVERFLOW = 2,
+ Normal = 0,
+ Underflow = 1,
+ Overflow = 2,
};
using UnsignedInt = Integral;
@@ -63,11 +63,11 @@
std::pair<SignedInt, Wrap> poll(UnsignedInt value) {
auto acc = mAccumulated.load(std::memory_order_relaxed);
const auto bottom_bits = static_cast<UnsignedInt>(acc);
- std::pair<SignedInt, Wrap> res = {0, Wrap::NORMAL};
+ std::pair<SignedInt, Wrap> res = {0, Wrap::Normal};
const bool overflow = __builtin_sub_overflow(value, bottom_bits, &res.first);
if (overflow) {
- res.second = (res.first > 0) ? Wrap::OVERFLOW : Wrap::UNDERFLOW;
+ res.second = (res.first > 0) ? Wrap::Overflow : Wrap::Underflow;
}
const bool acc_overflow = __builtin_add_overflow(acc, res.first, &acc);
diff --git a/media/utils/include/mediautils/StaticStringView.h b/media/utils/include/mediautils/StaticStringView.h
index 14be240..e9a5deb 100644
--- a/media/utils/include/mediautils/StaticStringView.h
+++ b/media/utils/include/mediautils/StaticStringView.h
@@ -21,15 +21,15 @@
#pragma push_macro("EXPLICIT_CONVERSION_GENERATE_OPERATOR")
#undef EXPLICIT_CONVERSION_GENERATE_OPERATOR
-#define EXPLICIT_CONVERSION_GENERATE_OPERATOR(T, U, op) \
- friend constexpr bool operator op(T lhs, T rhs) { \
- return operator op(static_cast<U>(lhs), static_cast<U>(rhs)); \
- } \
- friend constexpr bool operator op(T lhs, U rhs) { \
- return operator op(static_cast<U>(lhs), rhs); \
- } \
- friend constexpr bool operator op(U lhs, T rhs) { \
- return operator op(lhs, static_cast<U>(rhs)); \
+#define EXPLICIT_CONVERSION_GENERATE_OPERATOR(T, U, op) \
+ friend constexpr bool operator op(T lhs, T rhs) { \
+ return static_cast<U>(lhs) op static_cast<U>(rhs); \
+ } \
+ friend constexpr bool operator op(T lhs, U rhs) { \
+ return static_cast<U>(lhs) op rhs; \
+ } \
+ friend constexpr bool operator op(U lhs, T rhs) { \
+ return lhs op static_cast<U>(rhs); \
}
#pragma push_macro("EXPLICIT_CONVERSION_GENERATE_COMPARISON_OPERATORS")
diff --git a/media/utils/tests/extended_accumulator_tests.cpp b/media/utils/tests/extended_accumulator_tests.cpp
index e243e7e..2591df0 100644
--- a/media/utils/tests/extended_accumulator_tests.cpp
+++ b/media/utils/tests/extended_accumulator_tests.cpp
@@ -68,10 +68,10 @@
EXPECT_EQ(result, delta);
// Test overflow/underflow event reporting.
- if (next < base) EXPECT_EQ(TestDetect::Wrap::UNDERFLOW, status);
+ if (next < base) EXPECT_EQ(TestDetect::Wrap::Underflow, status);
else if (next > base + std::numeric_limits<TestUInt>::max())
- EXPECT_EQ(TestDetect::Wrap::OVERFLOW, status);
- else EXPECT_EQ(TestDetect::Wrap::NORMAL, status);
+ EXPECT_EQ(TestDetect::Wrap::Overflow, status);
+ else EXPECT_EQ(TestDetect::Wrap::Normal, status);
}
// Test this utility on every combination of prior and update value for the
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index ae60ed0..2577ca8 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -23,6 +23,7 @@
#include <audio_utils/mutex.h>
#include <audio_utils/LinearMap.h>
#include <binder/AppOpsManager.h>
+#include <utils/RWLock.h>
namespace android {
@@ -352,6 +353,7 @@
// Must hold thread lock to access tee patches
template <class F>
void forEachTeePatchTrack_l(F f) {
+ RWLock::AutoRLock readLock(mTeePatchesRWLock);
for (auto& tp : mTeePatches) { f(tp.patchTrack); }
};
@@ -387,6 +389,7 @@
audio_output_flags_t mFlags;
TeePatches mTeePatches;
std::optional<TeePatches> mTeePatchesToUpdate;
+ RWLock mTeePatchesRWLock;
const float mSpeed;
const bool mIsSpatialized;
const bool mIsBitPerfect;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 224c65b..4fe5b84 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1081,7 +1081,13 @@
// Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
// does not allow 0 frame size request contrary to getNextBuffer
}
- for (auto& teePatch : mTeePatches) {
+ TeePatches teePatches;
+ if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
+ // Cache a copy of tee patches in case it is updated while using.
+ teePatches = mTeePatches;
+ mTeePatchesRWLock.unlock();
+ }
+ for (auto& teePatch : teePatches) {
IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
const size_t framesWritten = patchRecord->writeFrames(
sourceBuffer.i8, frameCount, mFrameSize);
@@ -1094,7 +1100,7 @@
using namespace std::chrono_literals;
// Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
- spent.count(), mTeePatches.size());
+ spent.count(), teePatches.size());
}
// ExtendedAudioBufferProvider interface
@@ -1616,7 +1622,10 @@
void Track::updateTeePatches_l() {
if (mTeePatchesToUpdate.has_value()) {
forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
- mTeePatches = mTeePatchesToUpdate.value();
+ {
+ RWLock::AutoWLock writeLock(mTeePatchesRWLock);
+ mTeePatches = std::move(mTeePatchesToUpdate.value());
+ }
if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
mState == TrackBase::STOPPING_1) {
forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 58e5311..2fd908f 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3225,7 +3225,8 @@
ALOGD("%s: no group matching with %s", __FUNCTION__, toString(attributes).c_str());
return BAD_VALUE;
}
- ALOGV("%s: group %d matching with %s", __FUNCTION__, group, toString(attributes).c_str());
+ ALOGV("%s: group %d matching with %s index %d",
+ __FUNCTION__, group, toString(attributes).c_str(), index);
status_t status = NO_ERROR;
IVolumeCurves &curves = getVolumeCurves(attributes);
VolumeSource vs = toVolumeSource(group);
@@ -3342,6 +3343,21 @@
status = volStatus;
}
}
+
+ // update voice volume if the an active call route exists
+ if (mCallRxSourceClient != nullptr && mCallRxSourceClient->isConnected()
+ && (curSrcDevices.find(
+ Volume::getDeviceForVolume({mCallRxSourceClient->sinkDevice()->type()}))
+ != curSrcDevices.end())) {
+ bool isVoiceVolSrc;
+ bool isBtScoVolSrc;
+ if (isVolumeConsistentForCalls(vs, {mCallRxSourceClient->sinkDevice()->type()},
+ isVoiceVolSrc, isBtScoVolSrc, __func__)
+ && (isVoiceVolSrc || isBtScoVolSrc)) {
+ setVoiceVolume(index, curves, isVoiceVolSrc, 0);
+ }
+ }
+
mpClientInterface->onAudioVolumeGroupChanged(group, 0 /*flags*/);
return status;
}
@@ -7815,26 +7831,16 @@
outputDesc->getMuteCount(volumeSource), outputDesc->isActive(volumeSource));
return NO_ERROR;
}
- VolumeSource callVolSrc = toVolumeSource(AUDIO_STREAM_VOICE_CALL, false);
- VolumeSource btScoVolSrc = toVolumeSource(AUDIO_STREAM_BLUETOOTH_SCO, false);
- bool isVoiceVolSrc = (volumeSource != VOLUME_SOURCE_NONE) && (callVolSrc == volumeSource);
- bool isBtScoVolSrc = (volumeSource != VOLUME_SOURCE_NONE) && (btScoVolSrc == volumeSource);
- bool isScoRequested = isScoRequestedForComm();
- bool isHAUsed = isHearingAidUsedForComm();
-
- // do not change in call volume if bluetooth is connected and vice versa
- // if sco and call follow same curves, bypass forceUseForComm
- if ((callVolSrc != btScoVolSrc) &&
- ((isVoiceVolSrc && isScoRequested) ||
- (isBtScoVolSrc && !(isScoRequested || isHAUsed))) &&
- !isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
- ALOGV("%s cannot set volume group %d volume when is%srequested for comm", __func__,
- volumeSource, isScoRequested ? " " : " not ");
+ bool isVoiceVolSrc;
+ bool isBtScoVolSrc;
+ if (!isVolumeConsistentForCalls(
+ volumeSource, deviceTypes, isVoiceVolSrc, isBtScoVolSrc, __func__)) {
// Do not return an error here as AudioService will always set both voice call
- // and bluetooth SCO volumes due to stream aliasing.
+ // and Bluetooth SCO volumes due to stream aliasing.
return NO_ERROR;
}
+
if (deviceTypes.empty()) {
deviceTypes = outputDesc->devices().types();
index = curves.getVolumeIndex(deviceTypes);
@@ -7859,21 +7865,51 @@
deviceTypes, delayMs, force, isVoiceVolSrc);
if (outputDesc == mPrimaryOutput && (isVoiceVolSrc || isBtScoVolSrc)) {
- float voiceVolume;
- // Force voice volume to max or mute for Bluetooth SCO as other attenuations are managed by the headset
- if (isVoiceVolSrc) {
- voiceVolume = (float)index/(float)curves.getVolumeIndexMax();
- } else {
- voiceVolume = index == 0 ? 0.0 : 1.0;
- }
- if (voiceVolume != mLastVoiceVolume) {
- mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
- mLastVoiceVolume = voiceVolume;
- }
+ setVoiceVolume(index, curves, isVoiceVolSrc, delayMs);
}
return NO_ERROR;
}
+void AudioPolicyManager::setVoiceVolume(
+ int index, IVolumeCurves &curves, bool isVoiceVolSrc, int delayMs) {
+ float voiceVolume;
+ // Force voice volume to max or mute for Bluetooth SCO as other attenuations are managed
+ // by the headset
+ if (isVoiceVolSrc) {
+ voiceVolume = (float)index/(float)curves.getVolumeIndexMax();
+ } else {
+ voiceVolume = index == 0 ? 0.0 : 1.0;
+ }
+ if (voiceVolume != mLastVoiceVolume) {
+ mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
+ mLastVoiceVolume = voiceVolume;
+ }
+}
+
+bool AudioPolicyManager::isVolumeConsistentForCalls(VolumeSource volumeSource,
+ const DeviceTypeSet& deviceTypes,
+ bool& isVoiceVolSrc,
+ bool& isBtScoVolSrc,
+ const char* caller) {
+ const VolumeSource callVolSrc = toVolumeSource(AUDIO_STREAM_VOICE_CALL, false);
+ const VolumeSource btScoVolSrc = toVolumeSource(AUDIO_STREAM_BLUETOOTH_SCO, false);
+ const bool isScoRequested = isScoRequestedForComm();
+ const bool isHAUsed = isHearingAidUsedForComm();
+
+ isVoiceVolSrc = (volumeSource != VOLUME_SOURCE_NONE) && (callVolSrc == volumeSource);
+ isBtScoVolSrc = (volumeSource != VOLUME_SOURCE_NONE) && (btScoVolSrc == volumeSource);
+
+ if ((callVolSrc != btScoVolSrc) &&
+ ((isVoiceVolSrc && isScoRequested) ||
+ (isBtScoVolSrc && !(isScoRequested || isHAUsed))) &&
+ !isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
+ ALOGV("%s cannot set volume group %d volume when is%srequested for comm", caller,
+ volumeSource, isScoRequested ? " " : " not ");
+ return false;
+ }
+ return true;
+}
+
void AudioPolicyManager::applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
const DeviceTypeSet& deviceTypes,
int delayMs,
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 5b9f6ad..8f8550c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -575,6 +575,20 @@
DeviceTypeSet deviceTypes,
int delayMs = 0, bool force = false);
+ void setVoiceVolume(int index, IVolumeCurves &curves, bool isVoiceVolSrc, int delayMs);
+
+ // returns true if the supplied set of volume source and devices are consistent with
+ // call volume rules:
+ // if Bluetooth SCO and voice call use different volume curves:
+ // - do not apply voice call volume if Bluetooth SCO is used for call
+ // - do not apply Bluetooth SCO volume if SCO or Hearing Aid is not used for call.
+ // Also updates the booleans isVoiceVolSrc and isBtScoVolSrc according to the
+ // volume source supplied.
+ bool isVolumeConsistentForCalls(VolumeSource volumeSource,
+ const DeviceTypeSet& deviceTypes,
+ bool& isVoiceVolSrc,
+ bool& isBtScoVolSrc,
+ const char* caller);
// apply all stream volumes to the specified output and device
void applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
const DeviceTypeSet& deviceTypes,
diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp
index a2f17c2..506b3bc 100644
--- a/services/mediacodec/Android.bp
+++ b/services/mediacodec/Android.bp
@@ -95,31 +95,6 @@
"android.hidl.memory@1.0",
],
- runtime_libs: [
- "libstagefright_soft_aacdec",
- "libstagefright_soft_aacenc",
- "libstagefright_soft_amrdec",
- "libstagefright_soft_amrnbenc",
- "libstagefright_soft_amrwbenc",
- "libstagefright_soft_avcdec",
- "libstagefright_soft_avcenc",
- "libstagefright_soft_flacdec",
- "libstagefright_soft_flacenc",
- "libstagefright_soft_g711dec",
- "libstagefright_soft_gsmdec",
- "libstagefright_soft_hevcdec",
- "libstagefright_soft_mp3dec",
- "libstagefright_soft_mpeg2dec",
- "libstagefright_soft_mpeg4dec",
- "libstagefright_soft_mpeg4enc",
- "libstagefright_soft_opusdec",
- "libstagefright_soft_rawdec",
- "libstagefright_soft_vorbisdec",
- "libstagefright_soft_vpxdec",
- "libstagefright_soft_vpxenc",
- "libstagefright_softomx_plugin",
- ],
-
// OMX interfaces force this to stay in 32-bit mode;
compile_multilib: "32",
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy
index a55c3eb..0c6aafd 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy
@@ -52,6 +52,9 @@
getdents64: 1
ppoll: 1
+clock_gettime: 1
+pipe2: 1
+
# Required by AddressSanitizer
gettid: 1
sched_yield: 1
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
index cd3e579..63ae4c0 100755
--- a/tools/mainline_hook_partial.sh
+++ b/tools/mainline_hook_partial.sh
Binary files differ
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
index 1cc3b2b..d58143e 100755
--- a/tools/mainline_hook_project.sh
+++ b/tools/mainline_hook_project.sh
@@ -16,8 +16,8 @@
# tunables
-DEV_BRANCH=master
-MAINLINE_BRANCH=tm-mainline-prod
+DEV_BRANCH=main
+MAINLINE_BRANCH=udc-mainline-prod
###
RED=$(tput setaf 1)