Merge "NdkMedia: fix android.mediav2.cts.CodecEncoderSurfaceTest failed." into main
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index eaf5051..0b0d46a 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -8,21 +8,7 @@
}
cc_defaults {
- name: "aidl_clearkey_service_defaults",
- vendor: true,
-
- srcs: [
- "CreatePluginFactories.cpp",
- "CryptoPlugin.cpp",
- "DrmFactory.cpp",
- "DrmPlugin.cpp",
- ],
-
- relative_install_path: "hw",
-
- cflags: ["-Wall", "-Werror", "-Wthread-safety"],
-
- include_dirs: ["frameworks/av/include"],
+ name: "aidl_clearkey_service_defaults-use-shared-deps",
shared_libs: [
"libbase",
@@ -39,6 +25,46 @@
"libclearkeybase",
"libjsoncpp",
],
+}
+
+cc_defaults {
+ name: "aidl_clearkey_service_defaults-use-static-deps",
+
+ stl: "c++_static",
+
+ shared_libs: [
+ "libbinder_ndk",
+ "libcrypto",
+ "liblog",
+ ],
+
+ static_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.drm-V1-ndk",
+ "libbase",
+ "libclearkeybase",
+ "libjsoncpp",
+ "libprotobuf-cpp-lite",
+ "libutils",
+ ],
+}
+
+cc_defaults {
+ name: "aidl_clearkey_service_defaults",
+ vendor: true,
+
+ srcs: [
+ "CreatePluginFactories.cpp",
+ "CryptoPlugin.cpp",
+ "DrmFactory.cpp",
+ "DrmPlugin.cpp",
+ ],
+
+ relative_install_path: "hw",
+
+ cflags: ["-Wall", "-Werror", "-Wthread-safety"],
+
+ include_dirs: ["frameworks/av/include"],
local_include_dirs: ["include"],
@@ -49,7 +75,10 @@
cc_binary {
name: "android.hardware.drm-service.clearkey",
- defaults: ["aidl_clearkey_service_defaults"],
+ defaults: [
+ "aidl_clearkey_service_defaults",
+ "aidl_clearkey_service_defaults-use-shared-deps",
+ ],
srcs: ["Service.cpp"],
init_rc: ["android.hardware.drm-service.clearkey.rc"],
vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
@@ -57,17 +86,31 @@
cc_binary {
name: "android.hardware.drm-service-lazy.clearkey",
- defaults: ["aidl_clearkey_service_defaults"],
+ defaults: [
+ "aidl_clearkey_service_defaults",
+ "aidl_clearkey_service_defaults-use-shared-deps",
+ ],
overrides: ["android.hardware.drm-service.clearkey"],
srcs: ["ServiceLazy.cpp"],
init_rc: ["android.hardware.drm-service-lazy.clearkey.rc"],
vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
}
+cc_binary {
+ name: "android.hardware.drm-service.clearkey.apex",
+ stem: "android.hardware.drm-service.clearkey",
+ defaults: [
+ "aidl_clearkey_service_defaults",
+ "aidl_clearkey_service_defaults-use-static-deps",
+ ],
+ srcs: ["Service.cpp"],
+ installable: false, // installed in APEX
+}
+
phony {
name: "android.hardware.drm@latest-service.clearkey",
required: [
- "android.hardware.drm-service.clearkey",
+ "com.android.hardware.drm.clearkey",
],
}
@@ -123,3 +166,34 @@
],
},
}
+
+apex {
+ name: "com.android.hardware.drm.clearkey",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.key",
+ certificate: ":com.android.hardware.certificate",
+ vendor: true,
+ updatable: false,
+
+ binaries: [
+ "android.hardware.drm-service.clearkey.apex",
+ ],
+ prebuilts: [
+ "android.hardware.drm-service.clearkey.apex.rc",
+ "android.hardware.drm-service.clearkey.xml"
+ ],
+}
+
+prebuilt_etc {
+ name: "android.hardware.drm-service.clearkey.apex.rc",
+ src: "android.hardware.drm-service.clearkey.apex.rc",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "android.hardware.drm-service.clearkey.xml",
+ src: "android.hardware.drm-service.clearkey.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc
new file mode 100644
index 0000000..f4645b3
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc
@@ -0,0 +1,7 @@
+service vendor.drm-clearkey-service /apex/com.android.hardware.drm.clearkey/bin/hw/android.hardware.drm-service.clearkey
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh
+ interface aidl android.hardware.drm.IDrmFactory/clearkey
diff --git a/drm/mediadrm/plugins/clearkey/aidl/file_contexts b/drm/mediadrm/plugins/clearkey/aidl/file_contexts
new file mode 100644
index 0000000..e9e6ca2
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.drm-service(-lazy)?\.clearkey u:object_r:hal_drm_clearkey_aidl_exec:s0
diff --git a/drm/mediadrm/plugins/clearkey/aidl/manifest.json b/drm/mediadrm/plugins/clearkey/aidl/manifest.json
new file mode 100644
index 0000000..369dc21
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.drm.clearkey",
+ "version": 1
+}
diff --git a/media/aconfig/Android.bp b/media/aconfig/Android.bp
new file mode 100644
index 0000000..4b489e2
--- /dev/null
+++ b/media/aconfig/Android.bp
@@ -0,0 +1,16 @@
+aconfig_declarations {
+ name: "aconfig_mediacodec_flags",
+ package: "com.android.media.codec.flags",
+ srcs: ["mediacodec_flags.aconfig"],
+}
+
+java_aconfig_library {
+ name: "aconfig_mediacodec_flags_java_lib",
+ aconfig_declarations: "aconfig_mediacodec_flags",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+cc_aconfig_library {
+ name: "aconfig_mediacodec_flags_c_lib",
+ aconfig_declarations: "aconfig_mediacodec_flags",
+}
diff --git a/media/aconfig/mediacodec_flags.aconfig b/media/aconfig/mediacodec_flags.aconfig
new file mode 100644
index 0000000..67ba3e5
--- /dev/null
+++ b/media/aconfig/mediacodec_flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.media.codec.flags"
+
+flag {
+ name: "large_audio_frame"
+ namespace: "codec_fwk"
+ description: "Feature flags for large audio frame support"
+ bug: "297219557"
+}
diff --git a/media/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index b968c39..a6a6b77 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -6,6 +6,7 @@
// use libcodec2-aidl-client-defaults instead
cc_library {
name: "libcodec2_aidl_client",
+ min_sdk_version: "31",
srcs: [
"BufferTypes.cpp",
@@ -53,8 +54,8 @@
// use libcodec2-aidl-defaults instead
cc_library {
name: "libcodec2_aidl",
+ min_sdk_version: "31",
vendor_available: true,
- min_sdk_version: "34",
apex_available: [
"//apex_available:platform",
"com.android.media.swcodec",
@@ -131,11 +132,12 @@
// public dependency for Codec 2.0 HAL service implementations
cc_defaults {
name: "libcodec2-aidl-defaults",
- min_sdk_version: "34",
+ min_sdk_version: "31",
defaults: ["libcodec2-impl-defaults"],
shared_libs: [
"android.hardware.media.c2-V1-ndk",
+ "libbinder_ndk",
"libcodec2_aidl",
],
}
@@ -143,7 +145,7 @@
// public dependency for Codec 2.0 HAL client
cc_defaults {
name: "libcodec2-aidl-client-defaults",
- min_sdk_version: "34",
+ min_sdk_version: "31",
defaults: ["libcodec2-impl-defaults"],
shared_libs: [
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
index fa18c3e..9c21a5b 100644
--- a/media/codec2/hal/aidl/Component.cpp
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -301,7 +301,7 @@
switch (allocator.getTag()) {
case ALLOCATOR_ID:
#ifdef __ANDROID_APEX__
- status = CreateCodec2BlockPool(
+ status = ::android::CreateCodec2BlockPool(
static_cast<::android::C2PlatformAllocatorStore::id_t>(
allocator.get<ALLOCATOR_ID>()),
mComponent,
@@ -405,18 +405,22 @@
}
void Component::initListener(const std::shared_ptr<Component>& self) {
- std::shared_ptr<C2Component::Listener> c2listener =
- std::make_shared<Listener>(self);
- c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
- if (res != C2_OK) {
- mInit = res;
- }
+ if (__builtin_available(android __ANDROID_API_T__, *)) {
+ std::shared_ptr<C2Component::Listener> c2listener =
+ std::make_shared<Listener>(self);
+ c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
+ if (res != C2_OK) {
+ mInit = res;
+ }
- mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
- AIBinder_DeathRecipient_new(OnBinderDied));
- mDeathContext = new DeathContext{weak_from_this()};
- AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), OnBinderUnlinked);
- AIBinder_linkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
+ mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(OnBinderDied));
+ mDeathContext = new DeathContext{weak_from_this()};
+ AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), OnBinderUnlinked);
+ AIBinder_linkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
+ } else {
+ mInit = C2_NO_INIT;
+ }
}
// static
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
index 19734c0..2489683 100644
--- a/media/codec2/hal/aidl/ComponentStore.cpp
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -51,8 +51,11 @@
namespace c2 {
namespace utils {
+#ifndef __ANDROID_APEX__
using ::android::DefaultFilterPlugin;
using ::android::FilterWrapper;
+#endif
+
using ::ndk::ScopedAStatus;
namespace /* unnamed */ {
diff --git a/media/codec2/hal/client/GraphicBufferAllocator.cpp b/media/codec2/hal/client/GraphicBufferAllocator.cpp
index bbef1b5..7045537 100644
--- a/media/codec2/hal/client/GraphicBufferAllocator.cpp
+++ b/media/codec2/hal/client/GraphicBufferAllocator.cpp
@@ -62,14 +62,12 @@
return ::ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus GraphicBufferAllocator::getWaitableFds(
- IGraphicBufferAllocator::WaitableFds* _aidl_return) {
- int allocFd;
- int statusFd;
- c2_status_t ret = mGraphicsTracker->getWaitableFds(&allocFd, &statusFd);
+::ndk::ScopedAStatus GraphicBufferAllocator::getWaitableFd(
+ ::ndk::ScopedFileDescriptor* _aidl_return) {
+ int pipeFd;
+ c2_status_t ret = mGraphicsTracker->getWaitableFd(&pipeFd);
if (ret == C2_OK) {
- _aidl_return->allocEvent.set(allocFd);
- _aidl_return->statusEvent.set(statusFd);
+ _aidl_return->set(pipeFd);
return ::ndk::ScopedAStatus::ok();
}
return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
diff --git a/media/codec2/hal/client/GraphicsTracker.cpp b/media/codec2/hal/client/GraphicsTracker.cpp
index 5a2cb86..2424f7b 100644
--- a/media/codec2/hal/client/GraphicsTracker.cpp
+++ b/media/codec2/hal/client/GraphicsTracker.cpp
@@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <sys/eventfd.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <media/stagefright/foundation/ADebug.h>
#include <private/android/AHardwareBufferHelpers.h>
@@ -25,6 +26,9 @@
namespace {
+static constexpr int kMaxDequeueMin = 1;
+static constexpr int kMaxDequeueMax = ::android::BufferQueueDefs::NUM_BUFFER_SLOTS - 2;
+
c2_status_t retrieveAHardwareBufferId(const C2ConstGraphicBlock &blk, uint64_t *bid) {
// TODO
(void)blk;
@@ -139,21 +143,26 @@
mDequeueable{maxDequeueCount},
mTotalDequeued{0}, mTotalCancelled{0}, mTotalDropped{0}, mTotalReleased{0},
mInConfig{false}, mStopped{false} {
- if (maxDequeueCount <= 0) {
- mMaxDequeue = kDefaultMaxDequeue;
- mMaxDequeueRequested = kDefaultMaxDequeue;
- mMaxDequeueCommitted = kDefaultMaxDequeue;
- mDequeueable = kDefaultMaxDequeue;
+ if (maxDequeueCount < kMaxDequeueMin) {
+ mMaxDequeue = kMaxDequeueMin;
+ mMaxDequeueRequested = kMaxDequeueMin;
+ mMaxDequeueCommitted = kMaxDequeueMin;
+ mDequeueable = kMaxDequeueMin;
+ } else if(maxDequeueCount > kMaxDequeueMax) {
+ mMaxDequeue = kMaxDequeueMax;
+ mMaxDequeueRequested = kMaxDequeueMax;
+ mMaxDequeueCommitted = kMaxDequeueMax;
+ mDequeueable = kMaxDequeueMax;
}
- int allocEventFd = ::eventfd(mDequeueable, EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE);
- int statusEventFd = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
+ int pipefd[2] = { -1, -1};
+ int ret = ::pipe2(pipefd, O_CLOEXEC | O_NONBLOCK);
- mAllocEventFd.reset(allocEventFd);
- mStopEventFd.reset(statusEventFd);
+ mReadPipeFd.reset(pipefd[0]);
+ mWritePipeFd.reset(pipefd[1]);
mEventQueueThread = std::thread([this](){processEvent();});
- CHECK(allocEventFd >= 0 && statusEventFd >= 0);
+ CHECK(ret >= 0);
CHECK(mEventQueueThread.joinable());
}
@@ -161,7 +170,6 @@
stop();
if (mEventQueueThread.joinable()) {
std::unique_lock<std::mutex> l(mEventLock);
- mStopEventThread = true;
l.unlock();
mEventCv.notify_one();
mEventQueueThread.join();
@@ -231,6 +239,11 @@
c2_status_t GraphicsTracker::configureMaxDequeueCount(int maxDequeueCount) {
std::shared_ptr<BufferCache> cache;
+ if (maxDequeueCount < kMaxDequeueMin || maxDequeueCount > kMaxDequeueMax) {
+ ALOGE("max dequeue count %d is not valid", maxDequeueCount);
+ return C2_BAD_VALUE;
+ }
+
// max dequeue count which can be committed to IGBP.
// (Sometimes maxDequeueCount cannot be committed if the number of
// dequeued buffer count is bigger.)
@@ -347,89 +360,76 @@
void GraphicsTracker::stop() {
bool expected = false;
+ std::unique_lock<std::mutex> l(mEventLock);
bool updated = mStopped.compare_exchange_strong(expected, true);
if (updated) {
- uint64_t val = 1ULL;
- int ret = ::write(mStopEventFd.get(), &val, 8);
- if (ret < 0) {
- // EINTR maybe
- std::unique_lock<std::mutex> l(mEventLock);
- mStopRequest = true;
- l.unlock();
- mEventCv.notify_one();
- ALOGW("stop() status update pending");
- }
+ int writeFd = mWritePipeFd.release();
+ ::close(writeFd);
}
}
void GraphicsTracker::writeIncDequeueable(int inc) {
- uint64_t val = inc;
- int ret = ::write(mAllocEventFd.get(), &val, 8);
- if (ret < 0) {
- // EINTR due to signal handling maybe, this should be rare
+ CHECK(inc > 0 && inc < kMaxDequeueMax);
+ thread_local char buf[kMaxDequeueMax];
+ int diff = 0;
+ {
std::unique_lock<std::mutex> l(mEventLock);
- mIncDequeueable += inc;
- l.unlock();
- mEventCv.notify_one();
- ALOGW("updating dequeueable to eventfd pending");
+ 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");
+ }
}
}
void GraphicsTracker::processEvent() {
- // This is for write() failure of eventfds.
- // write() failure other than EINTR should not happen.
- int64_t acc = 0;
- bool stopRequest = false;
- bool stopCommitted = false;
-
+ // This is for partial/failed writes to the writing end.
+ // This may not happen in the real scenario.
+ thread_local char buf[kMaxDequeueMax];
while (true) {
- {
- std::unique_lock<std::mutex> l(mEventLock);
- acc += mIncDequeueable;
- mIncDequeueable = 0;
- stopRequest |= mStopRequest;
- mStopRequest = false;
- if (acc == 0 && stopRequest == stopCommitted) {
- if (mStopEventThread) {
- break;
+ 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);
}
- mEventCv.wait(l);
continue;
}
}
-
- if (acc > 0) {
- int ret = ::write(mAllocEventFd.get(), &acc, 8);
- if (ret > 0) {
- acc = 0;
- }
- }
- if (stopRequest && !stopCommitted) {
- uint64_t val = 1ULL;
- int ret = ::write(mStopEventFd.get(), &val, 8);
- if (ret > 0) {
- stopCommitted = true;
- }
- }
- if (mStopEventThread) {
- break;
- }
+ mEventCv.wait(l);
}
}
-c2_status_t GraphicsTracker::getWaitableFds(int *allocFd, int *statusFd) {
- *allocFd = ::dup(mAllocEventFd.get());
- *statusFd = ::dup(mStopEventFd.get());
-
- if (*allocFd < 0 || *statusFd < 0) {
- if (*allocFd >= 0) {
- ::close(*allocFd);
- *allocFd = -1;
+c2_status_t GraphicsTracker::getWaitableFd(int *pipeFd) {
+ *pipeFd = ::dup(mReadPipeFd.get());
+ if (*pipeFd < 0) {
+ if (mReadPipeFd.get() < 0) {
+ return C2_BAD_STATE;
}
- if (*statusFd >= 0) {
- ::close(*statusFd);
- *statusFd = -1;
- }
+ // dup error
+ ALOGE("dup() for the reading end failed %d", errno);
return C2_NO_MEMORY;
}
return C2_OK;
@@ -438,8 +438,8 @@
c2_status_t GraphicsTracker::requestAllocate(std::shared_ptr<BufferCache> *cache) {
std::lock_guard<std::mutex> l(mLock);
if (mDequeueable > 0) {
- uint64_t val;
- int ret = ::read(mAllocEventFd.get(), &val, 8);
+ char buf[1];
+ int ret = ::read(mReadPipeFd.get(), buf, 1);
if (ret < 0) {
if (errno == EINTR) {
// Do we really need to care for cancel due to signal handling?
@@ -452,6 +452,10 @@
}
CHECK(errno != 0);
}
+ if (ret == 0) {
+ // writing end is closed
+ return C2_BAD_STATE;
+ }
mDequeueable--;
*cache = mBufferCache;
return C2_OK;
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index accb9fd..e3f8b1c 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -1953,7 +1953,8 @@
std::shared_ptr<Codec2Client::Configurable>* configurable) {
if (mAidlBase) {
c2_aidl::IComponent::BlockPool aidlBlockPool;
- ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(id, &aidlBlockPool);
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(static_cast<int32_t>(id),
+ &aidlBlockPool);
c2_status_t status = GetC2Status(transStatus, "createBlockPool");
if (status != C2_OK) {
return status;
diff --git a/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
index f9c8aca..902c53f 100644
--- a/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
+++ b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
@@ -38,8 +38,8 @@
::ndk::ScopedAStatus deallocate(int64_t in_id, bool* _aidl_return) override;
- ::ndk::ScopedAStatus getWaitableFds(
- IGraphicBufferAllocator::WaitableFds* _aidl_return) override;
+ ::ndk::ScopedAStatus getWaitableFd(
+ ::ndk::ScopedFileDescriptor* _aidl_return) override;
/**
* Configuring Surface/BufferQueue for the interface.
diff --git a/media/codec2/hal/client/include/codec2/aidl/GraphicsTracker.h b/media/codec2/hal/client/include/codec2/aidl/GraphicsTracker.h
index 681b7e8..1fd9049 100644
--- a/media/codec2/hal/client/include/codec2/aidl/GraphicsTracker.h
+++ b/media/codec2/hal/client/include/codec2/aidl/GraphicsTracker.h
@@ -142,15 +142,15 @@
void onReleased(uint32_t generation);
/**
- * Get waitable fds for events.(allocate is ready, end of life cycle)
+ * Get waitable fd for events.(allocate is ready, end of life cycle)
*
- * @param[out] allocFd eventFd which signals being ready to allocate
- * @param[out] statusFd eventFd which signals end of life cycle.
- * When signaled no more allocate is possible.
+ * @param[out] pipeFd a file descriptor created from pipe2()
+ * in order for notifying being ready to allocate
+ *
* @return C2_OK
* C2_NO_MEMORY Max # of fd reached.(not really a memory issue)
*/
- c2_status_t getWaitableFds(int *allocFd, int *statusFd);
+ c2_status_t getWaitableFd(int *pipeFd);
/**
* Ends to use the class. after the call, allocate will fail.
@@ -158,8 +158,6 @@
void stop();
private:
- static constexpr int kDefaultMaxDequeue = 2;
-
struct BufferCache;
struct BufferItem {
@@ -246,21 +244,30 @@
std::mutex mLock; // locks for data synchronization
std::mutex mConfigLock; // locks for configuration change.
+ // NOTE: pipe2() creates two file descriptors for allocatable events
+ // and irrecoverable error events notification.
+ //
+ // A byte will be written to the writing end whenever a buffer is ready to
+ // dequeue/allocate. A byte will be read from the reading end whenever
+ // an allocate/dequeue event happens.
+ //
+ // The writing end will be closed when the end-of-lifecycle event was met.
+ //
+ // The reading end will be shared to the remote processes. Remote processes
+ // use ::poll() to check whether a buffer is ready to allocate/ready.
+ // Also ::poll() will let remote processes know the end-of-lifecycle event
+ // by returning POLLHUP event from the reading end.
+ ::android::base::unique_fd mReadPipeFd; // The reading end file descriptor
+ ::android::base::unique_fd mWritePipeFd; // The writing end file descriptor
+
std::atomic<bool> mStopped;
-
- ::android::base::unique_fd mAllocEventFd; // eventfd in semaphore mode which
- // mirrors mDqueueable.
- ::android::base::unique_fd mStopEventFd; // eventfd which indicates the life
- // cycle of the class being stopped.
-
std::thread mEventQueueThread; // Thread to handle interrupted
- // writes to eventfd{s}.
+ // writes to the writing end.
std::mutex mEventLock;
std::condition_variable mEventCv;
bool mStopEventThread;
int mIncDequeueable; // pending # of write to increase dequeueable eventfd
- bool mStopRequest; // pending write to statusfd
private:
explicit GraphicsTracker(int maxDequeueCount);
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 8305feb..db68b96 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
@@ -500,7 +500,7 @@
description("Encodes input file");
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- bool signalEOS = std::get<3>(GetParam());
+ bool signalEOS = std::get<2>(GetParam());
// Send an empty frame to receive CSD data from encoder.
bool sendEmptyFirstFrame = std::get<3>(GetParam());
mConfigBPictures = std::get<4>(GetParam());
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 385912a..22c4aee 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -2128,8 +2128,15 @@
if (notifyClient && !buffer && !flags) {
if (mTunneled && drop && outputFormat) {
- ALOGV("[%s] onWorkDone: Keep tunneled, drop frame with format change (%lld)",
- mName, work->input.ordinal.frameIndex.peekull());
+ if (mOutputFormat != outputFormat) {
+ ALOGV("[%s] onWorkDone: Keep tunneled, drop frame with format change (%lld)",
+ mName, work->input.ordinal.frameIndex.peekull());
+ mOutputFormat = outputFormat;
+ } else {
+ ALOGV("[%s] onWorkDone: Not reporting output buffer without format change (%lld)",
+ mName, work->input.ordinal.frameIndex.peekull());
+ notifyClient = false;
+ }
} else {
ALOGV("[%s] onWorkDone: Not reporting output buffer (%lld)",
mName, work->input.ordinal.frameIndex.peekull());
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 763eae9..a37c383 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -301,6 +301,7 @@
std::shared_ptr<C2BlockPool> mInputAllocator;
QueueSync mQueueSync;
std::vector<std::unique_ptr<C2Param>> mParamsToBeSet;
+ sp<AMessage> mOutputFormat;
struct Input {
Input();
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 0803dc3..fef465a 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -319,6 +319,450 @@
return C2_OK;
}
+static c2_status_t PopulatePlaneLayout(
+ buffer_handle_t buffer,
+ const Rect &rect,
+ uint32_t format,
+ uint64_t grallocUsage,
+ uint32_t stride,
+ C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
+ // 'NATIVE' on Android means LITTLE_ENDIAN
+ constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
+
+ // Try to resolve IMPLEMENTATION_DEFINED format to accurate format if
+ // possible.
+ uint32_t fourCc;
+ if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
+ !GraphicBufferMapper::get().getPixelFormatFourCC(buffer, &fourCc)) {
+ switch (fourCc) {
+ case DRM_FORMAT_XBGR8888:
+ format = static_cast<uint32_t>(PixelFormat4::RGBX_8888);
+ break;
+ case DRM_FORMAT_ABGR8888:
+ format = static_cast<uint32_t>(PixelFormat4::RGBA_8888);
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (format) {
+ case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
+ // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
+ // Surface. In all other cases it is RGBA. We don't know which case it is here, so
+ // default to YUV for now.
+ void *pointer = nullptr;
+ // TODO: fence
+ status_t err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(RGBA_1010102)");
+ return C2_CORRUPTED;
+ }
+ // treat as 32-bit values
+ addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
+ addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
+ addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
+ addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
+ layout->type = C2PlanarLayout::TYPE_YUVA;
+ layout->numPlanes = 4;
+ layout->rootPlanes = 1;
+ layout->planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y, // channel
+ 4, // colInc
+ static_cast<int32_t>(4 * stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 32, // allocatedDepth
+ 10, // bitDepth
+ 10, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB, // channel
+ 4, // colInc
+ static_cast<int32_t>(4 * stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 32, // allocatedDepth
+ 10, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR, // channel
+ 4, // colInc
+ static_cast<int32_t>(4 * stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 32, // allocatedDepth
+ 10, // bitDepth
+ 20, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_A] = {
+ C2PlaneInfo::CHANNEL_A, // channel
+ 4, // colInc
+ static_cast<int32_t>(4 * stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 32, // allocatedDepth
+ 2, // bitDepth
+ 30, // rightShift
+ C2PlaneInfo::LITTLE_END, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ break;
+ }
+
+ case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
+ // TODO: alpha channel
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
+ void *pointer = nullptr;
+ // TODO: fence
+ status_t err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t*>(buffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(RGBA_8888)");
+ return C2_CORRUPTED;
+ }
+ addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
+ addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
+ addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
+ layout->type = C2PlanarLayout::TYPE_RGB;
+ layout->numPlanes = 3;
+ layout->rootPlanes = 1;
+ layout->planes[C2PlanarLayout::PLANE_R] = {
+ C2PlaneInfo::CHANNEL_R, // channel
+ 4, // colInc
+ static_cast<int32_t>(4 * stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_R, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_G] = {
+ C2PlaneInfo::CHANNEL_G, // channel
+ 4, // colInc
+ static_cast<int32_t>(4 * stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_R, // rootIx
+ 1, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_B] = {
+ C2PlaneInfo::CHANNEL_B, // channel
+ 4, // colInc
+ static_cast<int32_t>(4 * stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_R, // rootIx
+ 2, // offset
+ };
+ break;
+ }
+
+ case static_cast<uint32_t>(PixelFormat4::BLOB): {
+ void *pointer = nullptr;
+ // TODO: fence
+ status_t err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t*>(buffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(BLOB)");
+ return C2_CORRUPTED;
+ }
+ *addr = (uint8_t *)pointer;
+ break;
+ }
+
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_422_SP):
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::YCRCB_420_SP):
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_422_I):
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
+ // fall-through
+ case static_cast<uint32_t>(PixelFormat4::YV12): {
+ android_ycbcr ycbcrLayout;
+
+ status_t err = GraphicBufferMapper::get().lockYCbCr(
+ const_cast<native_handle_t*>(buffer), grallocUsage, rect, &ycbcrLayout);
+ if (err) {
+ ALOGE("failed transaction: lockYCbCr (err=%d)", err);
+ return C2_CORRUPTED;
+ }
+ if (!ycbcrLayout.y || !ycbcrLayout.cb || !ycbcrLayout.cr
+ || ycbcrLayout.ystride == 0
+ || ycbcrLayout.cstride == 0
+ || ycbcrLayout.chroma_step == 0) {
+ ALOGE("invalid layout: lockYCbCr (y=%s cb=%s cr=%s "
+ "ystride=%zu cstride=%zu chroma_step=%zu)",
+ ycbcrLayout.y ? "(non-null)" : "(null)",
+ ycbcrLayout.cb ? "(non-null)" : "(null)",
+ ycbcrLayout.cr ? "(non-null)" : "(null)",
+ ycbcrLayout.ystride, ycbcrLayout.cstride, ycbcrLayout.chroma_step);
+ return C2_CORRUPTED;
+ }
+
+ addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
+ addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
+ addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
+ layout->type = C2PlanarLayout::TYPE_YUV;
+ layout->numPlanes = 3;
+ layout->rootPlanes = 3;
+ layout->planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y, // channel
+ 1, // colInc
+ (int32_t)ycbcrLayout.ystride, // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB, // channel
+ (int32_t)ycbcrLayout.chroma_step, // colInc
+ (int32_t)ycbcrLayout.cstride, // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR, // channel
+ (int32_t)ycbcrLayout.chroma_step, // colInc
+ (int32_t)ycbcrLayout.cstride, // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_V, // rootIx
+ 0, // offset
+ };
+ break;
+ }
+
+ case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
+ // In Android T, P010 is relaxed to allow arbitrary stride for the Y and UV planes,
+ // try locking with the gralloc4 mapper first.
+ c2_status_t status = Gralloc4Mapper_lock(
+ const_cast<native_handle_t*>(buffer), grallocUsage, rect, layout, addr);
+ if (status == C2_OK) {
+ break;
+ }
+
+ void *pointer = nullptr;
+ status_t err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(YCBCR_P010)");
+ return C2_CORRUPTED;
+ }
+ addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
+ addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer + stride * 2 * rect.height();
+ addr[C2PlanarLayout::PLANE_V] = addr[C2PlanarLayout::PLANE_U] + 2;
+ layout->type = C2PlanarLayout::TYPE_YUV;
+ layout->numPlanes = 3;
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y, // channel
+ 2, // colInc
+ static_cast<int32_t>(2 * stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ kEndianness, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB, // channel
+ 4, // colInc
+ static_cast<int32_t>(2 * stride), // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ kEndianness, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR, // channel
+ 4, // colInc
+ static_cast<int32_t>(2 * stride), // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 16, // allocatedDepth
+ 10, // bitDepth
+ 6, // rightShift
+ kEndianness, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 2, // offset
+ };
+ break;
+ }
+
+ default: {
+ // We don't know what it is, let's try to lock it with gralloc4
+ android_ycbcr ycbcrLayout;
+ if (isAtLeastT()) {
+ c2_status_t status = Gralloc4Mapper_lock(
+ const_cast<native_handle_t*>(buffer), grallocUsage, rect, layout, addr);
+ if (status == C2_OK) {
+ break;
+ }
+ }
+
+ // fallback to lockYCbCr
+ status_t err = GraphicBufferMapper::get().lockYCbCr(
+ const_cast<native_handle_t*>(buffer), grallocUsage, rect, &ycbcrLayout);
+ if (err == OK && ycbcrLayout.y && ycbcrLayout.cb && ycbcrLayout.cr
+ && ycbcrLayout.ystride > 0
+ && ycbcrLayout.cstride > 0
+ && ycbcrLayout.chroma_step > 0) {
+ addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
+ addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
+ addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
+ layout->type = C2PlanarLayout::TYPE_YUV;
+ layout->numPlanes = 3;
+ layout->rootPlanes = 3;
+ layout->planes[C2PlanarLayout::PLANE_Y] = {
+ C2PlaneInfo::CHANNEL_Y, // channel
+ 1, // colInc
+ (int32_t)ycbcrLayout.ystride, // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_Y, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_U] = {
+ C2PlaneInfo::CHANNEL_CB, // channel
+ (int32_t)ycbcrLayout.chroma_step, // colInc
+ (int32_t)ycbcrLayout.cstride, // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_U, // rootIx
+ 0, // offset
+ };
+ layout->planes[C2PlanarLayout::PLANE_V] = {
+ C2PlaneInfo::CHANNEL_CR, // channel
+ (int32_t)ycbcrLayout.chroma_step, // colInc
+ (int32_t)ycbcrLayout.cstride, // rowInc
+ 2, // mColSampling
+ 2, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ C2PlanarLayout::PLANE_V, // rootIx
+ 0, // offset
+ };
+ break;
+ }
+
+ // We really don't know what this is; lock the buffer and pass it through ---
+ // the client may know how to interpret it.
+
+ // unlock previous allocation if it was successful
+ if (err == OK) {
+ err = GraphicBufferMapper::get().unlock(buffer);
+ if (err) {
+ ALOGE("failed transaction: unlock");
+ return C2_CORRUPTED;
+ }
+ }
+
+ void *pointer = nullptr;
+ err = GraphicBufferMapper::get().lock(
+ const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
+ if (err) {
+ ALOGE("failed transaction: lock(??? %x)", format);
+ return C2_CORRUPTED;
+ }
+ addr[0] = (uint8_t *)pointer;
+ layout->type = C2PlanarLayout::TYPE_UNKNOWN;
+ layout->numPlanes = 1;
+ layout->rootPlanes = 1;
+ layout->planes[0] = {
+ // TODO: CHANNEL_UNKNOWN?
+ C2PlaneInfo::channel_t(0xFF), // channel
+ 1, // colInc
+ int32_t(stride), // rowInc
+ 1, // mColSampling
+ 1, // mRowSampling
+ 8, // allocatedDepth
+ 8, // bitDepth
+ 0, // rightShift
+ C2PlaneInfo::NATIVE, // endianness
+ 0, // rootIx
+ 0, // offset
+ };
+ break;
+ }
+ }
+ return C2_OK;
+}
+
+static void HandleInterleavedPlanes(
+ C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
+ if (layout->type == C2PlanarLayout::TYPE_YUV && layout->rootPlanes == 3) {
+ intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
+ intptr_t uvColInc = layout->planes[C2PlanarLayout::PLANE_U].colInc;
+ if (uvOffset > 0 && uvOffset < uvColInc) {
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
+ layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
+ } else if (uvOffset < 0 && uvOffset > -uvColInc) {
+ layout->rootPlanes = 2;
+ layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
+ layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
+ }
+ }
+}
+
} // unnamed namespace
@@ -476,440 +920,14 @@
mStride, generation, igbp_id, igbp_slot);
}
- // 'NATIVE' on Android means LITTLE_ENDIAN
- constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
-
- // Try to resolve IMPLEMENTATION_DEFINED format to accurate format if
- // possible.
- uint32_t format = mFormat;
- uint32_t fourCc;
- if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
- !GraphicBufferMapper::get().getPixelFormatFourCC(mBuffer, &fourCc)) {
- switch (fourCc) {
- case DRM_FORMAT_XBGR8888:
- format = static_cast<uint32_t>(PixelFormat4::RGBX_8888);
- break;
- case DRM_FORMAT_ABGR8888:
- format = static_cast<uint32_t>(PixelFormat4::RGBA_8888);
- break;
- default:
- break;
- }
- }
-
- switch (format) {
- case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
- // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
- // Surface. In all other cases it is RGBA. We don't know which case it is here, so
- // default to YUV for now.
- void *pointer = nullptr;
- // TODO: fence
- status_t err = GraphicBufferMapper::get().lock(
- const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
- if (err) {
- ALOGE("failed transaction: lock(RGBA_1010102)");
- return C2_CORRUPTED;
- }
- // treat as 32-bit values
- addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
- addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
- addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
- addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
- layout->type = C2PlanarLayout::TYPE_YUVA;
- layout->numPlanes = 4;
- layout->rootPlanes = 1;
- layout->planes[C2PlanarLayout::PLANE_Y] = {
- C2PlaneInfo::CHANNEL_Y, // channel
- 4, // colInc
- static_cast<int32_t>(4 * mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 32, // allocatedDepth
- 10, // bitDepth
- 10, // rightShift
- C2PlaneInfo::LITTLE_END, // endianness
- C2PlanarLayout::PLANE_Y, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_U] = {
- C2PlaneInfo::CHANNEL_CB, // channel
- 4, // colInc
- static_cast<int32_t>(4 * mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 32, // allocatedDepth
- 10, // bitDepth
- 0, // rightShift
- C2PlaneInfo::LITTLE_END, // endianness
- C2PlanarLayout::PLANE_Y, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_V] = {
- C2PlaneInfo::CHANNEL_CR, // channel
- 4, // colInc
- static_cast<int32_t>(4 * mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 32, // allocatedDepth
- 10, // bitDepth
- 20, // rightShift
- C2PlaneInfo::LITTLE_END, // endianness
- C2PlanarLayout::PLANE_Y, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_A] = {
- C2PlaneInfo::CHANNEL_A, // channel
- 4, // colInc
- static_cast<int32_t>(4 * mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 32, // allocatedDepth
- 2, // bitDepth
- 30, // rightShift
- C2PlaneInfo::LITTLE_END, // endianness
- C2PlanarLayout::PLANE_Y, // rootIx
- 0, // offset
- };
- break;
- }
-
- case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
- // TODO: alpha channel
- // fall-through
- case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
- void *pointer = nullptr;
- // TODO: fence
- status_t err = GraphicBufferMapper::get().lock(
- const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
- if (err) {
- ALOGE("failed transaction: lock(RGBA_8888)");
- return C2_CORRUPTED;
- }
- addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
- addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
- addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
- layout->type = C2PlanarLayout::TYPE_RGB;
- layout->numPlanes = 3;
- layout->rootPlanes = 1;
- layout->planes[C2PlanarLayout::PLANE_R] = {
- C2PlaneInfo::CHANNEL_R, // channel
- 4, // colInc
- static_cast<int32_t>(4 * mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_R, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_G] = {
- C2PlaneInfo::CHANNEL_G, // channel
- 4, // colInc
- static_cast<int32_t>(4 * mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_R, // rootIx
- 1, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_B] = {
- C2PlaneInfo::CHANNEL_B, // channel
- 4, // colInc
- static_cast<int32_t>(4 * mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_R, // rootIx
- 2, // offset
- };
- break;
- }
-
- case static_cast<uint32_t>(PixelFormat4::BLOB): {
- void *pointer = nullptr;
- // TODO: fence
- status_t err = GraphicBufferMapper::get().lock(
- const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
- if (err) {
- ALOGE("failed transaction: lock(BLOB)");
- return C2_CORRUPTED;
- }
- *addr = (uint8_t *)pointer;
- break;
- }
-
- case static_cast<uint32_t>(PixelFormat4::YCBCR_422_SP):
- // fall-through
- case static_cast<uint32_t>(PixelFormat4::YCRCB_420_SP):
- // fall-through
- case static_cast<uint32_t>(PixelFormat4::YCBCR_422_I):
- // fall-through
- case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
- // fall-through
- case static_cast<uint32_t>(PixelFormat4::YV12): {
- android_ycbcr ycbcrLayout;
-
- status_t err = GraphicBufferMapper::get().lockYCbCr(
- const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
- if (err) {
- ALOGE("failed transaction: lockYCbCr (err=%d)", err);
- return C2_CORRUPTED;
- }
- if (!ycbcrLayout.y || !ycbcrLayout.cb || !ycbcrLayout.cr
- || ycbcrLayout.ystride == 0
- || ycbcrLayout.cstride == 0
- || ycbcrLayout.chroma_step == 0) {
- ALOGE("invalid layout: lockYCbCr (y=%s cb=%s cr=%s "
- "ystride=%zu cstride=%zu chroma_step=%zu)",
- ycbcrLayout.y ? "(non-null)" : "(null)",
- ycbcrLayout.cb ? "(non-null)" : "(null)",
- ycbcrLayout.cr ? "(non-null)" : "(null)",
- ycbcrLayout.ystride, ycbcrLayout.cstride, ycbcrLayout.chroma_step);
- return C2_CORRUPTED;
- }
-
- addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
- addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
- addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
- layout->type = C2PlanarLayout::TYPE_YUV;
- layout->numPlanes = 3;
- layout->rootPlanes = 3;
- layout->planes[C2PlanarLayout::PLANE_Y] = {
- C2PlaneInfo::CHANNEL_Y, // channel
- 1, // colInc
- (int32_t)ycbcrLayout.ystride, // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_Y, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_U] = {
- C2PlaneInfo::CHANNEL_CB, // channel
- (int32_t)ycbcrLayout.chroma_step, // colInc
- (int32_t)ycbcrLayout.cstride, // rowInc
- 2, // mColSampling
- 2, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_U, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_V] = {
- C2PlaneInfo::CHANNEL_CR, // channel
- (int32_t)ycbcrLayout.chroma_step, // colInc
- (int32_t)ycbcrLayout.cstride, // rowInc
- 2, // mColSampling
- 2, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_V, // rootIx
- 0, // offset
- };
- break;
- }
-
- case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
- // In Android T, P010 is relaxed to allow arbitrary stride for the Y and UV planes,
- // try locking with the gralloc4 mapper first.
- c2_status_t status = Gralloc4Mapper_lock(
- const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
- if (status == C2_OK) {
- break;
- }
-
- void *pointer = nullptr;
- status_t err = GraphicBufferMapper::get().lock(
- const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
- if (err) {
- ALOGE("failed transaction: lock(YCBCR_P010)");
- return C2_CORRUPTED;
- }
- addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
- addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer + mStride * 2 * rect.height();
- addr[C2PlanarLayout::PLANE_V] = addr[C2PlanarLayout::PLANE_U] + 2;
- layout->type = C2PlanarLayout::TYPE_YUV;
- layout->numPlanes = 3;
- layout->rootPlanes = 2;
- layout->planes[C2PlanarLayout::PLANE_Y] = {
- C2PlaneInfo::CHANNEL_Y, // channel
- 2, // colInc
- static_cast<int32_t>(2 * mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 16, // allocatedDepth
- 10, // bitDepth
- 6, // rightShift
- kEndianness, // endianness
- C2PlanarLayout::PLANE_Y, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_U] = {
- C2PlaneInfo::CHANNEL_CB, // channel
- 4, // colInc
- static_cast<int32_t>(2 * mStride), // rowInc
- 2, // mColSampling
- 2, // mRowSampling
- 16, // allocatedDepth
- 10, // bitDepth
- 6, // rightShift
- kEndianness, // endianness
- C2PlanarLayout::PLANE_U, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_V] = {
- C2PlaneInfo::CHANNEL_CR, // channel
- 4, // colInc
- static_cast<int32_t>(2 * mStride), // rowInc
- 2, // mColSampling
- 2, // mRowSampling
- 16, // allocatedDepth
- 10, // bitDepth
- 6, // rightShift
- kEndianness, // endianness
- C2PlanarLayout::PLANE_U, // rootIx
- 2, // offset
- };
- break;
- }
-
- default: {
- // We don't know what it is, let's try to lock it with gralloc4
- android_ycbcr ycbcrLayout;
- if (isAtLeastT()) {
- c2_status_t status = Gralloc4Mapper_lock(
- const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
- if (status == C2_OK) {
- break;
- }
- }
-
- // fallback to lockYCbCr
- status_t err = GraphicBufferMapper::get().lockYCbCr(
- const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
- if (err == OK && ycbcrLayout.y && ycbcrLayout.cb && ycbcrLayout.cr
- && ycbcrLayout.ystride > 0
- && ycbcrLayout.cstride > 0
- && ycbcrLayout.chroma_step > 0) {
- addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
- addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
- addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
- layout->type = C2PlanarLayout::TYPE_YUV;
- layout->numPlanes = 3;
- layout->rootPlanes = 3;
- layout->planes[C2PlanarLayout::PLANE_Y] = {
- C2PlaneInfo::CHANNEL_Y, // channel
- 1, // colInc
- (int32_t)ycbcrLayout.ystride, // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_Y, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_U] = {
- C2PlaneInfo::CHANNEL_CB, // channel
- (int32_t)ycbcrLayout.chroma_step, // colInc
- (int32_t)ycbcrLayout.cstride, // rowInc
- 2, // mColSampling
- 2, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_U, // rootIx
- 0, // offset
- };
- layout->planes[C2PlanarLayout::PLANE_V] = {
- C2PlaneInfo::CHANNEL_CR, // channel
- (int32_t)ycbcrLayout.chroma_step, // colInc
- (int32_t)ycbcrLayout.cstride, // rowInc
- 2, // mColSampling
- 2, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- C2PlanarLayout::PLANE_V, // rootIx
- 0, // offset
- };
- break;
- }
-
- // We really don't know what this is; lock the buffer and pass it through ---
- // the client may know how to interpret it.
-
- // unlock previous allocation if it was successful
- if (err == OK) {
- err = GraphicBufferMapper::get().unlock(mBuffer);
- if (err) {
- ALOGE("failed transaction: unlock");
- return C2_CORRUPTED;
- }
- }
-
- void *pointer = nullptr;
- err = GraphicBufferMapper::get().lock(
- const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
- if (err) {
- ALOGE("failed transaction: lock(??? %x)", mFormat);
- return C2_CORRUPTED;
- }
- addr[0] = (uint8_t *)pointer;
- layout->type = C2PlanarLayout::TYPE_UNKNOWN;
- layout->numPlanes = 1;
- layout->rootPlanes = 1;
- layout->planes[0] = {
- // TODO: CHANNEL_UNKNOWN?
- C2PlaneInfo::channel_t(0xFF), // channel
- 1, // colInc
- int32_t(mStride), // rowInc
- 1, // mColSampling
- 1, // mRowSampling
- 8, // allocatedDepth
- 8, // bitDepth
- 0, // rightShift
- C2PlaneInfo::NATIVE, // endianness
- 0, // rootIx
- 0, // offset
- };
- break;
- }
+ c2_status_t ret = PopulatePlaneLayout(
+ mBuffer, rect, mFormat, grallocUsage, mStride, layout, addr);
+ if (ret != C2_OK) {
+ return ret;
}
mLocked = true;
- // handle interleaved formats
- if (layout->type == C2PlanarLayout::TYPE_YUV && layout->rootPlanes == 3) {
- intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
- intptr_t uvColInc = layout->planes[C2PlanarLayout::PLANE_U].colInc;
- if (uvOffset > 0 && uvOffset < uvColInc) {
- layout->rootPlanes = 2;
- layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
- layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
- } else if (uvOffset < 0 && uvOffset > -uvColInc) {
- layout->rootPlanes = 2;
- layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
- layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
- }
- }
+ HandleInterleavedPlanes(layout, addr);
ALOGV("C2AllocationGralloc::map: layout: type=%d numPlanes=%d rootPlanes=%d",
layout->type, layout->numPlanes, layout->rootPlanes);
diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp
index 0344fd3..b91ac6d 100644
--- a/media/codec2/vndk/C2Fence.cpp
+++ b/media/codec2/vndk/C2Fence.cpp
@@ -16,6 +16,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "C2FenceFactory"
+#include <poll.h>
+
+#include <android-base/unique_fd.h>
#include <cutils/native_handle.h>
#include <utils/Log.h>
#include <ui/Fence.h>
@@ -32,6 +35,7 @@
NULL_FENCE,
SURFACE_FENCE,
SYNC_FENCE,
+ PIPE_FENCE,
};
virtual c2_status_t wait(c2_nsecs_t timeoutNs) = 0;
@@ -353,6 +357,154 @@
return C2Fence(p);
}
+/**
+ * Fence implementation for notifying # of events available based on
+ * file descriptors created by pipe()/pipe2(). The writing end of the
+ * file descriptors is used to create the implementation.
+ * The implementation supports all C2Fence interface.
+ */
+class _C2FenceFactory::PipeFenceImpl: public C2Fence::Impl {
+private:
+ bool waitEvent(c2_nsecs_t timeoutNs, bool *hangUp, bool *event) const {
+ if (!mValid) {
+ *hangUp = true;
+ return true;
+ }
+
+ struct pollfd pfd;
+ pfd.fd = mPipeFd.get();
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+ struct timespec ts;
+ if (timeoutNs >= 0) {
+ ts.tv_sec = int(timeoutNs / 1000000000);
+ ts.tv_nsec = timeoutNs;
+ } else {
+ ALOGD("polling for indefinite duration requested, but changed to wait for %d sec",
+ kPipeFenceWaitLimitSecs);
+ ts.tv_sec = kPipeFenceWaitLimitSecs;
+ ts.tv_nsec = 0;
+ }
+ int ret = ::ppoll(&pfd, 1, &ts, nullptr);
+ if (ret >= 0) {
+ if (pfd.revents) {
+ if (pfd.revents & ~POLLIN) {
+ // Mostly this means the writing end fd was closed.
+ *hangUp = true;
+ mValid = false;
+ ALOGD("PipeFenceImpl: pipe fd hangup or err event returned");
+ }
+ *event = true;
+ return true;
+ }
+ // event not ready yet.
+ return true;
+ }
+ if (errno == EINTR) {
+ // poll() was cancelled by signal or inner kernel status.
+ return false;
+ }
+ // Since poll error happened here, treat the error is irrecoverable.
+ ALOGE("PipeFenceImpl: poll() error %d", errno);
+ *hangUp = true;
+ mValid = false;
+ return true;
+ }
+
+public:
+ virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
+ if (!mValid) {
+ return C2_BAD_STATE;
+ }
+ bool hangUp = false;
+ bool event = false;
+ if (waitEvent(timeoutNs, &hangUp, &event)) {
+ if (hangUp) {
+ return C2_BAD_STATE;
+ }
+ if (event) {
+ return C2_OK;
+ }
+ return C2_TIMED_OUT;
+ } else {
+ return C2_CANCELED;
+ }
+ }
+
+ virtual bool valid() const {
+ if (!mValid) {
+ return false;
+ }
+ bool hangUp = false;
+ bool event = false;
+ if (waitEvent(0, &hangUp, &event)) {
+ if (hangUp) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ virtual bool ready() const {
+ if (!mValid) {
+ return false;
+ }
+ bool hangUp = false;
+ bool event = false;
+ if (waitEvent(0, &hangUp, &event)) {
+ if (event) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual int fd() const {
+ if (!mValid) {
+ return -1;
+ }
+ return ::dup(mPipeFd.get());
+ }
+
+ virtual bool isHW() const {
+ return false;
+ }
+
+ virtual type_t type() const {
+ return PIPE_FENCE;
+ }
+
+ virtual native_handle_t *createNativeHandle() const {
+ // This is not supported.
+ return nullptr;
+ }
+
+ virtual ~PipeFenceImpl() = default;
+
+ PipeFenceImpl(int fd) : mPipeFd(fd) {
+ mValid = (mPipeFd.get() >= 0);
+ }
+
+private:
+ friend struct _C2FenceFactory;
+ static constexpr int kPipeFenceWaitLimitSecs = 5;
+
+ mutable std::atomic<bool> mValid;
+ ::android::base::unique_fd mPipeFd;
+};
+
+C2Fence _C2FenceFactory::CreatePipeFence(int fd) {
+ std::shared_ptr<_C2FenceFactory::PipeFenceImpl> impl =
+ std::make_shared<_C2FenceFactory::PipeFenceImpl>(fd);
+ std::shared_ptr<C2Fence::Impl> p = std::static_pointer_cast<C2Fence::Impl>(impl);
+ if (!p) {
+ ALOGE("PipeFence creation failure");
+ } else if (!impl->mValid) {
+ p.reset();
+ }
+ return C2Fence(p);
+}
+
native_handle_t* _C2FenceFactory::CreateNativeHandle(const C2Fence& fence) {
return fence.mImpl? fence.mImpl->createNativeHandle() : nullptr;
}
diff --git a/media/codec2/vndk/include/C2FenceFactory.h b/media/codec2/vndk/include/C2FenceFactory.h
index ef25c47..9b09980 100644
--- a/media/codec2/vndk/include/C2FenceFactory.h
+++ b/media/codec2/vndk/include/C2FenceFactory.h
@@ -39,6 +39,7 @@
class SurfaceFenceImpl;
class SyncFenceImpl;
+ class PipeFenceImpl;
/*
* Create C2Fence for BufferQueueBased blockpool.
@@ -66,6 +67,15 @@
*/
static C2Fence CreateMultipleFdSyncFence(const std::vector<int>& fenceFds);
+ /*
+ * Create C2Fence from an fd created by pipe()/pipe2() syscall.
+ *
+ * \param fd An fd representing the write end from a pair of
+ * file descriptors which are created by
+ * pipe()/pipe2() syscall.
+ */
+ static C2Fence CreatePipeFence(int fd);
+
/**
* Create a native handle from fence for marshalling
*
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 1e8dcca..5b90158 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -114,7 +114,6 @@
"libnblog",
"libprocessgroup",
"libshmemcompat",
- "libxml2",
"mediametricsservice-aidl-cpp",
"packagemanager_aidl-cpp",
"shared-file-region-aidl-cpp",
diff --git a/media/libaudioclient/tests/audio_test_utils.cpp b/media/libaudioclient/tests/audio_test_utils.cpp
index 1e26ff6..ee5489b 100644
--- a/media/libaudioclient/tests/audio_test_utils.cpp
+++ b/media/libaudioclient/tests/audio_test_utils.cpp
@@ -26,25 +26,10 @@
#define WAIT_PERIOD_MS 10 // from AudioTrack.cpp
#define MAX_WAIT_TIME_MS 5000
-template <class T>
-constexpr void (*xmlDeleter)(T* t);
-template <>
-constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
-template <>
-constexpr auto xmlDeleter<xmlChar> = [](xmlChar* s) { xmlFree(s); };
-
-/** @return a unique_ptr with the correct deleter for the libxml2 object. */
-template <class T>
-constexpr auto make_xmlUnique(T* t) {
- // Wrap deleter in lambda to enable empty base optimization
- auto deleter = [](T* t) { xmlDeleter<T>(t); };
- return std::unique_ptr<T, decltype(deleter)>{t, deleter};
-}
-
void OnAudioDeviceUpdateNotifier::onAudioDeviceUpdate(audio_io_handle_t audioIo,
audio_port_handle_t deviceId) {
std::unique_lock<std::mutex> lock{mMutex};
- ALOGD("%s audioIo=%d deviceId=%d", __func__, audioIo, deviceId);
+ ALOGI("%s: audioIo=%d deviceId=%d", __func__, audioIo, deviceId);
mAudioIo = audioIo;
mDeviceId = deviceId;
mCondition.notify_all();
@@ -727,184 +712,17 @@
}
std::string dumpPortConfig(const audio_port_config& port) {
- std::ostringstream result;
- std::string deviceInfo;
- if (port.type == AUDIO_PORT_TYPE_DEVICE) {
- if (port.ext.device.type & AUDIO_DEVICE_BIT_IN) {
- InputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
- } else {
- OutputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
- }
- deviceInfo += std::string(", address = ") + port.ext.device.address;
- }
- result << "audio_port_handle_t = " << port.id << ", "
- << "Role = " << (port.role == AUDIO_PORT_ROLE_SOURCE ? "source" : "sink") << ", "
- << "Type = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix") << ", "
- << "deviceInfo = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? deviceInfo : "") << ", "
- << "config_mask = 0x" << std::hex << port.config_mask << std::dec << ", ";
- if (port.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
- result << "sample rate = " << port.sample_rate << ", ";
- }
- if (port.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
- result << "channel mask = " << port.channel_mask << ", ";
- }
- if (port.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
- result << "format = " << port.format << ", ";
- }
- result << "input flags = " << port.flags.input << ", ";
- result << "output flags = " << port.flags.output << ", ";
- result << "mix io handle = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? 0 : port.ext.mix.handle)
- << "\n";
- return result.str();
+ auto aidlPortConfig = legacy2aidl_audio_port_config_AudioPortConfigFw(port);
+ return aidlPortConfig.ok() ? aidlPortConfig.value().toString()
+ : "Error while converting audio port config to AIDL";
}
std::string dumpPatch(const audio_patch& patch) {
- std::ostringstream result;
- result << "----------------- Dumping Patch ------------ \n";
- result << "Patch Handle: " << patch.id << ", sources: " << patch.num_sources
- << ", sink: " << patch.num_sinks << "\n";
- audio_port_v7 port;
- for (uint32_t i = 0; i < patch.num_sources; i++) {
- result << "----------------- Dumping Source Port Config @ index " << i
- << " ------------ \n";
- result << dumpPortConfig(patch.sources[i]);
- result << "----------------- Dumping Source Port for id " << patch.sources[i].id
- << " ------------ \n";
- getPortById(patch.sources[i].id, port);
- result << dumpPort(port);
- }
- for (uint32_t i = 0; i < patch.num_sinks; i++) {
- result << "----------------- Dumping Sink Port Config @ index " << i << " ------------ \n";
- result << dumpPortConfig(patch.sinks[i]);
- result << "----------------- Dumping Sink Port for id " << patch.sinks[i].id
- << " ------------ \n";
- getPortById(patch.sinks[i].id, port);
- result << dumpPort(port);
- }
- return result.str();
+ auto aidlPatch = legacy2aidl_audio_patch_AudioPatchFw(patch);
+ return aidlPatch.ok() ? aidlPatch.value().toString() : "Error while converting patch to AIDL";
}
std::string dumpPort(const audio_port_v7& port) {
- std::ostringstream result;
- std::string deviceInfo;
- if (port.type == AUDIO_PORT_TYPE_DEVICE) {
- if (port.ext.device.type & AUDIO_DEVICE_BIT_IN) {
- InputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
- } else {
- OutputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
- }
- deviceInfo += std::string(", address = ") + port.ext.device.address;
- }
- result << "audio_port_handle_t = " << port.id << ", "
- << "Role = " << (port.role == AUDIO_PORT_ROLE_SOURCE ? "source" : "sink") << ", "
- << "Type = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix") << ", "
- << "deviceInfo = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? deviceInfo : "") << ", "
- << "Name = " << port.name << ", "
- << "num profiles = " << port.num_audio_profiles << ", "
- << "mix io handle = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? 0 : port.ext.mix.handle)
- << ", ";
- for (int i = 0; i < port.num_audio_profiles; i++) {
- result << "AudioProfile = " << i << " {";
- result << "format = " << port.audio_profiles[i].format << ", ";
- result << "samplerates = ";
- for (int j = 0; j < port.audio_profiles[i].num_sample_rates; j++) {
- result << port.audio_profiles[i].sample_rates[j] << ", ";
- }
- result << "channelmasks = ";
- for (int j = 0; j < port.audio_profiles[i].num_channel_masks; j++) {
- result << "0x" << std::hex << port.audio_profiles[i].channel_masks[j] << std::dec
- << ", ";
- }
- result << "} ";
- }
- result << dumpPortConfig(port.active_config);
- return result.str();
-}
-
-std::string getXmlAttribute(const xmlNode* cur, const char* attribute) {
- auto charPtr = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
- if (charPtr == NULL) {
- return "";
- }
- std::string value(reinterpret_cast<const char*>(charPtr.get()));
- return value;
-}
-
-status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
- std::vector<MixPort>& mixPorts,
- std::vector<Route>& routes) {
- std::string path = audio_find_readable_configuration_file("audio_policy_configuration.xml");
- if (path.length() == 0) return UNKNOWN_ERROR;
- auto doc = make_xmlUnique(xmlParseFile(path.c_str()));
- if (doc == nullptr) return UNKNOWN_ERROR;
- xmlNode* root = xmlDocGetRootElement(doc.get());
- if (root == nullptr) return UNKNOWN_ERROR;
- if (xmlXIncludeProcess(doc.get()) < 0) return UNKNOWN_ERROR;
- mixPorts.clear();
- if (!xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>("audioPolicyConfiguration"))) {
- std::string raw{getXmlAttribute(root, "version")};
- for (auto* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
- if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("modules"))) {
- xmlNode* root = child;
- for (auto* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
- if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("module"))) {
- xmlNode* root = child;
- for (auto* child = root->xmlChildrenNode; child != nullptr;
- child = child->next) {
- if (!xmlStrcmp(child->name,
- reinterpret_cast<const xmlChar*>("mixPorts"))) {
- xmlNode* root = child;
- for (auto* child = root->xmlChildrenNode; child != nullptr;
- child = child->next) {
- if (!xmlStrcmp(child->name,
- reinterpret_cast<const xmlChar*>("mixPort"))) {
- MixPort mixPort;
- xmlNode* root = child;
- mixPort.name = getXmlAttribute(root, "name");
- mixPort.role = getXmlAttribute(root, "role");
- mixPort.flags = getXmlAttribute(root, "flags");
- if (mixPort.role == "source") mixPorts.push_back(mixPort);
- }
- }
- } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(
- "attachedDevices"))) {
- xmlNode* root = child;
- for (auto* child = root->xmlChildrenNode; child != nullptr;
- child = child->next) {
- if (!xmlStrcmp(child->name,
- reinterpret_cast<const xmlChar*>("item"))) {
- auto xmlValue = make_xmlUnique(xmlNodeListGetString(
- child->doc, child->xmlChildrenNode, 1));
- if (xmlValue == nullptr) {
- raw = "";
- } else {
- raw = reinterpret_cast<const char*>(xmlValue.get());
- }
- std::string& value = raw;
- attachedDevices.push_back(std::move(value));
- }
- }
- } else if (!xmlStrcmp(child->name,
- reinterpret_cast<const xmlChar*>("routes"))) {
- xmlNode* root = child;
- for (auto* child = root->xmlChildrenNode; child != nullptr;
- child = child->next) {
- if (!xmlStrcmp(child->name,
- reinterpret_cast<const xmlChar*>("route"))) {
- Route route;
- xmlNode* root = child;
- route.name = getXmlAttribute(root, "name");
- route.sources = getXmlAttribute(root, "sources");
- route.sink = getXmlAttribute(root, "sink");
- routes.push_back(route);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return OK;
+ auto aidlPort = legacy2aidl_audio_port_v7_AudioPortFw(port);
+ return aidlPort.ok() ? aidlPort.value().toString() : "Error while converting port to AIDL";
}
diff --git a/media/libaudioclient/tests/audio_test_utils.h b/media/libaudioclient/tests/audio_test_utils.h
index 90c30c2..76e4642 100644
--- a/media/libaudioclient/tests/audio_test_utils.h
+++ b/media/libaudioclient/tests/audio_test_utils.h
@@ -28,8 +28,6 @@
#include <thread>
#include <binder/MemoryDealer.h>
-#include <libxml/parser.h>
-#include <libxml/xinclude.h>
#include <media/AidlConversion.h>
#include <media/AudioRecord.h>
#include <media/AudioTrack.h>
@@ -48,9 +46,6 @@
std::string sink;
};
-status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
- std::vector<MixPort>& mixPorts,
- std::vector<Route>& routes);
status_t listAudioPorts(std::vector<audio_port_v7>& portsVec);
status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec);
status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
diff --git a/media/libaudioclient/tests/audiorouting_tests.cpp b/media/libaudioclient/tests/audiorouting_tests.cpp
index 19d1abc..fa990b5 100644
--- a/media/libaudioclient/tests/audiorouting_tests.cpp
+++ b/media/libaudioclient/tests/audiorouting_tests.cpp
@@ -15,10 +15,13 @@
*/
//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioRoutingTest"
+#include <string.h>
+
+#include <binder/ProcessState.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
-#include <string.h>
#include "audio_test_utils.h"
@@ -63,12 +66,16 @@
EXPECT_NE(0, ap->getAudioTrackHandle()->getFlags() & output_flags[i]);
audio_patch patch;
EXPECT_EQ(OK, getPatchForOutputMix(cb->mAudioIo, patch));
- for (auto j = 0; j < patch.num_sources; j++) {
- if (patch.sources[j].type == AUDIO_PORT_TYPE_MIX &&
- patch.sources[j].ext.mix.handle == cb->mAudioIo) {
- if ((patch.sources[j].flags.output & output_flags[i]) == 0) {
- ADD_FAILURE() << "expected output flag " << output_flags[i] << " is absent";
- std::cerr << dumpPortConfig(patch.sources[j]);
+ if (output_flags[i] != AUDIO_OUTPUT_FLAG_FAST) {
+ // A "normal" output can still have a FastMixer, depending on the buffer size.
+ // Thus, a fast track can be created on a mix port which does not have the FAST flag.
+ for (auto j = 0; j < patch.num_sources; j++) {
+ if (patch.sources[j].type == AUDIO_PORT_TYPE_MIX &&
+ patch.sources[j].ext.mix.handle == cb->mAudioIo) {
+ SCOPED_TRACE(dumpPortConfig(patch.sources[j]));
+ EXPECT_NE(0, patch.sources[j].flags.output & output_flags[i])
+ << "expected output flag "
+ << audio_output_flag_to_string(output_flags[i]) << " is absent";
}
}
}
@@ -259,3 +266,25 @@
captureA->stop();
playback->stop();
}
+
+class TestExecutionTracer : public ::testing::EmptyTestEventListener {
+ public:
+ void OnTestStart(const ::testing::TestInfo& test_info) override {
+ TraceTestState("Started", test_info);
+ }
+ void OnTestEnd(const ::testing::TestInfo& test_info) override {
+ TraceTestState("Completed", test_info);
+ }
+
+ private:
+ static void TraceTestState(const std::string& state, const ::testing::TestInfo& test_info) {
+ ALOGI("%s %s::%s", state.c_str(), test_info.test_suite_name(), test_info.name());
+ }
+};
+
+int main(int argc, char** argv) {
+ android::ProcessState::self()->startThreadPool();
+ ::testing::InitGoogleTest(&argc, argv);
+ ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
+ return RUN_ALL_TESTS();
+}
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index b09a379..2869ca4 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -615,28 +615,37 @@
android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
const android::media::audio::common::AudioPort& port) {
+ // Point-to-point connections do not use addresses.
+ static const std::set<std::string> kPointToPointConnections = {
+ AudioDeviceDescription::CONNECTION_ANALOG(), AudioDeviceDescription::CONNECTION_HDMI(),
+ AudioDeviceDescription::CONNECTION_HDMI_ARC(),
+ AudioDeviceDescription::CONNECTION_HDMI_EARC(),
+ AudioDeviceDescription::CONNECTION_SPDIF()};
static int nextId = 0;
using Tag = AudioDeviceAddress::Tag;
+ const auto& deviceDescription = port.ext.get<AudioPortExt::Tag::device>().device.type;
AudioDeviceAddress address;
- switch (suggestDeviceAddressTag(port.ext.get<AudioPortExt::Tag::device>().device.type)) {
- case Tag::id:
- address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
- break;
- case Tag::mac:
- address = AudioDeviceAddress::make<Tag::mac>(
- std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
- break;
- case Tag::ipv4:
- address = AudioDeviceAddress::make<Tag::ipv4>(
- std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
- break;
- case Tag::ipv6:
- address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
- 0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
- break;
- case Tag::alsa:
- address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
- break;
+ if (kPointToPointConnections.count(deviceDescription.connection) == 0) {
+ switch (suggestDeviceAddressTag(deviceDescription)) {
+ case Tag::id:
+ address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
+ break;
+ case Tag::mac:
+ address = AudioDeviceAddress::make<Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
+ break;
+ case Tag::ipv4:
+ address = AudioDeviceAddress::make<Tag::ipv4>(
+ std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
+ break;
+ case Tag::ipv6:
+ address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
+ 0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
+ break;
+ case Tag::alsa:
+ address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
+ break;
+ }
}
android::media::audio::common::AudioPort result = port;
result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 362f373..131684c 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -1080,6 +1080,7 @@
"%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
__func__, mInstance.c_str(), connectedPort.toString().c_str(),
it->second.toString().c_str());
+ mConnectedPorts[connectedPort.id] = false;
} else { // !connected
AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
auto portsIt = findPort(matchDevice);
@@ -1099,10 +1100,11 @@
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mModule->disconnectExternalDevice(portId)));
mPorts.erase(portsIt);
+ mConnectedPorts.erase(portId);
} else {
ALOGD("%s: since device port ID %d is used by a stream, "
"external device disconnection postponed", __func__, portId);
- mConnectedPortIdsHeldByStreams.insert(portId);
+ mConnectedPorts[portId] = true;
}
}
return updateRoutes();
@@ -1601,8 +1603,25 @@
} else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
return mPorts.find(mDefaultOutputPortId);
}
- return std::find_if(mPorts.begin(), mPorts.end(),
- [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+ if (device.address.getTag() != AudioDeviceAddress::id ||
+ !device.address.get<AudioDeviceAddress::id>().empty()) {
+ return std::find_if(mPorts.begin(), mPorts.end(),
+ [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+ }
+ // For connection w/o an address, two ports can be found: the template port,
+ // and a connected port (if exists). Make sure we return the connected port.
+ DeviceHalAidl::Ports::iterator portIt = mPorts.end();
+ for (auto it = mPorts.begin(); it != mPorts.end(); ++it) {
+ if (audioDeviceMatches(device, it->second)) {
+ if (mConnectedPorts.find(it->first) != mConnectedPorts.end()) {
+ return it;
+ } else {
+ // Will return 'it' if there is no connected port.
+ portIt = it;
+ }
+ }
+ }
+ return portIt;
}
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
@@ -1765,7 +1784,8 @@
std::set<int32_t> retryDeviceDisconnection;
for (const auto& portConfigAndIdPair : portConfigIds) {
resetPortConfig(portConfigAndIdPair.first);
- if (mConnectedPortIdsHeldByStreams.count(portConfigAndIdPair.second) != 0) {
+ if (const auto it = mConnectedPorts.find(portConfigAndIdPair.second);
+ it != mConnectedPorts.end() && it->second) {
retryDeviceDisconnection.insert(portConfigAndIdPair.second);
}
}
@@ -1774,7 +1794,7 @@
TIME_CHECK();
if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
mPorts.erase(portId);
- mConnectedPortIdsHeldByStreams.erase(portId);
+ mConnectedPorts.erase(portId);
ALOGD("%s: executed postponed external device disconnection for port ID %d",
__func__, portId);
}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 329adba..da96d80 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -187,6 +187,8 @@
Status status = Status::UNKNOWN;
MicrophoneInfoProvider::Info info;
};
+ // IDs of ports for connected external devices, and whether they are held by streams.
+ using ConnectedPorts = std::map<int32_t /*port ID*/, bool>;
using Patches = std::map<int32_t /*patch ID*/,
::aidl::android::hardware::audio::core::AudioPatch>;
using PortConfigs = std::map<int32_t /*port config ID*/,
@@ -313,7 +315,7 @@
std::mutex mLock;
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
- std::set<int32_t> mConnectedPortIdsHeldByStreams;
+ ConnectedPorts mConnectedPorts;
};
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index aecbba7..196b432 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -255,37 +255,37 @@
status_t EffectConversionHelperAidl::handleReset(uint32_t cmdSize __unused,
const void* pCmdData __unused, uint32_t* replySize,
void* pReplyData) {
- if (!replySize || !pReplyData) {
+ if (!replySize || *replySize != sizeof(int) || !pReplyData) {
ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
- return statusTFromBinderStatus(mEffect->command(CommandId::RESET));
+ return *(int *)pReplyData = statusTFromBinderStatus(mEffect->command(CommandId::RESET));
}
status_t EffectConversionHelperAidl::handleEnable(uint32_t cmdSize __unused,
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
- if (!replySize || !pReplyData) {
+ if (!replySize || *replySize != sizeof(int) || !pReplyData) {
ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
- return statusTFromBinderStatus(mEffect->command(CommandId::START));
+ return *(int *)pReplyData = statusTFromBinderStatus(mEffect->command(CommandId::START));
}
status_t EffectConversionHelperAidl::handleDisable(uint32_t cmdSize __unused,
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
- if (!replySize || !pReplyData) {
+ if (!replySize || *replySize != sizeof(int) || !pReplyData) {
ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
- return statusTFromBinderStatus(mEffect->command(CommandId::STOP));
+ return *(int *)pReplyData = statusTFromBinderStatus(mEffect->command(CommandId::STOP));
}
status_t EffectConversionHelperAidl::handleSetAudioSource(uint32_t cmdSize, const void* pCmdData,
@@ -477,7 +477,7 @@
efGroup);
status = (status == OK) ? BAD_VALUE : status;
}
- } else if (isBypassingOrOffload()) {
+ } else if (isBypassingOrTunnel()) {
// for effect with bypass (no processing) or offloadIndication flag, it's okay to not have
// statusQ
return OK;
@@ -487,8 +487,8 @@
return status;
}
-bool EffectConversionHelperAidl::isBypassingOrOffload() const {
- return isBypassing() || isOffload();
+bool EffectConversionHelperAidl::isBypassingOrTunnel() const {
+ return isBypassing() || isTunnel();
}
bool EffectConversionHelperAidl::isBypassing() const {
@@ -497,10 +497,10 @@
(mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
}
-bool EffectConversionHelperAidl::isOffload() const {
+bool EffectConversionHelperAidl::isTunnel() const {
return mEffect &&
- (mDesc.common.flags.offloadIndication ||
- (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isOffload()));
+ (mDesc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL ||
+ (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isTunnel()));
}
Descriptor EffectConversionHelperAidl::getDescriptor() const {
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index b2ef155..5db334c 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -43,8 +43,8 @@
std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
bool isBypassing() const;
- bool isOffload() const;
- bool isBypassingOrOffload() const;
+ bool isTunnel() const;
+ bool isBypassingOrTunnel() const;
::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 642d352..f26444c 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -173,7 +173,7 @@
mConversion->isBypassing()
? "bypassing"
: aidl::android::hardware::audio::effect::toString(state).c_str());
- return OK;
+ return -ENODATA;
}
auto statusQ = mConversion->getStatusMQ();
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 4d7db4c..1099b6d 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -278,8 +278,9 @@
return mSubEffects[mActiveSubIdx].descriptor.common.flags.bypass;
}
-bool EffectProxy::isOffload() const {
- return mSubEffects[mActiveSubIdx].descriptor.common.flags.offloadIndication;
+bool EffectProxy::isTunnel() const {
+ return mSubEffects[mActiveSubIdx].descriptor.common.flags.hwAcceleratorMode ==
+ Flags::HardwareAccelerator::TUNNEL;
}
binder_status_t EffectProxy::dump(int fd, const char** args, uint32_t numArgs) {
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
index e14eb8a..0d62642 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -98,7 +98,7 @@
}
bool isBypassing() const;
- bool isOffload() const;
+ bool isTunnel() const;
// call dump for all sub-effects
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index c058386..e74fc16 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -193,7 +193,7 @@
StreamDescriptor::Reply reply;
switch (state) {
case StreamDescriptor::State::ACTIVE:
- if (status_t status = pause(&reply); status != OK) return status;
+ RETURN_STATUS_IF_ERROR(pause(&reply));
if (reply.state != StreamDescriptor::State::PAUSED) {
ALOGE("%s: unexpected stream state: %s (expected PAUSED)",
__func__, toString(reply.state).c_str());
@@ -203,7 +203,7 @@
case StreamDescriptor::State::PAUSED:
case StreamDescriptor::State::DRAIN_PAUSED:
if (mIsInput) return flush();
- if (status_t status = flush(&reply); status != OK) return status;
+ RETURN_STATUS_IF_ERROR(flush(&reply));
if (reply.state != StreamDescriptor::State::IDLE) {
ALOGE("%s: unexpected stream state: %s (expected IDLE)",
__func__, toString(reply.state).c_str());
@@ -211,10 +211,8 @@
}
FALLTHROUGH_INTENDED;
case StreamDescriptor::State::IDLE:
- if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
- &reply, true /*safeFromNonWorkerThread*/); status != OK) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
+ &reply, true /*safeFromNonWorkerThread*/));
if (reply.state != StreamDescriptor::State::STANDBY) {
ALOGE("%s: unexpected stream state: %s (expected STANDBY)",
__func__, toString(reply.state).c_str());
@@ -244,10 +242,7 @@
const auto state = getState();
StreamDescriptor::Reply reply;
if (state == StreamDescriptor::State::STANDBY) {
- if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true);
- status != OK) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true));
return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), &reply, true);
}
@@ -264,10 +259,7 @@
ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
if (!mStream) return NO_INIT;
StreamDescriptor::Reply reply;
- if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
- return status;
- }
-
+ RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
*latency = std::clamp(std::max<int32_t>(0, reply.latencyMs), 1, 3000);
ALOGW_IF(reply.latencyMs != static_cast<int32_t>(*latency),
"Suspicious latency value reported by HAL: %d, clamped to %u", reply.latencyMs,
@@ -279,11 +271,9 @@
ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
if (!mStream) return NO_INIT;
StreamDescriptor::Reply reply;
- if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
- return status;
- }
- *frames = reply.observable.frames;
- *timestamp = reply.observable.timeNs;
+ RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
+ *frames = std::max<int64_t>(0, reply.observable.frames);
+ *timestamp = std::max<int64_t>(0, reply.observable.timeNs);
return OK;
}
@@ -292,12 +282,9 @@
if (!mStream) return NO_INIT;
StreamDescriptor::Reply reply;
// TODO: switch to updateCountersIfNeeded once we sort out mWorkerTid initialization
- if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), &reply, true);
- status != OK) {
- return status;
- }
- *frames = reply.hardware.frames;
- *timestamp = reply.hardware.timeNs;
+ RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), &reply, true));
+ *frames = std::max<int64_t>(0, reply.hardware.frames);
+ *timestamp = std::max<int64_t>(0, reply.hardware.timeNs);
return OK;
}
@@ -305,10 +292,8 @@
ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
if (!mStream) return NO_INIT;
StreamDescriptor::Reply reply;
- if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
- return status;
- }
- *frames = reply.xrunFrames;
+ RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
+ *frames = std::max<int32_t>(0, reply.xrunFrames);
return OK;
}
@@ -323,10 +308,7 @@
// stream state), however this scenario wasn't supported by the HIDL HAL.
if (getState() == StreamDescriptor::State::STANDBY) {
StreamDescriptor::Reply reply;
- if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply);
- status != OK) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply));
if (reply.state != StreamDescriptor::State::IDLE) {
ALOGE("%s: failed to get the stream out of standby, actual state: %s",
__func__, toString(reply.state).c_str());
@@ -345,9 +327,7 @@
}
}
StreamDescriptor::Reply reply;
- if (status_t status = sendCommand(burst, &reply); status != OK) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(sendCommand(burst, &reply));
*transferred = reply.fmqByteCount;
if (mIsInput) {
LOG_ALWAYS_FATAL_IF(*transferred > bytes,
@@ -385,11 +365,8 @@
if (state == StreamDescriptor::State::IDLE) {
StreamDescriptor::Reply localReply{};
StreamDescriptor::Reply* innerReply = reply ?: &localReply;
- if (status_t status =
- sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply);
- status != OK) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(
+ sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply));
if (innerReply->state != StreamDescriptor::State::ACTIVE) {
ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
__func__, toString(innerReply->state).c_str());
@@ -452,10 +429,7 @@
return BAD_VALUE;
}
int64_t aidlPosition = 0, aidlTimestamp = 0;
- if (status_t status = getHardwarePosition(&aidlPosition, &aidlTimestamp); status != OK) {
- return status;
- }
-
+ RETURN_STATUS_IF_ERROR(getHardwarePosition(&aidlPosition, &aidlTimestamp));
position->time_nanoseconds = aidlTimestamp;
position->position_frames = static_cast<int32_t>(aidlPosition);
return OK;
@@ -503,6 +477,11 @@
}
{
std::lock_guard l(mLock);
+ // Not every command replies with 'latencyMs' field filled out, substitute the last
+ // returned value in that case.
+ if (reply->latencyMs <= 0) {
+ reply->latencyMs = mLastReply.latencyMs;
+ }
mLastReply = *reply;
}
switch (reply->status) {
@@ -608,10 +587,8 @@
return BAD_VALUE;
}
int64_t aidlFrames = 0, aidlTimestamp = 0;
- if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
- return OK;
- }
- *dspFrames = std::clamp<int64_t>(aidlFrames, 0, UINT32_MAX);
+ RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp));
+ *dspFrames = static_cast<uint32_t>(aidlFrames);
return OK;
}
@@ -680,10 +657,8 @@
return BAD_VALUE;
}
int64_t aidlFrames = 0, aidlTimestamp = 0;
- if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
- return status;
- }
- *frames = std::max<int64_t>(0, aidlFrames);
+ RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp));
+ *frames = aidlFrames;
timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND;
timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND;
return OK;
@@ -901,9 +876,7 @@
return BAD_VALUE;
}
int32_t aidlXruns = 0;
- if (status_t status = getXruns(&aidlXruns); status != OK) {
- return status;
- }
+ RETURN_STATUS_IF_ERROR(getXruns(&aidlXruns));
*framesLost = std::max<int32_t>(0, aidlXruns);
return OK;
}
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 3b369bd..4acc6ac 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -207,10 +207,13 @@
status_t getLatency(uint32_t *latency);
+ // Always returns non-negative values.
status_t getObservablePosition(int64_t *frames, int64_t *timestamp);
+ // Always returns non-negative values.
status_t getHardwarePosition(int64_t *frames, int64_t *timestamp);
+ // Always returns non-negative values.
status_t getXruns(int32_t *frames);
status_t transfer(void *buffer, size_t bytes, size_t *transferred);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 8be9c48..5c9f68e 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1609,23 +1609,21 @@
mFramesInput++;
}
- const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
- BufferFlightTiming_t startdata = { presentationUs, nowNs };
+ // mutex access to mBuffersInFlight and other stats
+ Mutex::Autolock al(mLatencyLock);
- {
- // mutex access to mBuffersInFlight and other stats
- Mutex::Autolock al(mLatencyLock);
-
-
- // XXX: we *could* make sure that the time is later than the end of queue
- // as part of a consistency check...
+ // XXX: we *could* make sure that the time is later than the end of queue
+ // as part of a consistency check...
+ if (!mTunneled) {
+ const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ BufferFlightTiming_t startdata = { presentationUs, nowNs };
mBuffersInFlight.push_back(startdata);
-
- if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
- mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
- }
- ++mInputBufferCounter;
}
+
+ if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
+ mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
+ }
+ ++mInputBufferCounter;
}
// when we get a buffer back from the codec
diff --git a/media/libstagefright/tests/HEVC/AndroidTest.xml b/media/libstagefright/tests/HEVC/AndroidTest.xml
index 00bb3e5..8c7bb91 100644
--- a/media/libstagefright/tests/HEVC/AndroidTest.xml
+++ b/media/libstagefright/tests/HEVC/AndroidTest.xml
@@ -34,6 +34,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="HEVCUtilsUnitTest" />
- <option name="native-test-flag" value="-P /sdcard/tests/HEVCUtilsUnitTest-1.0/" />
+ <option name="native-test-flag" value="-P /sdcard/test/HEVCUtilsUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/libstagefright/timedtext/test/AndroidTest.xml b/media/libstagefright/timedtext/test/AndroidTest.xml
index 0d5d79f..b536059 100644
--- a/media/libstagefright/timedtext/test/AndroidTest.xml
+++ b/media/libstagefright/timedtext/test/AndroidTest.xml
@@ -34,6 +34,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="TimedTextUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/TimedTextUnitTest-1.0/" />
+ <option name="native-test-flag" value="-P /sdcard/test/TimedTextUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
index 2016b2a..fee5c94 100644
--- a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
+++ b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
@@ -226,7 +226,13 @@
mediaBuffer->add_ref();
// This pushBuffer will wait until the mediaBuffer is consumed.
- if (currentTrack->pushBuffer(mediaBuffer) != OK) {
+ android::status_t pushStatus = currentTrack->pushBuffer(mediaBuffer);
+
+ if (pushStatus != OK) {
+ if (pushStatus == INVALID_OPERATION) {
+ // In Case of INVALID_OPERATION, mObserver needs to be set before calling release()
+ mediaBuffer->setObserver(currentTrack.get());
+ }
mediaBuffer->release();
}
}
diff --git a/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
index e5983e4..fba4230 100644
--- a/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
+++ b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
@@ -17,6 +17,7 @@
#include "fuzzer/FuzzedDataProvider.h"
#include <C2Config.h>
#include <C2Param.h>
+#include <android/api-level.h>
using namespace std;
@@ -59,11 +60,31 @@
if (!store) {
return;
}
- android::sp<V1_1::IComponentStore> storeV1_1 =
+
+ int32_t platformVersion = android_get_device_api_level();
+ if (platformVersion >= __ANDROID_API_S__) {
+ android::sp<V1_2::IComponentStore> storeV1_2 =
+ new V1_2::utils::ComponentStore(store);
+ if (storeV1_2->registerAsService(string(kServiceName)) != android::OK) {
+ return;
+ }
+ } else if (platformVersion == __ANDROID_API_R__) {
+ android::sp<V1_1::IComponentStore> storeV1_1 =
new V1_1::utils::ComponentStore(store);
- if (storeV1_1->registerAsService(string(kServiceName)) != android::OK) {
+ if (storeV1_1->registerAsService(string(kServiceName)) != android::OK) {
+ return;
+ }
+ } else if (platformVersion == __ANDROID_API_Q__) {
+ android::sp<V1_0::IComponentStore> storeV1_0 =
+ new V1_0::utils::ComponentStore(store);
+ if (storeV1_0->registerAsService(string(kServiceName)) != android::OK) {
+ return;
+ }
+ }
+ else {
return;
}
+
string const preferredStoreName = string(kServiceName);
sp<IComponentStore> preferredStore =
IComponentStore::getService(preferredStoreName.c_str());
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
index 8f8ad4e..86979f4 100644
--- a/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
@@ -615,7 +615,7 @@
}
void CustomCsvReporter::PrintRunData(const Run& run) {
- if (run.error_occurred) {
+ if (run.skipped) {
return;
}
std::ostream& Out = GetOutputStream();
diff --git a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
index 8aafe33..6377195 100644
--- a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
+++ b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -40,7 +41,7 @@
}
void MtpMockDatabase::addObject(MtpObjectInfo* info) {
- assert(hasStorage(info->storageID));
+ assert(hasStorage(info->mStorageID));
// we take ownership
mObjects.push_back(info);
diff --git a/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
index 83c6076..635c7a4 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
@@ -17,6 +17,7 @@
#include <MtpDataPacket.h>
#include <MtpDevHandle.h>
#include <MtpPacketFuzzerUtils.h>
+#include <functional>
#include <fuzzer/FuzzedDataProvider.h>
#include <utils/String16.h>
diff --git a/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
index c32d28a..d34eae0 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
@@ -23,6 +23,7 @@
#include <MtpStringBuffer.h>
#include <android-base/unique_fd.h>
#include <fcntl.h>
+#include <functional>
#include <fuzzer/FuzzedDataProvider.h>
#include <linux/usb/ch9.h>
#include <sys/mman.h>
diff --git a/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp
index 3bd3be2..c00b4ca 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp
@@ -17,6 +17,7 @@
#include <MtpDevHandle.h>
#include <MtpEventPacket.h>
#include <MtpPacketFuzzerUtils.h>
+#include <functional>
#include <fuzzer/FuzzedDataProvider.h>
using namespace android;
diff --git a/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
index 6fc2a96..d1836e7 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
@@ -17,7 +17,9 @@
#include <MtpDevHandle.h>
#include <MtpPacket.h>
#include <MtpPacketFuzzerUtils.h>
+#include <functional>
#include <fuzzer/FuzzedDataProvider.h>
+#include <mtp.h>
using namespace android;
@@ -35,7 +37,8 @@
};
void MtpPacketFuzzer::process() {
- MtpPacket mtpPacket(mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)); /*bufferSize*/
+ MtpPacket mtpPacket(mFdp.ConsumeIntegralInRange<size_t>(MTP_CONTAINER_HEADER_SIZE,
+ kMaxSize)); /*bufferSize*/
while (mFdp.remaining_bytes() > 0) {
auto mtpPacketAPI = mFdp.PickValueInArray<const std::function<void()>>({
[&]() {
diff --git a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
index 6300256..7a657c0 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
@@ -18,6 +18,7 @@
#include <MtpDevHandle.h>
#include <MtpPacketFuzzerUtils.h>
#include <MtpProperty.h>
+#include <functional>
#include <fuzzer/FuzzedDataProvider.h>
#include <utils/String16.h>
diff --git a/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp
index 19fbc5b..3b2fae2 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp
@@ -17,8 +17,9 @@
#include <MtpDevHandle.h>
#include <MtpPacketFuzzerUtils.h>
#include <MtpRequestPacket.h>
-#include <fuzzer/FuzzedDataProvider.h>
#include <fstream>
+#include <functional>
+#include <fuzzer/FuzzedDataProvider.h>
using namespace android;
diff --git a/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp
index 697785f..a841d2f 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp
@@ -17,6 +17,7 @@
#include <MtpDevHandle.h>
#include <MtpPacketFuzzerUtils.h>
#include <MtpResponsePacket.h>
+#include <functional>
#include <fuzzer/FuzzedDataProvider.h>
using namespace android;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index bbfe763..dfe3157 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -825,7 +825,10 @@
if (mStatus != NO_ERROR || mEffectInterface == 0) {
return;
}
- mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, 0, NULL);
+
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, &replySize, &reply);
}
status_t AudioFlinger::EffectModule::configure()
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ad8cdb9..daf3f39 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -452,9 +452,9 @@
status_t AudioPolicyManager::deviceToAudioPort(audio_devices_t device, const char* device_address,
const char* device_name,
media::AudioPortFw* aidlPort) {
- DeviceDescriptorBase devDescr(device, device_address);
- devDescr.setName(device_name);
- return devDescr.writeToParcelable(aidlPort);
+ const auto devDescr = sp<DeviceDescriptorBase>::make(device, device_address);
+ devDescr->setName(device_name);
+ return devDescr->writeToParcelable(aidlPort);
}
void AudioPolicyManager::setEngineDeviceConnectionState(const sp<DeviceDescriptor> device,
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 98298ea..7f3130e 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -86,6 +86,7 @@
};
#define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0)
+#define CAMERA_DEVICE_API_VERSION_1_2 HARDWARE_DEVICE_API_VERSION(1, 2)
#define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0)
#define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1)
#define CAMERA_DEVICE_API_VERSION_3_2 HARDWARE_DEVICE_API_VERSION(3, 2)
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4198b71..4344902 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -51,6 +51,7 @@
#include <cutils/properties.h>
#include <camera/StringUtils.h>
+#include <android-base/properties.h>
#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
@@ -749,8 +750,7 @@
auto firstRequest = requestList->begin();
for (auto& outputStream : (*firstRequest)->mOutputStreams) {
if (outputStream->isVideoStream()) {
- (*firstRequest)->mBatchSize = requestList->size();
- outputStream->setBatchSize(requestList->size());
+ applyMaxBatchSizeLocked(requestList, outputStream);
break;
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d7cfa94..7243fc0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -656,6 +656,15 @@
status_t initializeCommonLocked();
/**
+ * Update capture request list so that each batch size honors the batch_size_max report from
+ * the HAL. Set the batch size to output stream for buffer operations.
+ *
+ * Must be called with mLock held.
+ */
+ virtual void applyMaxBatchSizeLocked(
+ RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) = 0;
+
+ /**
* Get the last request submitted to the hal by the request thread.
*
* Must be called with mLock held.
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index 1f9313e..1f2ac23 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -51,6 +51,7 @@
#include <aidl/android/hardware/camera/device/ICameraInjectionSession.h>
#include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/properties.h>
#include <android/binder_ibinder_platform.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
#include <camera/StringUtils.h>
@@ -309,6 +310,20 @@
}
}
+ // batch size limit is applied to the device with camera device version larger than 3.2 which is
+ // AIDL v2
+ hardware::hidl_version maxVersion{0, 0};
+ IPCTransport transport = IPCTransport::AIDL;
+ res = manager->getHighestSupportedVersion(mId, &maxVersion, &transport);
+ if (res != OK) {
+ ALOGE("%s: Error in getting camera device version id: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+ int deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
+
+ mBatchSizeLimitEnabled = (deviceVersion >= CAMERA_DEVICE_API_VERSION_1_2);
+
return initializeCommonLocked();
}
@@ -1572,6 +1587,66 @@
return OK;
}
+void AidlCamera3Device::applyMaxBatchSizeLocked(
+ RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) {
+ int batchSize = requestList->size();
+
+ if (!mBatchSizeLimitEnabled) {
+ (*requestList->begin())->mBatchSize = batchSize;
+ stream->setBatchSize(batchSize);
+ return;
+ }
+
+ const auto& metadata = (*requestList->begin())->mSettingsList.begin()->metadata;
+
+ uint32_t tag = ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS;
+ auto sensorPixelModeEntry = metadata.find(ANDROID_SENSOR_PIXEL_MODE);
+ if (sensorPixelModeEntry.count != 0) {
+ if (ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION == sensorPixelModeEntry.data.u8[0]) {
+ tag = ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION;
+ }
+ }
+
+ const auto fpsRange = metadata.find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE);
+ if (fpsRange.count > 1) {
+ auto configEntry = mDeviceInfo.find(tag);
+ for (size_t index = 4; index < configEntry.count; index += 5) {
+ if (stream->getWidth() == static_cast<uint32_t>(configEntry.data.i32[index - 4]) &&
+ stream->getHeight() == static_cast<uint32_t>(configEntry.data.i32[index - 3]) &&
+ fpsRange.data.i32[0] == configEntry.data.i32[index - 2] &&
+ fpsRange.data.i32[1] == configEntry.data.i32[index - 1]) {
+ const int maxBatchSize = configEntry.data.i32[index - 1] / 30;
+ const int reportedSize = configEntry.data.i32[index];
+
+ if (maxBatchSize % reportedSize == 0 && requestList->size() % reportedSize == 0) {
+ batchSize = reportedSize;
+ ALOGVV("Matching high speed configuration found. Limit batch size to %d",
+ batchSize);
+ } else if (maxBatchSize % reportedSize == 0 &&
+ reportedSize % requestList->size() == 0) {
+ ALOGVV("Matching high speed configuration found, but requested batch size is "
+ "divisor of batch_size_max. No need to limit batch size.");
+ } else {
+ ALOGW("Matching high speed configuration found, but batch_size_max is not a "
+ "divisor of corresponding fps_max/30 or requested batch size is not a "
+ "divisor of batch_size_max, (fps_max %d, batch_size_max %d, requested "
+ "batch size %zu)",
+ configEntry.data.i32[index - 1], reportedSize, requestList->size());
+ }
+ break;
+ }
+ }
+ }
+
+ for (auto request = requestList->begin(); request != requestList->end(); request++) {
+ if (requestList->distance(requestList->begin(), request) % batchSize == 0) {
+ (*request)->mBatchSize = batchSize;
+ }
+ }
+
+ stream->setBatchSize(batchSize);
+}
+
status_t AidlCamera3Device::injectionCameraInitialize(const std::string &injectedCamId,
sp<CameraProviderManager> manager) {
return (static_cast<AidlCamera3DeviceInjectionMethods *>
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index f4554d4..4d7d139 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -252,6 +252,10 @@
};
private:
+ virtual void applyMaxBatchSizeLocked(
+ RequestList* requestList,
+ const sp<camera3::Camera3OutputStreamInterface>& stream) override;
+
virtual status_t injectionCameraInitialize(const std::string &injectCamId,
sp<CameraProviderManager> manager) override;
@@ -271,6 +275,9 @@
std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks = nullptr;
+ // Whether the batch_size_max field in the high speed configuration actually applied to
+ // capture requests.
+ bool mBatchSizeLimitEnabled = false;
}; // class AidlCamera3Device
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index c22aad6..d234d83 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -699,6 +699,14 @@
// Java side to make sure the CameraCaptureSession is properly closed
}
+void HidlCamera3Device::applyMaxBatchSizeLocked(
+ RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) {
+ int batchSize = requestList->size();
+
+ (*requestList->begin())->mBatchSize = batchSize;
+ stream->setBatchSize(batchSize);
+}
+
sp<Camera3Device::RequestThread> HidlCamera3Device::createNewRequestThread(
wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker,
sp<Camera3Device::HalInterface> interface,
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index e64bcf0..2d33277 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -213,6 +213,10 @@
hardware::Return<void> notifyHelper(
const hardware::hidl_vec<NotifyMsgType>& msgs);
+ virtual void applyMaxBatchSizeLocked(
+ RequestList* requestList,
+ const sp<camera3::Camera3OutputStreamInterface>& stream) override;
+
virtual status_t injectionCameraInitialize(const std::string &injectCamId,
sp<CameraProviderManager> manager) override;