Deprecate AImageReader_getWindowNativeHandle am: 5f86662a67
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/24642003
Change-Id: If70190077324a03a302ec8f012fd83515095e1ed
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 35b8e21..6b040ab 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -245,7 +245,7 @@
ALOGV("getParameters");
String8 params;
sp <::android::hardware::ICamera> c = mCamera;
- if (c != 0) params = mCamera->getParameters();
+ if (c != 0) params = c->getParameters();
return params;
}
@@ -269,7 +269,7 @@
ALOGV("setPreviewCallbackFlags");
sp <::android::hardware::ICamera> c = mCamera;
if (c == 0) return;
- mCamera->setPreviewCallbackFlag(flag);
+ c->setPreviewCallbackFlag(flag);
}
status_t Camera::setPreviewCallbackTarget(
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 365ac5c..61c7551 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -400,7 +400,6 @@
camera_metadata_ro_entry rawEntry = static_cast<const CameraMetadata*>(mData.get())->find(tag);
if (rawEntry.count == 0) {
- ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
return ACAMERA_ERROR_METADATA_NOT_FOUND;
}
entry->tag = tag;
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/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index b19f78c..b968c39 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -50,100 +50,95 @@
}
// DO NOT DEPEND ON THIS DIRECTLY
-// use libcodec2-hidl-defaults instead
-//cc_library {
-// name: "libcodec2_hidl@1.0",
-// vendor_available: true,
-// min_sdk_version: "29",
-// apex_available: [
-// "//apex_available:platform",
-// "com.android.media.swcodec",
-// ],
-//
-// defaults: ["hidl_defaults"],
-//
-// srcs: [
-// "Component.cpp",
-// "ComponentInterface.cpp",
-// "ComponentStore.cpp",
-// "Configurable.cpp",
-// "InputBufferManager.cpp",
-// "InputSurface.cpp",
-// "InputSurfaceConnection.cpp",
-// "types.cpp",
-// ],
-//
-// header_libs: [
-// "libbinder_headers",
-// "libcodec2_hal_common",
-// "libcodec2_internal", // private
-// "libsystem_headers",
-// ],
-//
-// shared_libs: [
-// "android.hardware.graphics.bufferqueue@1.0",
-// "android.hardware.graphics.bufferqueue@2.0",
-// "android.hardware.graphics.common@1.0",
-// "android.hardware.media@1.0",
-// "android.hardware.media.bufferpool@2.0",
-// "android.hardware.media.c2@1.0",
-// "android.hardware.media.omx@1.0",
-// "libbase",
-// "libcodec2",
-// "libcodec2_vndk",
-// "libcodec2_hidl_plugin_stub",
-// "libcutils",
-// "libhidlbase",
-// "liblog",
-// "libstagefright_bufferpool@2.0.1",
-// "libstagefright_bufferqueue_helper_novndk",
-// "libui",
-// "libutils",
-// ],
-//
-// target: {
-// vendor: {
-// exclude_shared_libs: [
-// "libstagefright_bufferqueue_helper_novndk",
-// "libcodec2_hidl_plugin_stub",
-// ],
-// shared_libs: [
-// "libstagefright_bufferqueue_helper",
-// "libcodec2_hidl_plugin",
-// ],
-// },
-// apex: {
-// exclude_shared_libs: [
-// "libcodec2_hidl_plugin",
-// "libcodec2_hidl_plugin_stub",
-// ],
-// },
-// },
-//
-// export_include_dirs: [
-// "include",
-// ],
-//
-// export_shared_lib_headers: [
-// "android.hardware.media.c2@1.0",
-// "libcodec2",
-// "libcodec2_vndk",
-// "libhidlbase",
-// "libstagefright_bufferpool@2.0.1",
-// "libui",
-// ],
-//}
-//
-//// public dependency for Codec 2.0 HAL service implementations
-//cc_defaults {
-// name: "libcodec2-hidl-defaults@1.0",
-// defaults: ["libcodec2-impl-defaults"],
-//
-// shared_libs: [
-// "android.hardware.media.c2@1.0",
-// "libcodec2_hidl@1.0",
-// ],
-//}
+// use libcodec2-aidl-defaults instead
+cc_library {
+ name: "libcodec2_aidl",
+ vendor_available: true,
+ min_sdk_version: "34",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
+
+ srcs: [
+ "BufferTypes.cpp",
+ "Component.cpp",
+ "ComponentInterface.cpp",
+ "ComponentStore.cpp",
+ "Configurable.cpp",
+ "InputBufferManager.cpp",
+ "ParamTypes.cpp",
+ ],
+
+ header_libs: [
+ "libcodec2_internal", // private
+ ],
+
+ shared_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.media.bufferpool2-V1-ndk",
+ "android.hardware.media.c2-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "libcodec2",
+ "libcodec2_hal_common",
+ "libcodec2_hidl_plugin_stub",
+ "libcodec2_vndk",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libnativewindow",
+ "libstagefright_aidl_bufferpool2",
+ "libstagefright_bufferpool@2.0.1",
+ "libui",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libaidlcommonsupport",
+ ],
+
+ target: {
+ vendor: {
+ exclude_shared_libs: [
+ "libcodec2_hidl_plugin_stub",
+ ],
+ shared_libs: [
+ "libcodec2_hidl_plugin",
+ ],
+ },
+ apex: {
+ exclude_shared_libs: [
+ "libcodec2_hidl_plugin_stub",
+ "libcodec2_hidl_plugin",
+ ],
+ },
+ },
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ export_shared_lib_headers: [
+ "android.hardware.media.c2-V1-ndk",
+ "libcodec2",
+ "libstagefright_bufferpool@2.0.1",
+ "libui",
+ ],
+}
+
+// public dependency for Codec 2.0 HAL service implementations
+cc_defaults {
+ name: "libcodec2-aidl-defaults",
+ min_sdk_version: "34",
+ defaults: ["libcodec2-impl-defaults"],
+
+ shared_libs: [
+ "android.hardware.media.c2-V1-ndk",
+ "libcodec2_aidl",
+ ],
+}
// public dependency for Codec 2.0 HAL client
cc_defaults {
@@ -156,3 +151,28 @@
"libcodec2_aidl_client",
],
}
+
+cc_fuzz {
+ name: "libcodec2-aidl-fuzzer",
+ vendor: true,
+ srcs: [
+ "fuzzer.cpp",
+ ],
+ defaults: [
+ "libcodec2-aidl-defaults",
+ "service_fuzzer_defaults",
+ ],
+ shared_libs: [
+ "libcodec2_vndk",
+
+ "libcodec2_soft_avcdec",
+ "libcodec2_soft_avcenc",
+ "libcodec2_soft_aacdec",
+ "libcodec2_soft_aacenc",
+ ],
+ fuzz_config: {
+ cc: [
+ "wonsik@google.com",
+ ],
+ },
+}
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
new file mode 100644
index 0000000..fa18c3e
--- /dev/null
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -0,0 +1,449 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-Component-Aidl"
+#include <android-base/logging.h>
+
+#include <codec2/aidl/Component.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/InputBufferManager.h>
+
+#ifndef __ANDROID_APEX__
+#include <FilterWrapper.h>
+#endif
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <utils/Timers.h>
+
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::media::bufferpool2::IClientManager;
+using ::ndk::ScopedAStatus;
+
+// ComponentListener wrapper
+struct Component::Listener : public C2Component::Listener {
+
+ Listener(const std::shared_ptr<Component>& component) :
+ mComponent(component),
+ mListener(component->mListener) {
+ }
+
+ virtual void onError_nb(
+ std::weak_ptr<C2Component> /* c2component */,
+ uint32_t errorCode) override {
+ std::shared_ptr<IComponentListener> listener = mListener.lock();
+ if (listener) {
+ ScopedAStatus transStatus = listener->onError(Status{Status::OK}, errorCode);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "Component::Listener::onError_nb -- "
+ << "transaction failed.";
+ }
+ }
+ }
+
+ virtual void onTripped_nb(
+ std::weak_ptr<C2Component> /* c2component */,
+ std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
+ ) override {
+ std::shared_ptr<IComponentListener> listener = mListener.lock();
+ if (listener) {
+ std::vector<SettingResult> settingResults(c2settingResult.size());
+ size_t ix = 0;
+ for (const std::shared_ptr<C2SettingResult> &c2result :
+ c2settingResult) {
+ if (c2result) {
+ if (!ToAidl(&settingResults[ix++], *c2result)) {
+ break;
+ }
+ }
+ }
+ settingResults.resize(ix);
+ ScopedAStatus transStatus = listener->onTripped(settingResults);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "Component::Listener::onTripped_nb -- "
+ << "transaction failed.";
+ }
+ }
+ }
+
+ virtual void onWorkDone_nb(
+ std::weak_ptr<C2Component> /* c2component */,
+ std::list<std::unique_ptr<C2Work>> c2workItems) override {
+ for (const std::unique_ptr<C2Work>& work : c2workItems) {
+ if (work) {
+ if (work->worklets.empty()
+ || !work->worklets.back()
+ || (work->worklets.back()->output.flags &
+ C2FrameData::FLAG_INCOMPLETE) == 0) {
+ InputBufferManager::
+ unregisterFrameData(mListener, work->input);
+ }
+ }
+ }
+
+ std::shared_ptr<IComponentListener> listener = mListener.lock();
+ if (listener) {
+ WorkBundle workBundle;
+
+ std::shared_ptr<Component> strongComponent = mComponent.lock();
+ // TODO
+ // beginTransferBufferQueueBlocks(c2workItems, true);
+ if (!ToAidl(&workBundle, c2workItems, strongComponent ?
+ &strongComponent->mBufferPoolSender : nullptr)) {
+ LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+ << "received corrupted work items.";
+ // TODO
+ // endTransferBufferQueueBlocks(c2workItems, false, true);
+ return;
+ }
+ ScopedAStatus transStatus = listener->onWorkDone(workBundle);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+ << "transaction failed.";
+ // TODO
+ // endTransferBufferQueueBlocks(c2workItems, false, true);
+ return;
+ }
+ // TODO
+ // endTransferBufferQueueBlocks(c2workItems, true, true);
+ }
+ }
+
+protected:
+ std::weak_ptr<Component> mComponent;
+ std::weak_ptr<IComponentListener> mListener;
+};
+
+// Component::DeathContext
+struct Component::DeathContext {
+ std::weak_ptr<Component> mWeakComp;
+};
+
+// Component
+Component::Component(
+ const std::shared_ptr<C2Component>& component,
+ const std::shared_ptr<IComponentListener>& listener,
+ const std::shared_ptr<ComponentStore>& store,
+ const std::shared_ptr<IClientManager>& clientPoolManager)
+ : mComponent{component},
+ mInterface{SharedRefBase::make<ComponentInterface>(
+ component->intf(), store->getParameterCache())},
+ mListener{listener},
+ mStore{store},
+ mBufferPoolSender{clientPoolManager},
+ mDeathContext(nullptr) {
+ // Retrieve supported parameters from store
+ // TODO: We could cache this per component/interface type
+ mInit = mInterface->status();
+}
+
+c2_status_t Component::status() const {
+ return mInit;
+}
+
+// Methods from ::android::hardware::media::c2::V1_1::IComponent
+ScopedAStatus Component::queue(const WorkBundle& workBundle) {
+ std::list<std::unique_ptr<C2Work>> c2works;
+
+ if (!FromAidl(&c2works, workBundle)) {
+ return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
+ }
+
+ // Register input buffers.
+ for (const std::unique_ptr<C2Work>& work : c2works) {
+ if (work) {
+ InputBufferManager::
+ registerFrameData(mListener, work->input);
+ }
+ }
+
+ c2_status_t err = mComponent->queue_nb(&c2works);
+ if (err == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(err);
+}
+
+ScopedAStatus Component::flush(WorkBundle *flushedWorkBundle) {
+ std::list<std::unique_ptr<C2Work>> c2flushedWorks;
+ c2_status_t c2res = mComponent->flush_sm(
+ C2Component::FLUSH_COMPONENT,
+ &c2flushedWorks);
+
+ // Unregister input buffers.
+ for (const std::unique_ptr<C2Work>& work : c2flushedWorks) {
+ if (work) {
+ if (work->worklets.empty()
+ || !work->worklets.back()
+ || (work->worklets.back()->output.flags &
+ C2FrameData::FLAG_INCOMPLETE) == 0) {
+ InputBufferManager::
+ unregisterFrameData(mListener, work->input);
+ }
+ }
+ }
+
+ // TODO
+ // beginTransferBufferQueueBlocks(c2flushedWorks, true);
+ if (c2res == C2_OK) {
+ if (!ToAidl(flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
+ c2res = C2_CORRUPTED;
+ }
+ }
+ // TODO
+ // endTransferBufferQueueBlocks(c2flushedWorks, true, true);
+ if (c2res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(c2res);
+}
+
+ScopedAStatus Component::drain(bool withEos) {
+ c2_status_t res = mComponent->drain_nb(withEos ?
+ C2Component::DRAIN_COMPONENT_WITH_EOS :
+ C2Component::DRAIN_COMPONENT_NO_EOS);
+ if (res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(res);
+}
+
+namespace /* unnamed */ {
+
+struct BlockPoolIntf : public ConfigurableC2Intf {
+ BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
+ : ConfigurableC2Intf{
+ "C2BlockPool:" +
+ (pool ? std::to_string(pool->getLocalId()) : "null"),
+ 0},
+ mPool{pool} {
+ }
+
+ virtual c2_status_t config(
+ const std::vector<C2Param*>& params,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) override {
+ (void)params;
+ (void)mayBlock;
+ (void)failures;
+ return C2_OK;
+ }
+
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index>& indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const params
+ ) const override {
+ (void)indices;
+ (void)mayBlock;
+ (void)params;
+ return C2_OK;
+ }
+
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+ ) const override {
+ (void)params;
+ return C2_OK;
+ }
+
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields,
+ c2_blocking_t mayBlock) const override {
+ (void)fields;
+ (void)mayBlock;
+ return C2_OK;
+ }
+
+protected:
+ std::shared_ptr<C2BlockPool> mPool;
+};
+
+} // unnamed namespace
+
+ScopedAStatus Component::createBlockPool(
+ const IComponent::BlockPoolAllocator &allocator,
+ IComponent::BlockPool *blockPool) {
+ std::shared_ptr<C2BlockPool> c2BlockPool;
+ static constexpr IComponent::BlockPoolAllocator::Tag ALLOCATOR_ID =
+ IComponent::BlockPoolAllocator::allocatorId;
+ static constexpr IComponent::BlockPoolAllocator::Tag IGBA =
+ IComponent::BlockPoolAllocator::igba;
+ c2_status_t status = C2_OK;
+ switch (allocator.getTag()) {
+ case ALLOCATOR_ID:
+#ifdef __ANDROID_APEX__
+ status = CreateCodec2BlockPool(
+ static_cast<::android::C2PlatformAllocatorStore::id_t>(
+ allocator.get<ALLOCATOR_ID>()),
+ mComponent,
+ &c2BlockPool);
+#else
+ status = ComponentStore::GetFilterWrapper()->createBlockPool(
+ static_cast<::android::C2PlatformAllocatorStore::id_t>(
+ allocator.get<ALLOCATOR_ID>()),
+ mComponent,
+ &c2BlockPool);
+#endif
+ if (status != C2_OK) {
+ blockPool = nullptr;
+ }
+ break;
+ case IGBA:
+ // FIXME
+ break;
+ default:
+ break;
+ }
+ if (blockPool) {
+ mBlockPoolsMutex.lock();
+ mBlockPools.emplace(c2BlockPool->getLocalId(), c2BlockPool);
+ mBlockPoolsMutex.unlock();
+ } else if (status == C2_OK) {
+ status = C2_CORRUPTED;
+ }
+
+ blockPool->blockPoolId = c2BlockPool ? c2BlockPool->getLocalId() : 0;
+ blockPool->configurable = SharedRefBase::make<CachedConfigurable>(
+ std::make_unique<BlockPoolIntf>(c2BlockPool));
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::destroyBlockPool(int64_t blockPoolId) {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ if (mBlockPools.erase(blockPoolId) == 1) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
+}
+
+ScopedAStatus Component::start() {
+ c2_status_t status = mComponent->start();
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::stop() {
+ InputBufferManager::unregisterFrameData(mListener);
+ c2_status_t status = mComponent->stop();
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::reset() {
+ c2_status_t status = mComponent->reset();
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ mBlockPools.clear();
+ }
+ InputBufferManager::unregisterFrameData(mListener);
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::release() {
+ c2_status_t status = mComponent->release();
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ mBlockPools.clear();
+ }
+ InputBufferManager::unregisterFrameData(mListener);
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::getInterface(
+ std::shared_ptr<IComponentInterface> *intf) {
+ *intf = mInterface;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Component::configureVideoTunnel(
+ int32_t avSyncHwId, NativeHandle *handle) {
+ (void)avSyncHwId;
+ (void)handle;
+ return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
+}
+
+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;
+ }
+
+ 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);
+}
+
+// static
+void Component::OnBinderDied(void *cookie) {
+ DeathContext *context = (DeathContext *)cookie;
+ std::shared_ptr<Component> comp = context->mWeakComp.lock();
+ if (comp) {
+ comp->release();
+ }
+}
+
+// static
+void Component::OnBinderUnlinked(void *cookie) {
+ delete (DeathContext *)cookie;
+}
+
+Component::~Component() {
+ InputBufferManager::unregisterFrameData(mListener);
+ mStore->reportComponentDeath(this);
+ if (mDeathRecipient.get()) {
+ AIBinder_unlinkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
+ }
+}
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/ComponentInterface.cpp b/media/codec2/hal/aidl/ComponentInterface.cpp
new file mode 100644
index 0000000..2d812c9
--- /dev/null
+++ b/media/codec2/hal/aidl/ComponentInterface.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentInterface"
+#include <android-base/logging.h>
+
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
+
+#include <utils/Timers.h>
+
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using ::ndk::ScopedAStatus;
+
+namespace /* unnamed */ {
+
+// Implementation of ConfigurableC2Intf based on C2ComponentInterface
+struct CompIntf : public ConfigurableC2Intf {
+ CompIntf(const std::shared_ptr<C2ComponentInterface>& intf) :
+ ConfigurableC2Intf{intf->getName(), intf->getId()},
+ mIntf{intf} {
+ }
+
+ virtual c2_status_t config(
+ const std::vector<C2Param*>& params,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) override {
+ return mIntf->config_vb(params, mayBlock, failures);
+ }
+
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index>& indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const params
+ ) const override {
+ return mIntf->query_vb({}, indices, mayBlock, params);
+ }
+
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+ ) const override {
+ return mIntf->querySupportedParams_nb(params);
+ }
+
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields,
+ c2_blocking_t mayBlock) const override {
+ return mIntf->querySupportedValues_vb(fields, mayBlock);
+ }
+
+protected:
+ std::shared_ptr<C2ComponentInterface> mIntf;
+};
+
+} // unnamed namespace
+
+// ComponentInterface
+ComponentInterface::ComponentInterface(
+ const std::shared_ptr<C2ComponentInterface>& intf,
+ const std::shared_ptr<ParameterCache>& cache)
+ : mInterface{intf},
+ mConfigurable{SharedRefBase::make<CachedConfigurable>(
+ std::make_unique<CompIntf>(intf))} {
+ mInit = mConfigurable->init(cache);
+}
+
+c2_status_t ComponentInterface::status() const {
+ return mInit;
+}
+
+ScopedAStatus ComponentInterface::getConfigurable(
+ std::shared_ptr<IConfigurable> *configurable) {
+ *configurable = mConfigurable;
+ return ScopedAStatus::ok();
+}
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
new file mode 100644
index 0000000..19734c0
--- /dev/null
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -0,0 +1,478 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentStore-Aidl"
+#include <android-base/logging.h>
+
+#include <bufferpool2/ClientManager.h>
+#include <codec2/aidl/Component.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/ParamTypes.h>
+
+#include <android-base/file.h>
+#include <utils/Errors.h>
+
+#include <C2PlatformSupport.h>
+#include <util/C2InterfaceHelper.h>
+
+#include <chrono>
+#include <ctime>
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+
+#ifndef __ANDROID_APEX__
+#include <codec2/hidl/plugin/FilterPlugin.h>
+#include <dlfcn.h>
+#include <C2Config.h>
+#include <DefaultFilterPlugin.h>
+#include <FilterWrapper.h>
+#endif
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using ::android::DefaultFilterPlugin;
+using ::android::FilterWrapper;
+using ::ndk::ScopedAStatus;
+
+namespace /* unnamed */ {
+
+struct StoreIntf : public ConfigurableC2Intf {
+ StoreIntf(const std::shared_ptr<C2ComponentStore>& store)
+ : ConfigurableC2Intf{store ? store->getName() : "", 0},
+ mStore{store} {
+ }
+
+ virtual c2_status_t config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>> *const failures
+ ) override {
+ // Assume all params are blocking
+ // TODO: Filter for supported params
+ if (mayBlock == C2_DONT_BLOCK && params.size() != 0) {
+ return C2_BLOCKING;
+ }
+ return mStore->config_sm(params, failures);
+ }
+
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index> &indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>> *const params) const override {
+ // Assume all params are blocking
+ // TODO: Filter for supported params
+ if (mayBlock == C2_DONT_BLOCK && indices.size() != 0) {
+ return C2_BLOCKING;
+ }
+ return mStore->query_sm({}, indices, params);
+ }
+
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
+ ) const override {
+ return mStore->querySupportedParams_nb(params);
+ }
+
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields,
+ c2_blocking_t mayBlock) const override {
+ // Assume all params are blocking
+ // TODO: Filter for supported params
+ if (mayBlock == C2_DONT_BLOCK && fields.size() != 0) {
+ return C2_BLOCKING;
+ }
+ return mStore->querySupportedValues_sm(fields);
+ }
+
+protected:
+ std::shared_ptr<C2ComponentStore> mStore;
+};
+
+} // unnamed namespace
+
+struct ComponentStore::StoreParameterCache : public ParameterCache {
+ std::mutex mStoreMutex;
+ ComponentStore* mStore;
+
+ StoreParameterCache(ComponentStore* store): mStore{store} {
+ }
+
+ virtual c2_status_t validate(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>& params
+ ) override {
+ std::scoped_lock _lock(mStoreMutex);
+ return mStore ? mStore->validateSupportedParams(params) : C2_NO_INIT;
+ }
+
+ void onStoreDestroyed() {
+ std::scoped_lock _lock(mStoreMutex);
+ mStore = nullptr;
+ }
+};
+
+ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store)
+ : mConfigurable{SharedRefBase::make<CachedConfigurable>(std::make_unique<StoreIntf>(store))},
+ mParameterCache{std::make_shared<StoreParameterCache>(this)},
+ mStore{store} {
+
+ std::shared_ptr<C2ComponentStore> platformStore =
+ ::android::GetCodec2PlatformComponentStore();
+ ::android::SetPreferredCodec2ComponentStore(store);
+
+ // Retrieve struct descriptors
+ mParamReflector = mStore->getParamReflector();
+
+ // Retrieve supported parameters from store
+ using namespace std::placeholders;
+ mInit = mConfigurable->init(mParameterCache);
+}
+
+ComponentStore::~ComponentStore() {
+ mParameterCache->onStoreDestroyed();
+}
+
+c2_status_t ComponentStore::status() const {
+ return mInit;
+}
+
+c2_status_t ComponentStore::validateSupportedParams(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>& params) {
+ c2_status_t res = C2_OK;
+
+ for (const std::shared_ptr<C2ParamDescriptor> &desc : params) {
+ if (!desc) {
+ // All descriptors should be valid
+ res = res ? res : C2_BAD_VALUE;
+ continue;
+ }
+ C2Param::CoreIndex coreIndex = desc->index().coreIndex();
+ std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+ auto it = mStructDescriptors.find(coreIndex);
+ if (it == mStructDescriptors.end()) {
+ std::shared_ptr<C2StructDescriptor> structDesc =
+ mParamReflector->describe(coreIndex);
+ if (!structDesc) {
+ // All supported params must be described
+ res = C2_BAD_INDEX;
+ }
+ mStructDescriptors.insert({ coreIndex, structDesc });
+ }
+ }
+ return res;
+}
+
+std::shared_ptr<ParameterCache> ComponentStore::getParameterCache() const {
+ return mParameterCache;
+}
+
+#ifndef __ANDROID_APEX__
+// static
+std::shared_ptr<FilterWrapper> ComponentStore::GetFilterWrapper() {
+ constexpr const char kPluginPath[] = "libc2filterplugin.so";
+ static std::shared_ptr<FilterWrapper> wrapper = FilterWrapper::Create(
+ std::make_unique<DefaultFilterPlugin>(kPluginPath));
+ return wrapper;
+}
+#endif
+
+// Methods from ::aidl::android::hardware::media::c2::IComponentStore
+ScopedAStatus ComponentStore::createComponent(
+ const std::string& name,
+ const std::shared_ptr<IComponentListener>& listener,
+ const std::shared_ptr<IClientManager>& pool,
+ std::shared_ptr<IComponent> *component) {
+
+ std::shared_ptr<C2Component> c2component;
+ c2_status_t status =
+ mStore->createComponent(name, &c2component);
+
+ if (status == C2_OK) {
+#ifndef __ANDROID_APEX__
+ c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
+ onInterfaceLoaded(c2component->intf());
+ std::shared_ptr<Component> comp =
+ SharedRefBase::make<Component>(c2component, listener, shared_from_this(), pool);
+ *component = comp;
+ if (!component) {
+ status = C2_CORRUPTED;
+ } else {
+ reportComponentBirth(comp.get());
+ if (comp->status() != C2_OK) {
+ status = comp->status();
+ } else {
+ comp->initListener(comp);
+ if (comp->status() != C2_OK) {
+ status = comp->status();
+ }
+ }
+ }
+ }
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus ComponentStore::createInterface(
+ const std::string& name,
+ std::shared_ptr<IComponentInterface> *intf) {
+ std::shared_ptr<C2ComponentInterface> c2interface;
+ c2_status_t res = mStore->createInterface(name, &c2interface);
+ if (res == C2_OK) {
+#ifndef __ANDROID_APEX__
+ c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
+#endif
+ onInterfaceLoaded(c2interface);
+ *intf = SharedRefBase::make<ComponentInterface>(c2interface, mParameterCache);
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(res);
+}
+
+ScopedAStatus ComponentStore::listComponents(
+ std::vector<IComponentStore::ComponentTraits> *traits) {
+ std::vector<std::shared_ptr<const C2Component::Traits>> c2traits =
+ mStore->listComponents();
+ traits->resize(c2traits.size());
+ size_t ix = 0;
+ for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
+ if (c2trait) {
+ if (ToAidl(&traits->at(ix), *c2trait)) {
+ ++ix;
+ } else {
+ break;
+ }
+ }
+ }
+ traits->resize(ix);
+ return ScopedAStatus::ok();
+}
+
+void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
+ // invalidate unsupported struct descriptors if a new interface is loaded as it may have
+ // exposed new descriptors
+ std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+ if (!mLoadedInterfaces.count(intf->getName())) {
+ mUnsupportedStructDescriptors.clear();
+ mLoadedInterfaces.emplace(intf->getName());
+ }
+}
+
+ScopedAStatus ComponentStore::getStructDescriptors(
+ const std::vector<int32_t>& indices,
+ std::vector<StructDescriptor> *descriptors) {
+ descriptors->resize(indices.size());
+ size_t dstIx = 0;
+ int32_t res = Status::OK;
+ for (size_t srcIx = 0; srcIx < indices.size(); ++srcIx) {
+ std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+ const C2Param::CoreIndex coreIndex =
+ C2Param::CoreIndex(uint32_t(indices[srcIx])).coreIndex();
+ const auto item = mStructDescriptors.find(coreIndex);
+ if (item == mStructDescriptors.end()) {
+ // not in the cache, and not known to be unsupported, query local reflector
+ if (!mUnsupportedStructDescriptors.count(coreIndex)) {
+ std::shared_ptr<C2StructDescriptor> structDesc =
+ mParamReflector->describe(coreIndex);
+ if (!structDesc) {
+ mUnsupportedStructDescriptors.emplace(coreIndex);
+ } else {
+ mStructDescriptors.insert({ coreIndex, structDesc });
+ if (ToAidl(&descriptors->at(dstIx), *structDesc)) {
+ ++dstIx;
+ continue;
+ }
+ res = Status::CORRUPTED;
+ break;
+ }
+ }
+ res = Status::NOT_FOUND;
+ } else if (item->second) {
+ if (ToAidl(&descriptors->at(dstIx), *item->second)) {
+ ++dstIx;
+ continue;
+ }
+ res = Status::CORRUPTED;
+ break;
+ } else {
+ res = Status::NO_MEMORY;
+ break;
+ }
+ }
+ descriptors->resize(dstIx);
+ if (res == Status::OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(res);
+}
+
+ScopedAStatus ComponentStore::getPoolClientManager(
+ std::shared_ptr<IClientManager> *manager) {
+ using ::aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
+ *manager = ClientManager::getInstance();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
+ // TODO implement
+ (void)src;
+ (void)dst;
+ return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
+}
+
+ScopedAStatus ComponentStore::getConfigurable(
+ std::shared_ptr<IConfigurable> *configurable) {
+ *configurable = mConfigurable;
+ return ScopedAStatus::ok();
+}
+
+// Called from createComponent() after a successful creation of `component`.
+void ComponentStore::reportComponentBirth(Component* component) {
+ ComponentStatus componentStatus;
+ componentStatus.c2Component = component->mComponent;
+ componentStatus.birthTime = std::chrono::system_clock::now();
+
+ std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+ mComponentRoster.emplace(component, componentStatus);
+}
+
+// Called from within the destructor of `component`. No virtual function calls
+// are made on `component` here.
+void ComponentStore::reportComponentDeath(Component* component) {
+ std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+ mComponentRoster.erase(component);
+}
+
+// Dumps component traits.
+std::ostream& ComponentStore::dump(
+ std::ostream& out,
+ const std::shared_ptr<const C2Component::Traits>& comp) {
+
+ constexpr const char indent[] = " ";
+
+ out << indent << "name: " << comp->name << std::endl;
+ out << indent << "domain: " << comp->domain << std::endl;
+ out << indent << "kind: " << comp->kind << std::endl;
+ out << indent << "rank: " << comp->rank << std::endl;
+ out << indent << "mediaType: " << comp->mediaType << std::endl;
+ out << indent << "aliases:";
+ for (const auto& alias : comp->aliases) {
+ out << ' ' << alias;
+ }
+ out << std::endl;
+
+ return out;
+}
+
+// Dumps component status.
+std::ostream& ComponentStore::dump(
+ std::ostream& out,
+ ComponentStatus& compStatus) {
+
+ constexpr const char indent[] = " ";
+
+ // Print birth time.
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ compStatus.birthTime.time_since_epoch());
+ std::time_t birthTime = std::chrono::system_clock::to_time_t(
+ compStatus.birthTime);
+ std::tm tm = *std::localtime(&birthTime);
+ out << indent << "Creation time: "
+ << std::put_time(&tm, "%Y-%m-%d %H:%M:%S")
+ << '.' << std::setfill('0') << std::setw(3) << ms.count() % 1000
+ << std::endl;
+
+ // Print name and id.
+ std::shared_ptr<C2ComponentInterface> intf = compStatus.c2Component->intf();
+ if (!intf) {
+ out << indent << "Unknown component -- null interface" << std::endl;
+ return out;
+ }
+ out << indent << "Name: " << intf->getName() << std::endl;
+ out << indent << "Id: " << intf->getId() << std::endl;
+
+ return out;
+}
+
+// Dumps information when lshal is called.
+binder_status_t ComponentStore::dump(
+ int fd, [[maybe_unused]] const char** args, [[maybe_unused]] uint32_t numArgs) {
+ LOG(INFO) << "debug -- dumping...";
+ std::ostringstream out;
+
+ { // Populate "out".
+
+ constexpr const char indent[] = " ";
+
+ // Show name.
+ out << "Beginning of dump -- C2ComponentStore: "
+ << mStore->getName() << std::endl << std::endl;
+
+ // Retrieve the list of supported components.
+ std::vector<std::shared_ptr<const C2Component::Traits>> traitsList =
+ mStore->listComponents();
+
+ // Dump the traits of supported components.
+ out << indent << "Supported components:" << std::endl << std::endl;
+ if (traitsList.size() == 0) {
+ out << indent << indent << "NONE" << std::endl << std::endl;
+ } else {
+ for (const auto& traits : traitsList) {
+ dump(out, traits) << std::endl;
+ }
+ }
+
+ // Dump active components.
+ {
+ out << indent << "Active components:" << std::endl << std::endl;
+ std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+ if (mComponentRoster.size() == 0) {
+ out << indent << indent << "NONE" << std::endl << std::endl;
+ } else {
+ for (auto& pair : mComponentRoster) {
+ dump(out, pair.second) << std::endl;
+ }
+ }
+ }
+
+ out << "End of dump -- C2ComponentStore: "
+ << mStore->getName() << std::endl;
+ }
+
+ if (!::android::base::WriteStringToFd(out.str(), fd)) {
+ PLOG(WARNING) << "debug -- dumping failed -- write()";
+ } else {
+ LOG(INFO) << "debug -- dumping succeeded";
+ }
+ return STATUS_OK;
+}
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/Configurable.cpp b/media/codec2/hal/aidl/Configurable.cpp
new file mode 100644
index 0000000..0326263
--- /dev/null
+++ b/media/codec2/hal/aidl/Configurable.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-Configurable-Aidl"
+#include <android-base/logging.h>
+
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/ParamTypes.h>
+
+#include <C2ParamInternal.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using ::ndk::ScopedAStatus;
+
+CachedConfigurable::CachedConfigurable(
+ std::unique_ptr<ConfigurableC2Intf>&& intf)
+ : mIntf{std::move(intf)} {
+}
+
+c2_status_t CachedConfigurable::init(
+ const std::shared_ptr<ParameterCache>& cache) {
+ // Retrieve supported parameters from store
+ c2_status_t init = mIntf->querySupportedParams(&mSupportedParams);
+ c2_status_t validate = cache->validate(mSupportedParams);
+ return init == C2_OK ? C2_OK : validate;
+}
+
+// Methods from ::android::hardware::media::c2::V1_0::IConfigurable follow.
+
+ScopedAStatus CachedConfigurable::getId(int32_t* id) {
+ *id = mIntf->getId();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus CachedConfigurable::getName(std::string* name) {
+ *name = mIntf->getName();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus CachedConfigurable::query(
+ const std::vector<int32_t>& indices,
+ bool mayBlock,
+ Params* params) {
+ typedef C2Param::Index Index;
+ std::vector<Index> c2heapParamIndices(
+ (Index*)indices.data(),
+ (Index*)indices.data() + indices.size());
+ std::vector<std::unique_ptr<C2Param>> c2heapParams;
+ c2_status_t c2res = mIntf->query(
+ c2heapParamIndices,
+ mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
+ &c2heapParams);
+
+ if (!CreateParamsBlob(params, c2heapParams)) {
+ LOG(WARNING) << "query -- invalid output params.";
+ }
+ if (c2res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(c2res);
+}
+
+ScopedAStatus CachedConfigurable::config(
+ const Params& params,
+ bool mayBlock,
+ ConfigResult* result) {
+ // inParams is not writable, so create a copy as config modifies the parameters
+ std::vector<C2Param*> c2params;
+ if (!ParseParamsBlob(&c2params, params)) {
+ LOG(WARNING) << "config -- invalid input params.";
+ return ScopedAStatus::fromServiceSpecificError(C2_CORRUPTED);
+ }
+ // TODO: check if blob was invalid
+ std::vector<std::unique_ptr<C2SettingResult>> c2failures;
+ c2_status_t c2res = mIntf->config(
+ c2params,
+ mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
+ &c2failures);
+ result->failures.resize(c2failures.size());
+ {
+ size_t ix = 0;
+ for (const std::unique_ptr<C2SettingResult>& c2result : c2failures) {
+ if (c2result) {
+ if (ToAidl(&result->failures[ix], *c2result)) {
+ ++ix;
+ } else {
+ LOG(DEBUG) << "config -- invalid setting results.";
+ break;
+ }
+ }
+ }
+ result->failures.resize(ix);
+ }
+ if (!CreateParamsBlob(&result->params, c2params)) {
+ LOG(DEBUG) << "config -- invalid output params.";
+ }
+ if (c2res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(c2res);
+}
+
+ScopedAStatus CachedConfigurable::querySupportedParams(
+ int32_t start,
+ int32_t count,
+ std::vector<ParamDescriptor>* paramDesc) {
+ C2LinearRange request = C2LinearCapacity(mSupportedParams.size()).range(
+ start, count);
+ paramDesc->resize(request.size());
+ int32_t res = Status::OK;
+ size_t dstIx = 0;
+ for (size_t srcIx = request.offset(); srcIx < request.endOffset(); ++srcIx) {
+ if (mSupportedParams[srcIx]) {
+ if (ToAidl(&(*paramDesc)[dstIx], *mSupportedParams[srcIx])) {
+ ++dstIx;
+ } else {
+ res = Status::CORRUPTED;
+ LOG(WARNING) << "querySupportedParams -- invalid output params.";
+ break;
+ }
+ } else {
+ res = Status::BAD_INDEX;
+ }
+ }
+ paramDesc->resize(dstIx);
+ if (res == Status::OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(res);
+}
+
+ScopedAStatus CachedConfigurable::querySupportedValues(
+ const std::vector<FieldSupportedValuesQuery>& fields,
+ bool mayBlock,
+ std::vector<FieldSupportedValuesQueryResult>* result) {
+ std::vector<C2FieldSupportedValuesQuery> c2fields;
+ {
+ // C2FieldSupportedValuesQuery objects are restricted in that some
+ // members are const.
+ // C2ParamField - required for its constructor - has no constructors
+ // from fields. Use C2ParamInspector.
+ for (const FieldSupportedValuesQuery &query : fields) {
+ c2fields.emplace_back(_C2ParamInspector::CreateParamField(
+ (uint32_t)query.field.index,
+ query.field.fieldId.offset,
+ query.field.fieldId.sizeBytes),
+ query.type == FieldSupportedValuesQuery::Type::POSSIBLE ?
+ C2FieldSupportedValuesQuery::POSSIBLE :
+ C2FieldSupportedValuesQuery::CURRENT);
+ }
+ }
+ c2_status_t c2res = mIntf->querySupportedValues(
+ c2fields,
+ mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK);
+ result->resize(fields.size());
+ size_t dstIx = 0;
+ for (const C2FieldSupportedValuesQuery &res : c2fields) {
+ if (ToAidl(&(*result)[dstIx], res)) {
+ ++dstIx;
+ } else {
+ result->resize(dstIx);
+ c2res = C2_CORRUPTED;
+ LOG(WARNING) << "querySupportedValues -- invalid output params.";
+ break;
+ }
+ }
+ if (c2res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(c2res);
+}
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
diff --git a/media/codec2/hal/aidl/InputBufferManager.cpp b/media/codec2/hal/aidl/InputBufferManager.cpp
new file mode 100644
index 0000000..5c58155
--- /dev/null
+++ b/media/codec2/hal/aidl/InputBufferManager.cpp
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-InputBufferManager-Aidl"
+#include <android-base/logging.h>
+
+#include <codec2/aidl/InputBufferManager.h>
+
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
+#include <android-base/logging.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <chrono>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using namespace ::android;
+
+void InputBufferManager::registerFrameData(
+ const std::shared_ptr<IComponentListener>& listener,
+ const C2FrameData& input) {
+ getInstance()._registerFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+ const std::weak_ptr<IComponentListener>& listener,
+ const C2FrameData& input) {
+ getInstance()._unregisterFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+ const std::weak_ptr<IComponentListener>& listener) {
+ getInstance()._unregisterFrameData(listener);
+}
+
+void InputBufferManager::setNotificationInterval(
+ nsecs_t notificationIntervalNs) {
+ getInstance()._setNotificationInterval(notificationIntervalNs);
+}
+
+void InputBufferManager::_registerFrameData(
+ const std::shared_ptr<IComponentListener>& listener,
+ const C2FrameData& input) {
+ uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+ LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- called with "
+ << "listener @ 0x" << std::hex << listener.get()
+ << ", frameIndex = " << std::dec << frameIndex
+ << ".";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ std::set<TrackedBuffer*> &bufferIds =
+ mTrackedBuffersMap[listener][frameIndex];
+
+ for (size_t i = 0; i < input.buffers.size(); ++i) {
+ if (!input.buffers[i]) {
+ LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- "
+ << "Input buffer at index " << i << " is null.";
+ continue;
+ }
+ TrackedBuffer *bufferId =
+ new TrackedBuffer(listener, frameIndex, i, input.buffers[i]);
+ mTrackedBufferCache.emplace(bufferId);
+ bufferIds.emplace(bufferId);
+
+ c2_status_t status = input.buffers[i]->registerOnDestroyNotify(
+ onBufferDestroyed,
+ reinterpret_cast<void*>(bufferId));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_registerFrameData -- "
+ << "registerOnDestroyNotify() failed "
+ << "(listener @ 0x" << std::hex << listener.get()
+ << ", frameIndex = " << std::dec << frameIndex
+ << ", bufferIndex = " << i
+ << ") => status = " << status
+ << ".";
+ }
+ }
+
+ mDeathNotifications.emplace(
+ listener,
+ DeathNotifications(
+ mNotificationIntervalNs.load(std::memory_order_relaxed)));
+}
+
+// Remove a pair (listener, frameIndex) from mTrackedBuffersMap and
+// mDeathNotifications. This implies all bufferIndices are removed.
+//
+// This is called from onWorkDone() and flush().
+void InputBufferManager::_unregisterFrameData(
+ const std::weak_ptr<IComponentListener>& listener,
+ const C2FrameData& input) {
+ uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+ LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
+ << "frameIndex = " << frameIndex << ".";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ auto findListener = mTrackedBuffersMap.find(listener);
+ if (findListener != mTrackedBuffersMap.end()) {
+ std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds
+ = findListener->second;
+ auto findFrameIndex = frameIndex2BufferIds.find(frameIndex);
+ if (findFrameIndex != frameIndex2BufferIds.end()) {
+ std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+ for (TrackedBuffer* bufferId : bufferIds) {
+ std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock();
+ if (buffer) {
+ c2_status_t status = buffer->unregisterOnDestroyNotify(
+ onBufferDestroyed,
+ reinterpret_cast<void*>(bufferId));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+ << "-- unregisterOnDestroyNotify() failed "
+ << "(frameIndex = " << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ") => status = " << status
+ << ".";
+ }
+ }
+ mTrackedBufferCache.erase(bufferId);
+ delete bufferId;
+ }
+
+ frameIndex2BufferIds.erase(findFrameIndex);
+ if (frameIndex2BufferIds.empty()) {
+ mTrackedBuffersMap.erase(findListener);
+ }
+ }
+ }
+
+ auto findListenerD = mDeathNotifications.find(listener);
+ if (findListenerD != mDeathNotifications.end()) {
+ DeathNotifications &deathNotifications = findListenerD->second;
+ auto findFrameIndex = deathNotifications.indices.find(frameIndex);
+ if (findFrameIndex != deathNotifications.indices.end()) {
+ std::vector<size_t> &bufferIndices = findFrameIndex->second;
+ deathNotifications.count -= bufferIndices.size();
+ deathNotifications.indices.erase(findFrameIndex);
+ }
+ }
+}
+
+// Remove listener from mTrackedBuffersMap and mDeathNotifications. This implies
+// all frameIndices and bufferIndices are removed.
+//
+// This is called when the component cleans up all input buffers, i.e., when
+// reset(), release(), stop() or ~Component() is called.
+void InputBufferManager::_unregisterFrameData(
+ const std::weak_ptr<IComponentListener>& listener) {
+ LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData.";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ auto findListener = mTrackedBuffersMap.find(listener);
+ if (findListener != mTrackedBuffersMap.end()) {
+ std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds =
+ findListener->second;
+ for (auto findFrameIndex = frameIndex2BufferIds.begin();
+ findFrameIndex != frameIndex2BufferIds.end();
+ ++findFrameIndex) {
+ std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+ for (TrackedBuffer* bufferId : bufferIds) {
+ std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock();
+ if (buffer) {
+ c2_status_t status = buffer->unregisterOnDestroyNotify(
+ onBufferDestroyed,
+ reinterpret_cast<void*>(bufferId));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+ << "-- unregisterOnDestroyNotify() failed "
+ << "(frameIndex = " << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ") => status = " << status
+ << ".";
+ }
+ mTrackedBufferCache.erase(bufferId);
+ delete bufferId;
+ }
+ }
+ }
+ mTrackedBuffersMap.erase(findListener);
+ }
+
+ mDeathNotifications.erase(listener);
+}
+
+// Set mNotificationIntervalNs.
+void InputBufferManager::_setNotificationInterval(
+ nsecs_t notificationIntervalNs) {
+ mNotificationIntervalNs.store(
+ notificationIntervalNs,
+ std::memory_order_relaxed);
+}
+
+// Move a buffer from mTrackedBuffersMap to mDeathNotifications.
+// This is called when a registered C2Buffer object is destroyed.
+void InputBufferManager::onBufferDestroyed(const C2Buffer* buf, void* arg) {
+ getInstance()._onBufferDestroyed(buf, arg);
+}
+
+void InputBufferManager::_onBufferDestroyed(const C2Buffer* buf, void* arg) {
+ if (!buf || !arg) {
+ LOG(WARNING) << "InputBufferManager::_onBufferDestroyed -- called with "
+ << "null argument (s): "
+ << "buf @ 0x" << std::hex << buf
+ << ", arg @ 0x" << std::hex << arg
+ << std::dec << ".";
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ TrackedBuffer *bufferId = reinterpret_cast<TrackedBuffer*>(arg);
+
+ if (mTrackedBufferCache.find(bufferId) == mTrackedBufferCache.end()) {
+ LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+ << "unregistered buffer: "
+ << "buf @ 0x" << std::hex << buf
+ << ", arg @ 0x" << std::hex << arg
+ << std::dec << ".";
+ return;
+ }
+
+ LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+ << "buf @ 0x" << std::hex << buf
+ << ", arg @ 0x" << std::hex << arg
+ << std::dec << " -- "
+ << ", frameIndex = " << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ".";
+ auto findListener = mTrackedBuffersMap.find(bufferId->listener);
+ if (findListener == mTrackedBuffersMap.end()) {
+ LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid listener: "
+ << " (frameIndex = " << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ").";
+ return;
+ }
+
+ std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds
+ = findListener->second;
+ auto findFrameIndex = frameIndex2BufferIds.find(bufferId->frameIndex);
+ if (findFrameIndex == frameIndex2BufferIds.end()) {
+ LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid frame index: "
+ << "frameIndex = " << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ").";
+ return;
+ }
+
+ std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+ auto findBufferId = bufferIds.find(bufferId);
+ if (findBufferId == bufferIds.end()) {
+ LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid buffer index: "
+ << "bufferIndex = " << bufferId->bufferIndex
+ << " (frameIndex = " << bufferId->frameIndex
+ << ").";
+ return;
+ }
+
+ bufferIds.erase(findBufferId);
+ if (bufferIds.empty()) {
+ frameIndex2BufferIds.erase(findFrameIndex);
+ if (frameIndex2BufferIds.empty()) {
+ mTrackedBuffersMap.erase(findListener);
+ }
+ }
+
+ DeathNotifications &deathNotifications = mDeathNotifications[bufferId->listener];
+ deathNotifications.indices[bufferId->frameIndex].emplace_back(bufferId->bufferIndex);
+ ++deathNotifications.count;
+ mOnBufferDestroyed.notify_one();
+
+ mTrackedBufferCache.erase(bufferId);
+ delete bufferId;
+}
+
+// Notify the clients about buffer destructions.
+// Return false if all destructions have been notified.
+// Return true and set timeToRetry to the time point to wait for before
+// retrying if some destructions have not been notified.
+bool InputBufferManager::processNotifications(nsecs_t* timeToRetryNs) {
+
+ struct Notification {
+ std::shared_ptr<IComponentListener> listener;
+ std::vector<IComponentListener::InputBuffer> inputBuffers;
+ Notification(const std::shared_ptr<IComponentListener>& l, size_t s)
+ : listener(l), inputBuffers(s) {}
+ };
+ std::list<Notification> notifications;
+ nsecs_t notificationIntervalNs =
+ mNotificationIntervalNs.load(std::memory_order_relaxed);
+
+ bool retry = false;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ *timeToRetryNs = notificationIntervalNs;
+ nsecs_t timeNowNs = systemTime();
+ for (auto it = mDeathNotifications.begin();
+ it != mDeathNotifications.end(); ) {
+ std::shared_ptr<IComponentListener> listener = it->first.lock();
+ if (!listener) {
+ ++it;
+ continue;
+ }
+ DeathNotifications &deathNotifications = it->second;
+
+ nsecs_t timeSinceLastNotifiedNs =
+ timeNowNs - deathNotifications.lastSentNs;
+ // If not enough time has passed since the last callback, leave the
+ // notifications for this listener untouched for now and retry
+ // later.
+ if (timeSinceLastNotifiedNs < notificationIntervalNs) {
+ retry = true;
+ *timeToRetryNs = std::min(*timeToRetryNs,
+ notificationIntervalNs - timeSinceLastNotifiedNs);
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "Notifications for listener @ "
+ << std::hex << listener.get()
+ << " will be postponed.";
+ ++it;
+ continue;
+ }
+
+ // If enough time has passed since the last notification to this
+ // listener but there are currently no pending notifications, the
+ // listener can be removed from mDeathNotifications---there is no
+ // need to keep track of the last notification time anymore.
+ if (deathNotifications.count == 0) {
+ it = mDeathNotifications.erase(it);
+ continue;
+ }
+
+ // Create the argument for the callback.
+ notifications.emplace_back(listener, deathNotifications.count);
+ std::vector<IComponentListener::InputBuffer> &inputBuffers =
+ notifications.back().inputBuffers;
+ size_t i = 0;
+ for (std::pair<const uint64_t, std::vector<size_t>>& p :
+ deathNotifications.indices) {
+ uint64_t frameIndex = p.first;
+ const std::vector<size_t> &bufferIndices = p.second;
+ for (const size_t& bufferIndex : bufferIndices) {
+ IComponentListener::InputBuffer &inputBuffer
+ = inputBuffers[i++];
+ inputBuffer.arrayIndex = bufferIndex;
+ inputBuffer.frameIndex = frameIndex;
+ }
+ }
+
+ // Clear deathNotifications for this listener and set retry to true
+ // so processNotifications will be called again. This will
+ // guarantee that a listener with no pending notifications will
+ // eventually be removed from mDeathNotifications after
+ // mNotificationIntervalNs nanoseconds has passed.
+ retry = true;
+ deathNotifications.indices.clear();
+ deathNotifications.count = 0;
+ deathNotifications.lastSentNs = timeNowNs;
+ ++it;
+ }
+ }
+
+ // Call onInputBuffersReleased() outside the lock to avoid deadlock.
+ for (const Notification& notification : notifications) {
+ if (!notification.listener->onInputBuffersReleased(
+ notification.inputBuffers).isOk()) {
+ // This may trigger if the client has died.
+ LOG(DEBUG) << "InputBufferManager::processNotifications -- "
+ << "failed to send death notifications to "
+ << "listener @ 0x" << std::hex
+ << notification.listener.get()
+ << std::dec << ".";
+ } else {
+#if LOG_NDEBUG == 0
+ std::stringstream inputBufferLog;
+ for (const IComponentListener::InputBuffer& inputBuffer :
+ notification.inputBuffers) {
+ inputBufferLog << " (" << inputBuffer.frameIndex
+ << ", " << inputBuffer.arrayIndex
+ << ")";
+ }
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "death notifications sent to "
+ << "listener @ 0x" << std::hex
+ << notification.listener.get()
+ << std::dec
+ << " with these (frameIndex, bufferIndex) pairs:"
+ << inputBufferLog.str();
+#endif
+ }
+ }
+#if LOG_NDEBUG == 0
+ if (retry) {
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "will retry again in " << *timeToRetryNs << "ns.";
+ } else {
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "no pending death notifications.";
+ }
+#endif
+ return retry;
+}
+
+void InputBufferManager::main() {
+ LOG(VERBOSE) << "InputBufferManager main -- started.";
+ nsecs_t timeToRetryNs;
+ while (true) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (mDeathNotifications.empty()) {
+ mOnBufferDestroyed.wait(lock);
+ }
+ lock.unlock();
+ while (processNotifications(&timeToRetryNs)) {
+ std::this_thread::sleep_for(
+ std::chrono::nanoseconds(timeToRetryNs));
+ }
+ }
+}
+
+InputBufferManager::InputBufferManager()
+ : mMainThread{&InputBufferManager::main, this} {
+}
+
+InputBufferManager& InputBufferManager::getInstance() {
+ static InputBufferManager instance{};
+ return instance;
+}
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
diff --git a/media/codec2/hal/aidl/ParamTypes.cpp b/media/codec2/hal/aidl/ParamTypes.cpp
index 0a430f9..7026f4c 100644
--- a/media/codec2/hal/aidl/ParamTypes.cpp
+++ b/media/codec2/hal/aidl/ParamTypes.cpp
@@ -157,14 +157,13 @@
namespace c2 {
namespace utils {
+// TODO: read it from aconfig flags
+bool IsEnabled() { return false; }
+
const char* asString(Status status, const char* def) {
return asString(static_cast<c2_status_t>(status.status), def);
}
-namespace /* unnamed */ {
-
-} // unnamed namespace
-
// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
bool ToAidl(
FieldSupportedValuesQuery* d,
diff --git a/media/codec2/hal/aidl/fuzzer.cpp b/media/codec2/hal/aidl/fuzzer.cpp
new file mode 100644
index 0000000..c1a2762
--- /dev/null
+++ b/media/codec2/hal/aidl/fuzzer.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <C2PlatformSupport.h>
+
+#include <android/binder_interface_utils.h>
+#include <codec2/aidl/ComponentStore.h>
+
+using aidl::android::hardware::media::c2::utils::ComponentStore;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::shared_ptr<C2ComponentStore> store = ::android::GetCodec2PlatformComponentStore();
+ std::shared_ptr<ComponentStore> binder = SharedRefBase::make<ComponentStore>(store);
+
+ fuzzService(binder->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Component.h b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
new file mode 100644
index 0000000..d5ea92b
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_COMPONENT_H
+#define CODEC2_AIDL_UTILS_COMPONENT_H
+
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/BufferTypes.h>
+#include <codec2/aidl/ParamTypes.h>
+
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponent.h>
+#include <aidl/android/hardware/media/c2/IComponentInterface.h>
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
+#include <aidl/android/hardware/media/c2/IComponentStore.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+
+struct ComponentStore;
+
+struct Component : public BnComponent,
+ public std::enable_shared_from_this<Component> {
+ Component(
+ const std::shared_ptr<C2Component>&,
+ const std::shared_ptr<IComponentListener>& listener,
+ const std::shared_ptr<ComponentStore>& store,
+ const std::shared_ptr<bufferpool2::IClientManager>& clientPoolManager);
+ c2_status_t status() const;
+
+ // Methods from IComponent follow.
+ ::ndk::ScopedAStatus queue(const WorkBundle& workBundle) override;
+ ::ndk::ScopedAStatus flush(WorkBundle *workBundle) override;
+ ::ndk::ScopedAStatus drain(bool withEos) override;
+ ::ndk::ScopedAStatus createBlockPool(
+ const IComponent::BlockPoolAllocator &allocator,
+ IComponent::BlockPool *blockPool) override;
+ ::ndk::ScopedAStatus destroyBlockPool(int64_t blockPoolId) override;
+ ::ndk::ScopedAStatus start() override;
+ ::ndk::ScopedAStatus stop() override;
+ ::ndk::ScopedAStatus reset() override;
+ ::ndk::ScopedAStatus release() override;
+ ::ndk::ScopedAStatus getInterface(
+ std::shared_ptr<IComponentInterface> *intf) override;
+ ::ndk::ScopedAStatus configureVideoTunnel(
+ int32_t avSyncHwId,
+ common::NativeHandle* handle) override;
+
+protected:
+ c2_status_t mInit;
+ std::shared_ptr<C2Component> mComponent;
+ std::shared_ptr<ComponentInterface> mInterface;
+ std::shared_ptr<IComponentListener> mListener;
+ std::shared_ptr<ComponentStore> mStore;
+ DefaultBufferPoolSender mBufferPoolSender;
+
+ std::mutex mBlockPoolsMutex;
+ // This map keeps C2BlockPool objects that are created by createBlockPool()
+ // alive. These C2BlockPool objects can be deleted by calling
+ // destroyBlockPool(), reset() or release(), or by destroying the component.
+ std::map<uint64_t, std::shared_ptr<C2BlockPool>> mBlockPools;
+
+ void initListener(const std::shared_ptr<Component>& self);
+
+ virtual ~Component() override;
+
+ friend struct ComponentStore;
+
+ struct Listener;
+
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+ static void OnBinderDied(void *cookie);
+ static void OnBinderUnlinked(void *cookie);
+ struct DeathContext;
+ DeathContext *mDeathContext;
+};
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // CODEC2_AIDL_UTILS_COMPONENT_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
new file mode 100644
index 0000000..7723bee
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
+
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/ParamTypes.h>
+
+#include <aidl/android/hardware/media/c2/BnComponentInterface.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+struct ComponentStore;
+
+struct ComponentInterface : public BnComponentInterface {
+ ComponentInterface(
+ const std::shared_ptr<C2ComponentInterface>& interface,
+ const std::shared_ptr<ParameterCache>& cache);
+ c2_status_t status() const;
+ ::ndk::ScopedAStatus getConfigurable(
+ std::shared_ptr<IConfigurable> *intf) override;
+
+protected:
+ std::shared_ptr<C2ComponentInterface> mInterface;
+ std::shared_ptr<CachedConfigurable> mConfigurable;
+ c2_status_t mInit;
+};
+
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
new file mode 100644
index 0000000..7fc5d2f
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_COMPONENTSTORE_H
+#define CODEC2_AIDL_UTILS_COMPONENTSTORE_H
+
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
+
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponentStore.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <chrono>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+namespace android {
+class FilterWrapper;
+} // namespace android
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+struct Component;
+
+using ::aidl::android::hardware::media::bufferpool2::IClientManager;
+
+struct ComponentStore : public BnComponentStore,
+ public std::enable_shared_from_this<ComponentStore> {
+ ComponentStore(const std::shared_ptr<C2ComponentStore>& store);
+ virtual ~ComponentStore();
+
+ /**
+ * Returns the status of the construction of this object.
+ */
+ c2_status_t status() const;
+
+ /**
+ * This function is called by CachedConfigurable::init() to validate
+ * supported parameters.
+ */
+ c2_status_t validateSupportedParams(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>& params);
+
+ /**
+ * Returns the store's ParameterCache. This is used for validation by
+ * Configurable::init().
+ */
+ std::shared_ptr<ParameterCache> getParameterCache() const;
+
+ static std::shared_ptr<::android::FilterWrapper> GetFilterWrapper();
+
+ // Methods from ::aidl::android::hardware::media::c2::IComponentStore.
+ virtual ::ndk::ScopedAStatus createComponent(
+ const std::string& name,
+ const std::shared_ptr<IComponentListener>& listener,
+ const std::shared_ptr<IClientManager>& pool,
+ std::shared_ptr<IComponent> *component) override;
+ virtual ::ndk::ScopedAStatus createInterface(
+ const std::string& name,
+ std::shared_ptr<IComponentInterface> *intf) override;
+ virtual ::ndk::ScopedAStatus listComponents(
+ std::vector<IComponentStore::ComponentTraits>* traits) override;
+ virtual ::ndk::ScopedAStatus getStructDescriptors(
+ const std::vector<int32_t>& indices,
+ std::vector<StructDescriptor> *descs) override;
+ virtual ::ndk::ScopedAStatus getPoolClientManager(
+ std::shared_ptr<IClientManager> *manager) override;
+ virtual ::ndk::ScopedAStatus copyBuffer(
+ const Buffer& src,
+ const Buffer& dst) override;
+ virtual ::ndk::ScopedAStatus getConfigurable(
+ std::shared_ptr<IConfigurable> *configurable) override;
+
+ /**
+ * Dumps information when lshal is called.
+ */
+ virtual binder_status_t dump(
+ int fd, const char** args, uint32_t numArgs) override;
+
+protected:
+ std::shared_ptr<CachedConfigurable> mConfigurable;
+ struct StoreParameterCache;
+ std::shared_ptr<StoreParameterCache> mParameterCache;
+
+ // Does bookkeeping for an interface that has been loaded.
+ void onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf);
+
+ c2_status_t mInit;
+ std::shared_ptr<C2ComponentStore> mStore;
+ std::shared_ptr<C2ParamReflector> mParamReflector;
+
+ std::map<C2Param::CoreIndex, std::shared_ptr<C2StructDescriptor>> mStructDescriptors;
+ std::set<C2Param::CoreIndex> mUnsupportedStructDescriptors;
+ std::set<C2String> mLoadedInterfaces;
+ mutable std::mutex mStructDescriptorsMutex;
+
+ // ComponentStore keeps track of live Components.
+
+ struct ComponentStatus {
+ std::shared_ptr<C2Component> c2Component;
+ std::chrono::system_clock::time_point birthTime;
+ };
+
+ mutable std::mutex mComponentRosterMutex;
+ std::map<Component*, ComponentStatus> mComponentRoster;
+
+ // Called whenever Component is created.
+ void reportComponentBirth(Component* component);
+ // Called only from the destructor of Component.
+ void reportComponentDeath(Component* component);
+
+ friend Component;
+
+ // Helper functions for dumping.
+
+ std::ostream& dump(
+ std::ostream& out,
+ const std::shared_ptr<const C2Component::Traits>& comp);
+
+ std::ostream& dump(
+ std::ostream& out,
+ ComponentStatus& compStatus);
+
+};
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // CODEC2_AIDL_UTILS_COMPONENTSTORE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
new file mode 100644
index 0000000..6cc2c1b
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_CONFIGURABLE_H
+#define CODEC2_AIDL_UTILS_CONFIGURABLE_H
+
+#include <aidl/android/hardware/media/c2/BnConfigurable.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+struct ComponentStore;
+
+/**
+ * Codec2 objects of different types may have different querying and configuring
+ * functions, but across the Treble boundary, they share the same HIDL
+ * interface, IConfigurable.
+ *
+ * ConfigurableC2Intf is an abstract class that a Codec2 object can implement to
+ * easily expose an IConfigurable instance. See CachedConfigurable below.
+ */
+struct ConfigurableC2Intf {
+ C2String getName() const { return mName; }
+ uint32_t getId() const { return mId; }
+ /** C2ComponentInterface::query_vb sans stack params */
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index> &indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const params) const = 0;
+ /** C2ComponentInterface::config_vb */
+ virtual c2_status_t config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+ /** C2ComponentInterface::querySupportedParams_nb */
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const = 0;
+ /** C2ComponentInterface::querySupportedParams_nb */
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const = 0;
+
+ virtual ~ConfigurableC2Intf() = default;
+
+ ConfigurableC2Intf(const C2String& name, uint32_t id)
+ : mName{name}, mId{id} {}
+
+protected:
+ C2String mName; /* cached component name */
+ uint32_t mId;
+};
+
+/**
+ * Type for validating and caching parameters when CachedConfigurable is
+ * initialized.
+ *
+ * This is meant to be created by the ComponentStore. The purpose of abstracting
+ * this is to allow different versions of ComponentStore to work with this
+ * CachedConfigurable.
+ */
+struct ParameterCache {
+ virtual c2_status_t validate(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>&) = 0;
+ virtual ~ParameterCache() = default;
+};
+
+/**
+ * Implementation of the IConfigurable interface that supports caching of
+ * supported parameters from a supplied ComponentStore.
+ *
+ * CachedConfigurable essentially converts a ConfigurableC2Intf into HIDL's
+ * IConfigurable. A Codec2 object generally implements ConfigurableC2Intf and
+ * passes the implementation to the constructor of CachedConfigurable.
+ *
+ * Note that caching happens
+ */
+struct CachedConfigurable : public BnConfigurable {
+ CachedConfigurable(std::unique_ptr<ConfigurableC2Intf>&& intf);
+
+ // Populates mSupportedParams.
+ c2_status_t init(const std::shared_ptr<ParameterCache> &cache);
+
+ // Methods from ::android::hardware::media::c2::V1_0::IConfigurable
+
+ virtual ::ndk::ScopedAStatus getId(int32_t* id) override;
+
+ virtual ::ndk::ScopedAStatus getName(std::string* name) override;
+
+ virtual ::ndk::ScopedAStatus query(
+ const std::vector<int32_t>& indices,
+ bool mayBlock,
+ Params* params) override;
+
+ virtual ::ndk::ScopedAStatus config(
+ const ::aidl::android::hardware::media::c2::Params& params,
+ bool mayBlock,
+ ConfigResult* result) override;
+
+ virtual ::ndk::ScopedAStatus querySupportedParams(
+ int32_t start,
+ int32_t count,
+ std::vector<ParamDescriptor>* paramDesc) override;
+
+ virtual ::ndk::ScopedAStatus querySupportedValues(
+ const std::vector<FieldSupportedValuesQuery>& fields,
+ bool mayBlock,
+ std::vector<FieldSupportedValuesQueryResult>* result) override;
+
+protected:
+ // Common Codec2.0 interface wrapper
+ std::unique_ptr<ConfigurableC2Intf> mIntf;
+
+ // Cached supported params
+ std::vector<std::shared_ptr<C2ParamDescriptor>> mSupportedParams;
+};
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // CODEC2_AIDL_UTILS_CONFIGURABLE_H
+
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
new file mode 100644
index 0000000..4e107a8
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
+
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
+#include <utils/Timers.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <set>
+#include <map>
+#include <thread>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+/**
+ * InputBufferManager
+ * ==================
+ *
+ * InputBufferManager presents a way to track and untrack input buffers in this
+ * (codec) process and send a notification to a listener, possibly in a
+ * different process, when a tracked buffer no longer has any references in this
+ * process.
+ *
+ * InputBufferManager holds a collection of records representing tracked buffers
+ * and their callback listeners. Conceptually, one record is a triple (listener,
+ * frameIndex, bufferIndex) where
+ *
+ * - (frameIndex, bufferIndex) is a pair of indices used to identify the buffer.
+ * - listener is of type IComponentListener. Its onInputBuffersReleased()
+ * function will be called after the associated buffer dies. The argument of
+ * onInputBuffersReleased() is a list of InputBuffer objects, each of which
+ * has the following members:
+ *
+ * uint64_t frameIndex
+ * uint32_t arrayIndex
+ *
+ * When a tracked buffer associated to the triple (listener, frameIndex,
+ * bufferIndex) goes out of scope, listener->onInputBuffersReleased() will be
+ * called with an InputBuffer object whose members are set as follows:
+ *
+ * inputBuffer.frameIndex = frameIndex
+ * inputBuffer.arrayIndex = bufferIndex
+ *
+ * IPC Optimization
+ * ----------------
+ *
+ * Since onInputBuffersReleased() is an IPC call, InputBufferManager tries not
+ * to call it too often. Any two calls to the same listener are at least
+ * mNotificationIntervalNs nanoseconds apart, where mNotificationIntervalNs is
+ * configurable via calling setNotificationInterval(). The default value of
+ * mNotificationIntervalNs is kDefaultNotificationInternalNs.
+ *
+ * Public Member Functions
+ * -----------------------
+ *
+ * InputBufferManager is a singleton class. Its only instance is accessible via
+ * the following public functions:
+ *
+ * - registerFrameData(const sp<IComponentListener>& listener,
+ * const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener,
+ * const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener)
+ *
+ * - setNotificationInterval(nsecs_t notificationIntervalNs)
+ *
+ */
+
+struct InputBufferManager {
+
+ /**
+ * The default value for the time interval between 2 subsequent IPCs.
+ */
+ static constexpr nsecs_t kDefaultNotificationIntervalNs = 1000000; /* 1ms */
+
+ /**
+ * Track all buffers in a C2FrameData object.
+ *
+ * input (C2FrameData) has the following two members that are of interest:
+ *
+ * C2WorkOrdinal ordinal
+ * vector<shared_ptr<C2Buffer>> buffers
+ *
+ * Calling registerFrameData(listener, input) will register multiple
+ * triples (listener, frameIndex, bufferIndex) where frameIndex is equal to
+ * input.ordinal.frameIndex and bufferIndex runs through the indices of
+ * input.buffers such that input.buffers[bufferIndex] is not null.
+ *
+ * This should be called from queue().
+ *
+ * \param listener Listener of death notifications.
+ * \param input Input frame data whose input buffers are to be tracked.
+ */
+ static void registerFrameData(
+ const std::shared_ptr<IComponentListener>& listener,
+ const C2FrameData& input);
+
+ /**
+ * Untrack all buffers in a C2FrameData object.
+ *
+ * Calling unregisterFrameData(listener, input) will unregister and remove
+ * pending notifications for all triples (l, fi, bufferIndex) such that
+ * l = listener and fi = input.ordinal.frameIndex.
+ *
+ * This should be called from onWorkDone() and flush().
+ *
+ * \param listener Previously registered listener.
+ * \param input Previously registered frame data.
+ */
+ static void unregisterFrameData(
+ const std::weak_ptr<IComponentListener>& listener,
+ const C2FrameData& input);
+
+ /**
+ * Untrack all buffers associated to a given listener.
+ *
+ * Calling unregisterFrameData(listener) will unregister and remove
+ * pending notifications for all triples (l, frameIndex, bufferIndex) such
+ * that l = listener.
+ *
+ * This should be called when the component cleans up all input buffers,
+ * i.e., when reset(), release(), stop() or ~Component() is called.
+ *
+ * \param listener Previously registered listener.
+ */
+ static void unregisterFrameData(
+ const std::weak_ptr<IComponentListener>& listener);
+
+ /**
+ * Set the notification interval.
+ *
+ * \param notificationIntervalNs New notification interval, in nanoseconds.
+ */
+ static void setNotificationInterval(nsecs_t notificationIntervalNs);
+
+private:
+ void _registerFrameData(
+ const std::shared_ptr<IComponentListener>& listener,
+ const C2FrameData& input);
+ void _unregisterFrameData(
+ const std::weak_ptr<IComponentListener>& listener,
+ const C2FrameData& input);
+ void _unregisterFrameData(
+ const std::weak_ptr<IComponentListener>& listener);
+ void _setNotificationInterval(nsecs_t notificationIntervalNs);
+
+ // The callback function tied to C2Buffer objects.
+ //
+ // Note: This function assumes that sInstance is the only instance of this
+ // class.
+ static void onBufferDestroyed(const C2Buffer* buf, void* arg);
+ void _onBufferDestroyed(const C2Buffer* buf, void* arg);
+
+ // Persistent data to be passed as "arg" in onBufferDestroyed().
+ // This is essentially the triple (listener, frameIndex, bufferIndex) plus a
+ // weak pointer to the C2Buffer object.
+ //
+ // Note that the "key" is bufferIndex according to operator<(). This is
+ // designed to work with TrackedBuffersMap defined below.
+ struct TrackedBuffer {
+ std::weak_ptr<IComponentListener> listener;
+ uint64_t frameIndex;
+ size_t bufferIndex;
+ std::weak_ptr<C2Buffer> buffer;
+ TrackedBuffer(const std::weak_ptr<IComponentListener>& listener,
+ uint64_t frameIndex,
+ size_t bufferIndex,
+ const std::shared_ptr<C2Buffer>& buffer)
+ : listener(listener),
+ frameIndex(frameIndex),
+ bufferIndex(bufferIndex),
+ buffer(buffer) {}
+ };
+
+ // Map: listener -> frameIndex -> set<TrackedBuffer*>.
+ // Essentially, this is used to store triples (listener, frameIndex,
+ // bufferIndex) that's searchable by listener and (listener, frameIndex).
+ // However, the value of the innermost map is TrackedBuffer, which also
+ // contains an extra copy of listener and frameIndex. This is needed
+ // because onBufferDestroyed() needs to know listener and frameIndex too.
+ typedef std::map<std::weak_ptr<IComponentListener>,
+ std::map<uint64_t,
+ std::set<TrackedBuffer*>>,
+ std::owner_less<std::weak_ptr<IComponentListener>>> TrackedBuffersMap;
+
+ // Storage for pending (unsent) death notifications for one listener.
+ // Each pair in member named "indices" are (frameIndex, bufferIndex) from
+ // the (listener, frameIndex, bufferIndex) triple.
+ struct DeathNotifications {
+
+ // The number of pending notifications for this listener.
+ // count may be 0, in which case the DeathNotifications object will
+ // remain valid for only a small period (specified
+ // nanoseconds).
+ size_t count;
+
+ // The timestamp of the most recent callback on this listener. This is
+ // used to guarantee that callbacks do not occur too frequently, and
+ // also to trigger expiration of a DeathNotifications object that has
+ // count = 0.
+ nsecs_t lastSentNs;
+
+ // Map: frameIndex -> vector of bufferIndices
+ // This is essentially a collection of (framdeIndex, bufferIndex).
+ std::map<uint64_t, std::vector<size_t>> indices;
+
+ DeathNotifications(
+ nsecs_t notificationIntervalNs = kDefaultNotificationIntervalNs)
+ : count(0),
+ lastSentNs(systemTime() - notificationIntervalNs),
+ indices() {}
+ };
+
+ // The minimum time period between IPC calls to notify the client about the
+ // destruction of input buffers.
+ std::atomic<nsecs_t> mNotificationIntervalNs{kDefaultNotificationIntervalNs};
+
+ // Mutex for the management of all input buffers.
+ std::mutex mMutex;
+
+ // Cache for all TrackedBuffers.
+ //
+ // Whenever registerOnDestroyNotify() is called, an argument of type
+ // TrackedBuffer is created and stored into this cache.
+ // Whenever unregisterOnDestroyNotify() or onBufferDestroyed() is called,
+ // the TrackedBuffer is removed from this cache.
+ //
+ // mTrackedBuffersMap stores references to TrackedBuffers inside this cache.
+ std::set<TrackedBuffer*> mTrackedBufferCache;
+
+ // Tracked input buffers.
+ TrackedBuffersMap mTrackedBuffersMap;
+
+ // Death notifications to be sent.
+ //
+ // A DeathNotifications object is associated to each listener. An entry in
+ // this map will be removed if its associated DeathNotifications has count =
+ // 0 and lastSentNs < systemTime() - mNotificationIntervalNs.
+ std::map<std::weak_ptr<IComponentListener>,
+ DeathNotifications,
+ std::owner_less<std::weak_ptr<IComponentListener>>> mDeathNotifications;
+
+ // Condition variable signaled when an entry is added to mDeathNotifications.
+ std::condition_variable mOnBufferDestroyed;
+
+ // Notify the clients about buffer destructions.
+ // Return false if all destructions have been notified.
+ // Return true and set timeToRetry to the duration to wait for before
+ // retrying if some destructions have not been notified.
+ bool processNotifications(nsecs_t* timeToRetryNs);
+
+ // Main function for the input buffer manager thread.
+ void main();
+
+ // The thread that manages notifications.
+ //
+ // Note: This variable is declared last so its initialization will happen
+ // after all other member variables have been initialized.
+ std::thread mMainThread;
+
+ // Private constructor.
+ InputBufferManager();
+
+ // The only instance of this class.
+ static InputBufferManager& getInstance();
+
+};
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
+
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h b/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
index ff69039..3f82ee3 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
@@ -37,11 +37,14 @@
namespace c2 {
namespace utils {
+// Returns true iff AIDL c2 HAL is enabled
+bool IsEnabled();
+
// Make asString() and operator<< work with Status as well as c2_status_t.
C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(Status);
/**
- * All objcpy() functions will return a boolean value indicating whether the
+ * All To/FromAidl() functions will return a boolean value indicating whether the
* conversion succeeds or not.
*/
diff --git a/media/codec2/hal/client/Android.bp b/media/codec2/hal/client/Android.bp
index 61ec10e..0b5b940 100644
--- a/media/codec2/hal/client/Android.bp
+++ b/media/codec2/hal/client/Android.bp
@@ -23,6 +23,7 @@
name: "libcodec2_client",
srcs: [
+ "GraphicBufferAllocator.cpp",
"GraphicsTracker.cpp",
"client.cpp",
"output.cpp",
@@ -42,6 +43,7 @@
"android.hardware.media.c2@1.0",
"android.hardware.media.c2@1.1",
"android.hardware.media.c2@1.2",
+ "android.hardware.media.bufferpool2-V1-ndk",
"android.hardware.media.c2-V1-ndk",
"libbase",
"libbinder",
@@ -56,11 +58,16 @@
"libhidlbase",
"liblog",
"libnativewindow",
+ "libstagefright_aidl_bufferpool2",
"libstagefright_bufferpool@2.0.1",
"libui",
"libutils",
],
+ static_libs: [
+ "libaidlcommonsupport",
+ ],
+
export_include_dirs: [
"include",
],
diff --git a/media/codec2/hal/client/GraphicBufferAllocator.cpp b/media/codec2/hal/client/GraphicBufferAllocator.cpp
new file mode 100644
index 0000000..bbef1b5
--- /dev/null
+++ b/media/codec2/hal/client/GraphicBufferAllocator.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/IProducerListener.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <codec2/aidl/GraphicBufferAllocator.h>
+#include <codec2/aidl/GraphicsTracker.h>
+
+namespace aidl::android::hardware::media::c2::implementation {
+
+class OnBufferReleasedListener : public ::android::BnProducerListener {
+private:
+ uint32_t mGeneration;
+ std::weak_ptr<GraphicBufferAllocator> mAllocator;
+public:
+ OnBufferReleasedListener(
+ uint32_t generation,
+ const std::shared_ptr<GraphicBufferAllocator> &allocator)
+ : mGeneration(generation), mAllocator(allocator) {}
+ virtual ~OnBufferReleasedListener() = default;
+ virtual void onBufferReleased() {
+ auto p = mAllocator.lock();
+ if (p) {
+ p->onBufferReleased(mGeneration);
+ }
+ }
+ virtual bool needsReleaseNotify() { return true; }
+};
+
+::ndk::ScopedAStatus GraphicBufferAllocator::allocate(
+ const IGraphicBufferAllocator::Description& in_desc,
+ IGraphicBufferAllocator::Allocation* _aidl_return) {
+ AHardwareBuffer *buf;
+ ::android::sp<::android::Fence> fence;
+ c2_status_t ret = allocate(
+ in_desc.width, in_desc.height, in_desc.format, in_desc.usage,
+ &buf, &fence);
+ if (ret == C2_OK) {
+ _aidl_return->buffer.reset(buf);
+ _aidl_return->fence = ::ndk::ScopedFileDescriptor(fence->dup());
+ return ::ndk::ScopedAStatus::ok();
+ }
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
+}
+
+::ndk::ScopedAStatus GraphicBufferAllocator::deallocate(int64_t in_id, bool* _aidl_return) {
+ *_aidl_return = deallocate(in_id, ::android::Fence::NO_FENCE);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus GraphicBufferAllocator::getWaitableFds(
+ IGraphicBufferAllocator::WaitableFds* _aidl_return) {
+ int allocFd;
+ int statusFd;
+ c2_status_t ret = mGraphicsTracker->getWaitableFds(&allocFd, &statusFd);
+ if (ret == C2_OK) {
+ _aidl_return->allocEvent.set(allocFd);
+ _aidl_return->statusEvent.set(statusFd);
+ return ::ndk::ScopedAStatus::ok();
+ }
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
+}
+
+bool GraphicBufferAllocator::configure(
+ const ::android::sp<IGraphicBufferProducer>& igbp,
+ uint32_t generation,
+ int maxDequeueBufferCount) {
+ c2_status_t ret = C2_OK;
+
+ ret = mGraphicsTracker->configureGraphics(igbp, generation);
+ if (ret != C2_OK) {
+ ALOGE("configuring igbp failed gen #(%d), configuring max dequeue count didn't happen",
+ (unsigned int)generation);
+ return false;
+ }
+
+ ret = mGraphicsTracker->configureMaxDequeueCount(maxDequeueBufferCount);
+ if (ret != C2_OK) {
+ ALOGE("configuring max dequeue count to %d failed", maxDequeueBufferCount);
+ return false;
+ }
+ return true;
+}
+
+void GraphicBufferAllocator::updateMaxDequeueBufferCount(int count) {
+ c2_status_t ret = mGraphicsTracker->configureMaxDequeueCount(count);
+ if (ret != C2_OK) {
+ ALOGE("updating max dequeue buffer count failed %d", ret);
+ }
+}
+
+void GraphicBufferAllocator::reset() {
+ mGraphicsTracker->stop();
+}
+
+const ::android::sp<::android::IProducerListener> GraphicBufferAllocator::createReleaseListener(
+ uint32_t generation) {
+ return new OnBufferReleasedListener(generation, ref<GraphicBufferAllocator>());
+}
+
+void GraphicBufferAllocator::onBufferReleased(uint32_t generation) {
+ mGraphicsTracker->onReleased(generation);
+}
+
+c2_status_t GraphicBufferAllocator::allocate(
+ uint32_t width, uint32_t height, ::android::PixelFormat format, uint64_t usage,
+ AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence) {
+ return mGraphicsTracker->allocate(width, height, format, usage, buf, fence);
+}
+
+bool GraphicBufferAllocator::deallocate(const uint64_t id,
+ const ::android::sp<::android::Fence> &fence) {
+ c2_status_t ret = mGraphicsTracker->deallocate(id, fence);
+ if (ret != C2_OK) {
+ ALOGW("deallocate() %llu was not successful %d", (unsigned long long)id, ret);
+ return false;
+ }
+ return true;
+}
+
+c2_status_t GraphicBufferAllocator::displayBuffer(
+ const C2ConstGraphicBlock& block,
+ const IGraphicBufferProducer::QueueBufferInput& input,
+ IGraphicBufferProducer::QueueBufferOutput *output) {
+ return mGraphicsTracker->render(block, input, output);
+}
+
+GraphicBufferAllocator::~GraphicBufferAllocator() {}
+
+std::shared_ptr<GraphicBufferAllocator> GraphicBufferAllocator::CreateGraphicBufferAllocator(
+ int maxDequeueCount) {
+ return ::ndk::SharedRefBase::make<GraphicBufferAllocator>(maxDequeueCount);
+}
+
+GraphicBufferAllocator::GraphicBufferAllocator(int maxDequeueCount)
+ : mGraphicsTracker(GraphicsTracker::CreateGraphicsTracker(maxDequeueCount)) {}
+
+} // namespace aidl::android::hardware::media::c2::implementation
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index 00820eb..accb9fd 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -24,7 +24,6 @@
#include <C2Config.h> // for C2StreamUsageTuning
#include <C2PlatformSupport.h>
-#include <android/binder_auto_utils.h>
#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
#include <android/hardware/media/c2/1.0/IComponent.h>
#include <android/hardware/media/c2/1.0/IComponentInterface.h>
@@ -33,6 +32,8 @@
#include <android/hardware/media/c2/1.0/IConfigurable.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponentListener.h>
#include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
#include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
#include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
@@ -41,9 +42,17 @@
#include <aidl/android/hardware/media/c2/IComponentStore.h>
#include <aidl/android/hardware/media/c2/IConfigurable.h>
#include <aidl/android/hardware/media/c2/ParamDescriptor.h>
+#include <aidl/android/hardware/media/c2/StructDescriptor.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
#include <bufferpool/ClientManager.h>
+#include <bufferpool2/ClientManager.h>
+#include <codec2/aidl/BufferTypes.h>
#include <codec2/aidl/ParamTypes.h>
#include <codec2/hidl/1.0/types.h>
#include <codec2/hidl/1.1/types.h>
@@ -85,6 +94,7 @@
V2_0::utils::H2BGraphicBufferProducer;
using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
+namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
namespace c2_aidl = ::aidl::android::hardware::media::c2;
namespace c2_hidl_base = ::android::hardware::media::c2;
@@ -178,6 +188,20 @@
}
};
+c2_status_t GetC2Status(const ::ndk::ScopedAStatus &transStatus, const char *method) {
+ if (!transStatus.isOk()) {
+ if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
+ LOG(DEBUG) << method << " -- call failed: " << status << ".";
+ return status;
+ } else {
+ LOG(ERROR) << method << " -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+ return C2_OK;
+}
+
} // unnamed namespace
// This class caches a Codec2Client object and its component traits. The client
@@ -605,18 +629,11 @@
}
c2_aidl::Params result;
ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
- if (!transStatus.isOk()) {
- if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
- c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
- LOG(DEBUG) << "query -- call failed: " << status << ".";
- return status;
- } else {
- LOG(ERROR) << "query -- transaction failed.";
- return C2_TRANSACTION_FAILED;
- }
+ c2_status_t status = GetC2Status(transStatus, "query");
+ if (status != C2_OK) {
+ return status;
}
- c2_status_t status = C2_OK;
std::vector<C2Param*> paramPointers;
if (!c2_aidl::utils::ParseParamsBlob(¶mPointers, result)) {
LOG(ERROR) << "query -- error while parsing params.";
@@ -685,17 +702,10 @@
}
c2_aidl::IConfigurable::ConfigResult result;
ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
- if (!transStatus.isOk()) {
- if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
- c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
- LOG(DEBUG) << "config -- call failed: " << status << ".";
- return status;
- } else {
- LOG(ERROR) << "config -- transaction failed.";
- return C2_TRANSACTION_FAILED;
- }
+ c2_status_t status = GetC2Status(transStatus, "config");
+ if (status != C2_OK) {
+ return status;
}
- c2_status_t status = C2_OK;
size_t i = failures->size();
failures->resize(i + result.failures.size());
for (const c2_aidl::SettingResult& sf : result.failures) {
@@ -720,17 +730,10 @@
std::numeric_limits<uint32_t>::min(),
std::numeric_limits<uint32_t>::max(),
&result);
- if (!transStatus.isOk()) {
- if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
- c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
- LOG(DEBUG) << "querySupportedParams -- call failed: " << status << ".";
- return status;
- } else {
- LOG(ERROR) << "querySupportedParams -- transaction failed.";
- return C2_TRANSACTION_FAILED;
- }
+ c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
+ if (status != C2_OK) {
+ return status;
}
- c2_status_t status = C2_OK;
size_t i = params->size();
params->resize(i + result.size());
for (const c2_aidl::ParamDescriptor& sp : result) {
@@ -756,17 +759,10 @@
std::vector<c2_aidl::FieldSupportedValuesQueryResult> result;
ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
inFields, (mayBlock == C2_MAY_BLOCK), &result);
- if (!transStatus.isOk()) {
- if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
- c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
- LOG(DEBUG) << "querySupportedValues -- call failed: " << status << ".";
- return status;
- } else {
- LOG(ERROR) << "querySupportedValues -- transaction failed.";
- return C2_TRANSACTION_FAILED;
- }
+ c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
+ if (status != C2_OK) {
+ return status;
}
- c2_status_t status = C2_OK;
if (result.size() != fields.size()) {
LOG(ERROR) << "querySupportedValues -- "
"input and output lists "
@@ -922,14 +918,119 @@
};
-// Codec2Client::Component::BufferPoolSender
-struct Codec2Client::Component::BufferPoolSender :
+// Codec2Client::Component::AidlListener
+struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
+ std::weak_ptr<Component> component;
+ std::weak_ptr<Listener> base;
+
+ virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
+ std::list<std::unique_ptr<C2Work>> workItems;
+ if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
+ LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
+ return ::ndk::ScopedAStatus::ok();
+ }
+ // release input buffers potentially held by the component from queue
+ std::shared_ptr<Codec2Client::Component> strongComponent =
+ component.lock();
+ if (strongComponent) {
+ strongComponent->handleOnWorkDone(workItems);
+ }
+ if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
+ listener->onWorkDone(component, workItems);
+ } else {
+ LOG(DEBUG) << "onWorkDone -- listener died.";
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ virtual ::ndk::ScopedAStatus onTripped(
+ const std::vector<c2_aidl::SettingResult>& settingResults) override {
+ std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
+ settingResults.size());
+ for (size_t i = 0; i < settingResults.size(); ++i) {
+ std::unique_ptr<C2SettingResult> c2SettingResult;
+ if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
+ LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
+ return ::ndk::ScopedAStatus::ok();
+ }
+ c2SettingResults[i] = std::move(c2SettingResult);
+ }
+ if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
+ listener->onTripped(component, c2SettingResults);
+ } else {
+ LOG(DEBUG) << "onTripped -- listener died.";
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
+ LOG(DEBUG) << "onError --"
+ << " status = " << s.status
+ << ", errorCode = " << errorCode
+ << ".";
+ if (std::shared_ptr<Listener> listener = base.lock()) {
+ listener->onError(component, s.status == c2_aidl::Status::OK ?
+ errorCode : static_cast<c2_status_t>(s.status));
+ } else {
+ LOG(DEBUG) << "onError -- listener died.";
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ virtual ::ndk::ScopedAStatus onFramesRendered(
+ const std::vector<RenderedFrame>& renderedFrames) override {
+ std::shared_ptr<Listener> listener = base.lock();
+ if (!listener) {
+ LOG(DEBUG) << "onFramesRendered -- listener died.";
+ return ::ndk::ScopedAStatus::ok();
+ }
+ for (const RenderedFrame& renderedFrame : renderedFrames) {
+ listener->onFrameRendered(
+ renderedFrame.bufferQueueId,
+ renderedFrame.slotId,
+ renderedFrame.timestampNs);
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ virtual ::ndk::ScopedAStatus onInputBuffersReleased(
+ const std::vector<InputBuffer>& inputBuffers) override {
+ std::shared_ptr<Listener> listener = base.lock();
+ if (!listener) {
+ LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
+ return ::ndk::ScopedAStatus::ok();
+ }
+ for (const InputBuffer& inputBuffer : inputBuffers) {
+ LOG(VERBOSE) << "onInputBuffersReleased --"
+ " received death notification of"
+ " input buffer:"
+ " frameIndex = " << inputBuffer.frameIndex
+ << ", bufferIndex = " << inputBuffer.arrayIndex
+ << ".";
+ listener->onInputBufferDone(
+ inputBuffer.frameIndex, inputBuffer.arrayIndex);
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+};
+
+// Codec2Client::Component::HidlBufferPoolSender
+struct Codec2Client::Component::HidlBufferPoolSender :
hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
- BufferPoolSender()
+ HidlBufferPoolSender()
: hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
}
};
+// Codec2Client::Component::AidlBufferPoolSender
+struct Codec2Client::Component::AidlBufferPoolSender :
+ c2_aidl::utils::DefaultBufferPoolSender {
+ AidlBufferPoolSender()
+ : c2_aidl::utils::DefaultBufferPoolSender() {
+ }
+};
+
// Codec2Client::Component::OutputBufferQueue
struct Codec2Client::Component::OutputBufferQueue :
hardware::media::c2::OutputBufferQueue {
@@ -939,36 +1040,53 @@
};
// Codec2Client
-Codec2Client::Codec2Client(sp<Base> const& base,
+Codec2Client::Codec2Client(sp<HidlBase> const& base,
sp<c2_hidl::IConfigurable> const& configurable,
size_t serviceIndex)
: Configurable{configurable},
- mBase1_0{base},
- mBase1_1{Base1_1::castFrom(base)},
- mBase1_2{Base1_2::castFrom(base)},
+ mHidlBase1_0{base},
+ mHidlBase1_1{HidlBase1_1::castFrom(base)},
+ mHidlBase1_2{HidlBase1_2::castFrom(base)},
mServiceIndex{serviceIndex} {
Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
if (!transResult.isOk()) {
LOG(ERROR) << "getPoolClientManager -- transaction failed.";
} else {
- mHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
+ mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
}
}
-sp<Codec2Client::Base> const& Codec2Client::getBase() const {
- return mBase1_0;
+Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
+ std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
+ size_t serviceIndex)
+ : Configurable{configurable},
+ mAidlBase{base},
+ mServiceIndex{serviceIndex} {
+ ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "getPoolClientManager -- transaction failed.";
+ mAidlHostPoolManager.reset();
+ }
}
-sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
- return mBase1_0;
+sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
+ return mHidlBase1_0;
}
-sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
- return mBase1_1;
+sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
+ return mHidlBase1_0;
}
-sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
- return mBase1_2;
+sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
+ return mHidlBase1_1;
+}
+
+sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
+ return mHidlBase1_2;
+}
+
+::ndk::SpAIBinder Codec2Client::getAidlBase() const {
+ return mAidlBase ? mAidlBase->asBinder() : nullptr;
}
std::string const& Codec2Client::getServiceName() const {
@@ -979,13 +1097,41 @@
const C2String& name,
const std::shared_ptr<Codec2Client::Listener>& listener,
std::shared_ptr<Codec2Client::Component>* const component) {
+ if (mAidlBase) {
+ std::shared_ptr<Component::AidlListener> aidlListener =
+ Component::AidlListener::make<Component::AidlListener>();
+ aidlListener->base = listener;
+ std::shared_ptr<c2_aidl::IComponent> aidlComponent;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
+ name,
+ aidlListener,
+ bufferpool2_aidl::implementation::ClientManager::getInstance(),
+ &aidlComponent);
+ c2_status_t status = GetC2Status(transStatus, "createComponent");
+ if (status != C2_OK) {
+ return status;
+ } else if (!aidlComponent) {
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- null component.";
+ return C2_CORRUPTED;
+ }
+ *component = std::make_shared<Codec2Client::Component>(aidlComponent);
+ status = (*component)->setDeathListener((*component), listener);
+ if (status != C2_OK) {
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- failed to set up death listener: "
+ << status << ".";
+ }
+ (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
+ return status;
+ }
c2_status_t status;
sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
hidlListener->base = listener;
Return<void> transStatus;
- if (mBase1_2) {
- transStatus = mBase1_2->createComponent_1_2(
+ if (mHidlBase1_2) {
+ transStatus = mHidlBase1_2->createComponent_1_2(
name,
hidlListener,
bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -1000,8 +1146,8 @@
hidlListener->component = *component;
});
}
- else if (mBase1_1) {
- transStatus = mBase1_1->createComponent_1_1(
+ else if (mHidlBase1_1) {
+ transStatus = mHidlBase1_1->createComponent_1_1(
name,
hidlListener,
bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -1015,8 +1161,8 @@
*component = std::make_shared<Codec2Client::Component>(c);
hidlListener->component = *component;
});
- } else if (mBase1_0) { // ver1_0
- transStatus = mBase1_0->createComponent(
+ } else if (mHidlBase1_0) { // ver1_0
+ transStatus = mHidlBase1_0->createComponent(
name,
hidlListener,
bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -1059,15 +1205,32 @@
<< status << ".";
}
- (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
+ (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
return status;
}
c2_status_t Codec2Client::createInterface(
const C2String& name,
std::shared_ptr<Codec2Client::Interface>* const interface) {
+ if (mAidlBase) {
+ std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
+ name,
+ &aidlInterface);
+ c2_status_t status = GetC2Status(transStatus, "createInterface");
+ if (status != C2_OK) {
+ return status;
+ } else if (!aidlInterface) {
+ LOG(ERROR) << "createInterface(" << name.c_str()
+ << ") -- null interface.";
+ return C2_CORRUPTED;
+ }
+ interface->reset(new Codec2Client::Interface(aidlInterface));
+ return C2_OK;
+ }
+
c2_status_t status;
- Return<void> transStatus = mBase1_0->createInterface(
+ Return<void> transStatus = mHidlBase1_0->createInterface(
name,
[&status, interface](
c2_hidl::Status s,
@@ -1098,8 +1261,13 @@
c2_status_t Codec2Client::createInputSurface(
std::shared_ptr<InputSurface>* const inputSurface) {
+ if (mAidlBase) {
+ // FIXME
+ return C2_OMITTED;
+ }
+
c2_status_t status;
- Return<void> transStatus = mBase1_0->createInputSurface(
+ Return<void> transStatus = mHidlBase1_0->createInputSurface(
[&status, inputSurface](
c2_hidl::Status s,
const sp<c2_hidl::IInputSurface>& i) {
@@ -1127,7 +1295,29 @@
bool* success) const {
std::vector<C2Component::Traits> traits;
std::string const& serviceName = getServiceName();
- Return<void> transStatus = mBase1_0->listComponents(
+
+ if (mAidlBase) {
+ std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "_listComponents -- transaction failed.";
+ *success = false;
+ } else {
+ traits.resize(aidlTraits.size());
+ *success = true;
+ for (size_t i = 0; i < aidlTraits.size(); ++i) {
+ if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
+ LOG(ERROR) << "_listComponents -- corrupted output.";
+ *success = false;
+ traits.clear();
+ break;
+ }
+ traits[i].owner = serviceName;
+ }
+ }
+ return traits;
+ }
+ Return<void> transStatus = mHidlBase1_0->listComponents(
[&traits, &serviceName](c2_hidl::Status s,
const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
if (s != c2_hidl::Status::OK) {
@@ -1163,12 +1353,12 @@
return C2_OMITTED;
}
-std::shared_ptr<C2ParamReflector>
- Codec2Client::getParamReflector() {
+std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
// TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
// should reflect the HAL API.
- struct SimpleParamReflector : public C2ParamReflector {
- virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
+ struct HidlSimpleParamReflector : public C2ParamReflector {
+ std::unique_ptr<C2StructDescriptor> describe(
+ C2Param::CoreIndex coreIndex) const override {
hidl_vec<c2_hidl::ParamIndex> indices(1);
indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
std::unique_ptr<C2StructDescriptor> descriptor;
@@ -1210,80 +1400,112 @@
return descriptor;
}
- SimpleParamReflector(sp<Base> base)
+ HidlSimpleParamReflector(sp<HidlBase> base)
: mBase(base) { }
- sp<Base> mBase;
+ sp<HidlBase> mBase;
+ };
+ struct AidlSimpleParamReflector : public C2ParamReflector {
+ std::unique_ptr<C2StructDescriptor> describe(
+ C2Param::CoreIndex coreIndex) const override {
+ std::vector<c2_aidl::StructDescriptor> aidlDesc;
+ std::unique_ptr<C2StructDescriptor> descriptor;
+ ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
+ {int32_t(coreIndex.coreIndex())},
+ &aidlDesc);
+ c2_status_t status = GetC2Status(transStatus, "describe");
+ if (status != C2_OK) {
+ descriptor.reset();
+ } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
+ LOG(ERROR) << "describe -- conversion failed.";
+ descriptor.reset();
+ }
+ return descriptor;
+ }
+
+ AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
+ : mBase(base) { }
+
+ std::shared_ptr<AidlBase> mBase;
};
- return std::make_shared<SimpleParamReflector>(mBase1_0);
+ if (mAidlBase) {
+ return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
+ }
+ return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
};
-std::vector<std::string> const& Codec2Client::GetServiceNames() {
- static std::vector<std::string> sServiceNames{[]() {
- using ::android::hardware::media::c2::V1_0::IComponentStore;
- using ::android::hidl::manager::V1_2::IServiceManager;
+std::vector<std::string> Codec2Client::CacheServiceNames() {
+ std::vector<std::string> names;
- while (true) {
- sp<IServiceManager> serviceManager = IServiceManager::getService();
- CHECK(serviceManager) << "Hardware service manager is not running.";
+ if (c2_aidl::utils::IsEnabled()) {
+ // Get AIDL service names
+ AServiceManager_forEachDeclaredInstance(
+ AidlBase::descriptor, &names, [](const char *name, void *context) {
+ std::vector<std::string> *names = (std::vector<std::string> *)context;
+ names->emplace_back(name);
+ });
+ }
- // There are three categories of services based on names.
- std::vector<std::string> defaultNames; // Prefixed with "default"
- std::vector<std::string> vendorNames; // Prefixed with "vendor"
- std::vector<std::string> otherNames; // Others
- Return<void> transResult;
- transResult = serviceManager->listManifestByInterface(
- IComponentStore::descriptor,
- [&defaultNames, &vendorNames, &otherNames](
- hidl_vec<hidl_string> const& instanceNames) {
- for (hidl_string const& instanceName : instanceNames) {
- char const* name = instanceName.c_str();
- if (strncmp(name, "default", 7) == 0) {
- defaultNames.emplace_back(name);
- } else if (strncmp(name, "vendor", 6) == 0) {
- vendorNames.emplace_back(name);
- } else {
- otherNames.emplace_back(name);
- }
- }
- });
- if (transResult.isOk()) {
- // Sort service names in each category.
- std::sort(defaultNames.begin(), defaultNames.end());
- std::sort(vendorNames.begin(), vendorNames.end());
- std::sort(otherNames.begin(), otherNames.end());
+ // Get HIDL service names
+ using ::android::hardware::media::c2::V1_0::IComponentStore;
+ using ::android::hidl::manager::V1_2::IServiceManager;
+ while (true) {
+ sp<IServiceManager> serviceManager = IServiceManager::getService();
+ CHECK(serviceManager) << "Hardware service manager is not running.";
- // Concatenate the three lists in this order: default, vendor,
- // other.
- std::vector<std::string>& names = defaultNames;
- names.reserve(names.size() + vendorNames.size() + otherNames.size());
- names.insert(names.end(),
- std::make_move_iterator(vendorNames.begin()),
- std::make_move_iterator(vendorNames.end()));
- names.insert(names.end(),
- std::make_move_iterator(otherNames.begin()),
- std::make_move_iterator(otherNames.end()));
-
- // Summarize to logcat.
- if (names.empty()) {
- LOG(INFO) << "No Codec2 services declared in the manifest.";
- } else {
- std::stringstream stringOutput;
- stringOutput << "Available Codec2 services:";
- for (std::string const& name : names) {
- stringOutput << " \"" << name << "\"";
- }
- LOG(INFO) << stringOutput.str();
- }
-
- return names;
- }
- LOG(ERROR) << "Could not retrieve the list of service instances of "
- << IComponentStore::descriptor
- << ". Retrying...";
+ Return<void> transResult;
+ transResult = serviceManager->listManifestByInterface(
+ IComponentStore::descriptor,
+ [&names](
+ hidl_vec<hidl_string> const& instanceNames) {
+ names.insert(names.end(), instanceNames.begin(), instanceNames.end());
+ });
+ if (transResult.isOk()) {
+ break;
}
- }()};
+ LOG(ERROR) << "Could not retrieve the list of service instances of "
+ << IComponentStore::descriptor
+ << ". Retrying...";
+ }
+ // Sort service names in each category.
+ std::stable_sort(
+ names.begin(), names.end(),
+ [](const std::string &a, const std::string &b) {
+ // First compare by prefix: default -> vendor -> {everything else}
+ constexpr int DEFAULT = 1;
+ constexpr int VENDOR = 2;
+ constexpr int OTHER = 3;
+ int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
+ (a.compare(0, 6, "vendor") == 0) ? VENDOR :
+ OTHER);
+ int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
+ (b.compare(0, 6, "vendor") == 0) ? VENDOR :
+ OTHER);
+ if (aPrefix != bPrefix) {
+ return aPrefix < bPrefix;
+ }
+ // If the prefix is the same, compare alphabetically
+ return a < b;
+ });
+
+ // Summarize to logcat.
+ if (names.empty()) {
+ LOG(INFO) << "No Codec2 services declared in the manifest.";
+ } else {
+ std::stringstream stringOutput;
+ stringOutput << "Available Codec2 services:";
+ for (std::string const& name : names) {
+ stringOutput << " \"" << name << "\"";
+ }
+ LOG(INFO) << stringOutput.str();
+ }
+
+ return names;
+}
+
+std::vector<std::string> const& Codec2Client::GetServiceNames() {
+ static std::vector<std::string> sServiceNames = CacheServiceNames();
return sServiceNames;
}
@@ -1322,14 +1544,34 @@
std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
std::string const& name = GetServiceNames()[index];
LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
- sp<Base> baseStore = Base::getService(name);
+
+ if (c2_aidl::utils::IsEnabled()) {
+ std::string instanceName =
+ ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
+ if (AServiceManager_isDeclared(instanceName.c_str())) {
+ std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
+ ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
+ CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
+ " inaccessible for unknown reasons.";
+ LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
+ std::shared_ptr<c2_aidl::IConfigurable> configurable;
+ ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
+ CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
+ "does not have IConfigurable.";
+ return std::make_shared<Codec2Client>(baseStore, configurable, index);
+ }
+ }
+
+ std::string instanceName = "android.hardware.media.c2/" + name;
+ sp<HidlBase> baseStore = HidlBase::getService(name);
CHECK(baseStore) << "Codec2 service \"" << name << "\""
" inaccessible for unknown reasons.";
LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
- Return<sp<IConfigurable>> transResult = baseStore->getConfigurable();
+ Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
"does not have IConfigurable.";
- sp<IConfigurable> configurable = static_cast<sp<IConfigurable>>(transResult);
+ sp<c2_hidl::IConfigurable> configurable =
+ static_cast<sp<c2_hidl::IConfigurable>>(transResult);
return std::make_shared<Codec2Client>(baseStore, configurable, index);
}
@@ -1431,8 +1673,7 @@
return status;
}
-std::shared_ptr<Codec2Client::Interface>
- Codec2Client::CreateInterfaceByName(
+std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
const char* interfaceName,
std::shared_ptr<Codec2Client>* owner,
size_t numberOfAttempts) {
@@ -1518,13 +1759,8 @@
return nullptr;
}
-// Codec2Client::Listener
-
-Codec2Client::Listener::~Listener() {
-}
-
// Codec2Client::Interface
-Codec2Client::Interface::Interface(const sp<Base>& base)
+Codec2Client::Interface::Interface(const sp<HidlBase>& base)
: Configurable{
[base]() -> sp<c2_hidl::IConfigurable> {
Return<sp<c2_hidl::IConfigurable>> transResult =
@@ -1534,11 +1770,91 @@
nullptr;
}()
},
- mBase{base} {
+ mHidlBase{base} {
+}
+
+Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
+ : Configurable{
+ [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
+ std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
+ ::ndk::ScopedAStatus transStatus =
+ base->getConfigurable(&aidlConfigurable);
+ return transStatus.isOk() ? aidlConfigurable : nullptr;
+ }()
+ },
+ mAidlBase{base} {
}
// Codec2Client::Component
-Codec2Client::Component::Component(const sp<Base>& base)
+
+class Codec2Client::Component::AidlDeathManager {
+public:
+ AidlDeathManager()
+ : mSeq(0),
+ mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
+ }
+
+ ~AidlDeathManager() = default;
+
+ bool linkToDeath(
+ const std::shared_ptr<Component> &comp,
+ const std::shared_ptr<Listener> &listener,
+ size_t *seqPtr) {
+ std::unique_lock lock(mMutex);
+ size_t seq = mSeq++;
+ if (!mMap.try_emplace(seq, comp, listener).second) {
+ return false;
+ }
+ if (STATUS_OK != AIBinder_linkToDeath(
+ comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
+ mMap.erase(seq);
+ return false;
+ }
+ *seqPtr = seq;
+ return true;
+ }
+
+ void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
+ std::unique_lock lock(mMutex);
+ AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
+ mMap.erase(seq);
+ }
+
+private:
+ std::mutex mMutex;
+ size_t mSeq;
+ typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
+ std::map<size_t, Context> mMap;
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+ bool extractContext(size_t seq, Context *context) {
+ std::unique_lock lock(mMutex);
+ auto node = mMap.extract(seq);
+ if (!node) {
+ return false;
+ }
+ *context = node.mapped();
+ return true;
+ }
+
+ static void OnBinderDied(void *cookie) {
+ size_t seq = size_t(cookie);
+ Context context;
+ if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
+ return;
+ }
+ std::weak_ptr<Component> weakComponent;
+ std::weak_ptr<Listener> weakListener;
+ std::tie(weakComponent, weakListener) = context;
+ if (std::shared_ptr<Listener> listener = weakListener.lock()) {
+ listener->onDeath(weakComponent);
+ } else {
+ LOG(DEBUG) << "onDeath -- listener died.";
+ }
+ }
+};
+
+Codec2Client::Component::Component(const sp<HidlBase>& base)
: Configurable{
[base]() -> sp<c2_hidl::IConfigurable> {
Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1554,14 +1870,14 @@
nullptr;
}()
},
- mBase1_0{base},
- mBase1_1{Base1_1::castFrom(base)},
- mBase1_2{Base1_2::castFrom(base)},
- mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+ mHidlBase1_0{base},
+ mHidlBase1_1{HidlBase1_1::castFrom(base)},
+ mHidlBase1_2{HidlBase1_2::castFrom(base)},
+ mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
}
-Codec2Client::Component::Component(const sp<Base1_1>& base)
+Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
: Configurable{
[base]() -> sp<c2_hidl::IConfigurable> {
Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1577,14 +1893,14 @@
nullptr;
}()
},
- mBase1_0{base},
- mBase1_1{base},
- mBase1_2{Base1_2::castFrom(base)},
- mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+ mHidlBase1_0{base},
+ mHidlBase1_1{base},
+ mHidlBase1_2{HidlBase1_2::castFrom(base)},
+ mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
}
-Codec2Client::Component::Component(const sp<Base1_2>& base)
+Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
: Configurable{
[base]() -> sp<c2_hidl::IConfigurable> {
Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1600,22 +1916,54 @@
nullptr;
}()
},
- mBase1_0{base},
- mBase1_1{base},
- mBase1_2{base},
- mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+ mHidlBase1_0{base},
+ mHidlBase1_1{base},
+ mHidlBase1_2{base},
+ mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
+ mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
+}
+
+Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
+ : Configurable{
+ [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
+ std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
+ ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
+ if (!transStatus.isOk()) {
+ return nullptr;
+ }
+ std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
+ transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
+ return transStatus.isOk() ? aidlConfigurable : nullptr;
+ }()
+ },
+ mAidlBase{base},
+ mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
}
Codec2Client::Component::~Component() {
+ if (mAidlDeathSeq) {
+ GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
+ }
}
c2_status_t Codec2Client::Component::createBlockPool(
C2Allocator::id_t id,
C2BlockPool::local_id_t* blockPoolId,
std::shared_ptr<Codec2Client::Configurable>* configurable) {
+ if (mAidlBase) {
+ c2_aidl::IComponent::BlockPool aidlBlockPool;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(id, &aidlBlockPool);
+ c2_status_t status = GetC2Status(transStatus, "createBlockPool");
+ if (status != C2_OK) {
+ return status;
+ }
+ *blockPoolId = aidlBlockPool.blockPoolId;
+ *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
+ return C2_OK;
+ }
c2_status_t status;
- Return<void> transStatus = mBase1_0->createBlockPool(
+ Return<void> transStatus = mHidlBase1_0->createBlockPool(
static_cast<uint32_t>(id),
[&status, blockPoolId, configurable](
c2_hidl::Status s,
@@ -1640,7 +1988,11 @@
c2_status_t Codec2Client::Component::destroyBlockPool(
C2BlockPool::local_id_t localId) {
- Return<c2_hidl::Status> transResult = mBase1_0->destroyBlockPool(
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
+ return GetC2Status(transStatus, "destroyBlockPool");
+ }
+ Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
static_cast<uint64_t>(localId));
if (!transResult.isOk()) {
LOG(ERROR) << "destroyBlockPool -- transaction failed.";
@@ -1657,12 +2009,21 @@
c2_status_t Codec2Client::Component::queue(
std::list<std::unique_ptr<C2Work>>* const items) {
+ if (mAidlBase) {
+ c2_aidl::WorkBundle workBundle;
+ if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
+ LOG(ERROR) << "queue -- bad input.";
+ return C2_TRANSACTION_FAILED;
+ }
+ ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
+ return GetC2Status(transStatus, "queue");
+ }
c2_hidl::WorkBundle workBundle;
- if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
+ if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
LOG(ERROR) << "queue -- bad input.";
return C2_TRANSACTION_FAILED;
}
- Return<c2_hidl::Status> transStatus = mBase1_0->queue(workBundle);
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
if (!transStatus.isOk()) {
LOG(ERROR) << "queue -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1678,25 +2039,38 @@
c2_status_t Codec2Client::Component::flush(
C2Component::flush_mode_t mode,
std::list<std::unique_ptr<C2Work>>* const flushedWork) {
- (void)mode; // Flush mode isn't supported in HIDL yet.
- c2_status_t status;
- Return<void> transStatus = mBase1_0->flush(
- [&status, flushedWork](
- c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
- status = static_cast<c2_status_t>(s);
- if (status != C2_OK) {
- LOG(DEBUG) << "flush -- call failed: " << status << ".";
- return;
- }
- if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
- status = C2_CORRUPTED;
- } else {
- status = C2_OK;
- }
- });
- if (!transStatus.isOk()) {
- LOG(ERROR) << "flush -- transaction failed.";
- return C2_TRANSACTION_FAILED;
+ (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
+ c2_status_t status = C2_OK;
+ if (mAidlBase) {
+ c2_aidl::WorkBundle workBundle;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
+ c2_status_t status = GetC2Status(transStatus, "flush");
+ if (status != C2_OK) {
+ return status;
+ }
+ if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
+ LOG(DEBUG) << "flush -- flushedWork corrupted.";
+ return C2_CORRUPTED;
+ }
+ } else {
+ Return<void> transStatus = mHidlBase1_0->flush(
+ [&status, flushedWork](
+ c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "flush -- call failed: " << status << ".";
+ return;
+ }
+ if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
+ status = C2_CORRUPTED;
+ } else {
+ status = C2_OK;
+ }
+ });
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "flush -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
}
// Indices of flushed work items.
@@ -1721,7 +2095,12 @@
}
c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
- Return<c2_hidl::Status> transStatus = mBase1_0->drain(
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
+ mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
+ return GetC2Status(transStatus, "drain");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
if (!transStatus.isOk()) {
LOG(ERROR) << "drain -- transaction failed.";
@@ -1736,7 +2115,11 @@
}
c2_status_t Codec2Client::Component::start() {
- Return<c2_hidl::Status> transStatus = mBase1_0->start();
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->start();
+ return GetC2Status(transStatus, "start");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
if (!transStatus.isOk()) {
LOG(ERROR) << "start -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1750,7 +2133,11 @@
}
c2_status_t Codec2Client::Component::stop() {
- Return<c2_hidl::Status> transStatus = mBase1_0->stop();
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
+ return GetC2Status(transStatus, "stop");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
if (!transStatus.isOk()) {
LOG(ERROR) << "stop -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1764,7 +2151,11 @@
}
c2_status_t Codec2Client::Component::reset() {
- Return<c2_hidl::Status> transStatus = mBase1_0->reset();
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
+ return GetC2Status(transStatus, "reset");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
if (!transStatus.isOk()) {
LOG(ERROR) << "reset -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1778,7 +2169,11 @@
}
c2_status_t Codec2Client::Component::release() {
- Return<c2_hidl::Status> transStatus = mBase1_0->release();
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->release();
+ return GetC2Status(transStatus, "release");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
if (!transStatus.isOk()) {
LOG(ERROR) << "release -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1795,11 +2190,25 @@
uint32_t avSyncHwId,
native_handle_t** sidebandHandle) {
*sidebandHandle = nullptr;
- if (!mBase1_1) {
+ if (mAidlBase) {
+ ::aidl::android::hardware::common::NativeHandle handle;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
+ c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
+ if (status != C2_OK) {
+ return status;
+ }
+ if (isAidlNativeHandleEmpty(handle)) {
+ LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
+ } else {
+ *sidebandHandle = dupFromAidl(handle);
+ }
+ return C2_OK;
+ }
+ if (!mHidlBase1_1) {
return C2_OMITTED;
}
c2_status_t status{};
- Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
+ Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
[&status, sidebandHandle](
c2_hidl::Status s, hardware::hidl_handle const& h) {
status = static_cast<c2_status_t>(s);
@@ -1840,8 +2249,8 @@
bqId = 0;
mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
} else {
- mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
- &syncObj : nullptr);
+ mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
+ mHidlBase1_2 ? &syncObj : nullptr);
}
// set consumer bits
@@ -1880,11 +2289,15 @@
ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
generation, (long long)consumerUsage, syncObj ? " sync" : "");
+ if (mAidlBase) {
+ // FIXME
+ return C2_OMITTED;
+ }
Return<c2_hidl::Status> transStatus = syncObj ?
- mBase1_2->setOutputSurfaceWithSyncObj(
+ mHidlBase1_2->setOutputSurfaceWithSyncObj(
static_cast<uint64_t>(blockPoolId),
bqId == 0 ? nullHgbp : igbp, *syncObj) :
- mBase1_0->setOutputSurface(
+ mHidlBase1_0->setOutputSurface(
static_cast<uint64_t>(blockPoolId),
bqId == 0 ? nullHgbp : igbp);
@@ -1923,7 +2336,11 @@
C2BlockPool::local_id_t blockPoolId) {
std::scoped_lock lock(mOutputMutex);
mOutputBufferQueue->stop();
- Return<c2_hidl::Status> transStatus = mBase1_0->setOutputSurface(
+ if (mAidlBase) {
+ // FIXME
+ return;
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
static_cast<uint64_t>(blockPoolId), nullptr);
if (!transStatus.isOk()) {
LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
@@ -1941,8 +2358,12 @@
c2_status_t Codec2Client::Component::connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
std::shared_ptr<InputSurfaceConnection>* connection) {
+ if (mAidlBase) {
+ // FIXME
+ return C2_OMITTED;
+ }
c2_status_t status;
- Return<void> transStatus = mBase1_0->connectToInputSurface(
+ Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
inputSurface->mBase,
[&status, connection](
c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
@@ -1965,8 +2386,12 @@
const sp<HGraphicBufferProducer1>& producer,
const sp<HGraphicBufferSource>& source,
std::shared_ptr<InputSurfaceConnection>* connection) {
+ if (mAidlBase) {
+ LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
+ return C2_OMITTED;
+ }
c2_status_t status;
- Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
+ Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
producer, source,
[&status, connection](
c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
@@ -1986,7 +2411,11 @@
}
c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
- Return<c2_hidl::Status> transStatus = mBase1_0->disconnectFromInputSurface();
+ if (mAidlBase) {
+ // FIXME
+ return C2_OMITTED;
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
if (!transStatus.isOk()) {
LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -2000,6 +2429,12 @@
return status;
}
+Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
+ // This object never gets destructed
+ static AidlDeathManager *sManager = new AidlDeathManager();
+ return sManager;
+}
+
c2_status_t Codec2Client::Component::setDeathListener(
const std::shared_ptr<Component>& component,
const std::shared_ptr<Listener>& listener) {
@@ -2020,12 +2455,20 @@
}
};
+ if (component->mAidlBase) {
+ size_t seq;
+ if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
+ component->mAidlDeathSeq = seq;
+ }
+ return C2_OK;
+ }
+
sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
deathRecipient->base = listener;
deathRecipient->component = component;
component->mDeathRecipient = deathRecipient;
- Return<bool> transResult = component->mBase1_0->linkToDeath(
+ Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
component->mDeathRecipient, 0);
if (!transResult.isOk()) {
LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
diff --git a/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
new file mode 100644
index 0000000..f9c8aca
--- /dev/null
+++ b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/media/c2/BnGraphicBufferAllocator.h>
+
+#include <android-base/unique_fd.h>
+#include <gui/IGraphicBufferProducer.h>
+
+#include <memory>
+
+#include <C2Buffer.h>
+
+namespace aidl::android::hardware::media::c2::implementation {
+
+// forward declarations
+class GraphicsTracker;
+
+struct GraphicBufferAllocator : public BnGraphicBufferAllocator {
+public:
+ // HAL interfaces
+ ::ndk::ScopedAStatus allocate(const IGraphicBufferAllocator::Description& in_desc,
+ IGraphicBufferAllocator::Allocation* _aidl_return) override;
+
+ ::ndk::ScopedAStatus deallocate(int64_t in_id, bool* _aidl_return) override;
+
+ ::ndk::ScopedAStatus getWaitableFds(
+ IGraphicBufferAllocator::WaitableFds* _aidl_return) override;
+
+ /**
+ * Configuring Surface/BufferQueue for the interface.
+ *
+ * Configure Surface, generation # and max dequeueBuffer() count for
+ * allocate interface.
+ *
+ * @param igbp Surface where to allocate.
+ * @param generation Generation # for allocations.
+ * @param maxDequeueBufferCount
+ * Maximum # of pending allocations.
+ */
+ bool configure(const ::android::sp<::android::IGraphicBufferProducer>& igbp,
+ uint32_t generation,
+ int maxDequeueBufferCount);
+
+ /**
+ * Update max dequeue buffer count of BufferQueue.
+ *
+ * BufferQueue does not update this value if count is smaller
+ * than the currently dequeued count.
+ * TODO: better to update the value inside this interface.
+ * for return value inspection from BQ, also for delayed updates.
+ *
+ * @param count the new value to update
+ */
+ void updateMaxDequeueBufferCount(int count);
+
+ void reset();
+
+ /**
+ * Create a listener for buffer being released.
+ *
+ * Surface will register this listener and notify whenever the consumer
+ * releases a buffer.
+ *
+ * @param generation generation # for the BufferQueue.
+ * @return IProducerListener can be used when connect# to Surface.
+ */
+ const ::android::sp<::android::IProducerListener> createReleaseListener(
+ uint32_t generation);
+
+ /**
+ * Notifies a buffer being released.
+ *
+ * @param generation generation # for the BufferQueue.
+ */
+ void onBufferReleased(uint32_t generation);
+
+ /**
+ * Allocates a buffer.
+ *
+ * @param width width of the requested buffer.
+ * @param height height of the requested buffer.
+ * @param format format of the requested buffer.
+ * @param usage usage of the requested buffer.
+ * @param buf out param for created buffer.
+ * @param fence out param for a pending fence.
+ *
+ * @return OK When an allocation was created.
+ * C2_BAD_STATE Client is not in the state for allocating
+ * C2_BLOCKING operation is blocked. Waitable fds can be
+ * used to know when it unblocks.
+ * C2_CORRUPTED Failed with a serious reason.
+ */
+ c2_status_t allocate(uint32_t width, uint32_t height,
+ ::android::PixelFormat format, uint64_t usage,
+ AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence);
+
+ /**
+ * De-allocate a buffer.
+ *
+ * @param id unique id for a buffer.
+ * @param fence write fence if it's deallocated due to
+ * cancellation of displaying
+ */
+ bool deallocate(const uint64_t id, const ::android::sp<::android::Fence> &fence);
+
+ /**
+ * Display a graphic buffer to BufferQueue.
+ *
+ * @param block block to display to Surface.
+ * @param input input parameter for displaying.
+ * @param output out parameter from Surface.
+ */
+ c2_status_t displayBuffer(
+ const C2ConstGraphicBlock& block,
+ const ::android::IGraphicBufferProducer::QueueBufferInput& input,
+ ::android::IGraphicBufferProducer::QueueBufferOutput *output);
+
+ ~GraphicBufferAllocator();
+
+ /**
+ * Create the interface.
+ *
+ * The interface and codec instance's relationship is 1 to 1.
+ * The interface will be cretaed in the beginning of Codec createion. And
+ * lives until the instance destroyed.
+ *
+ * @param maxDequeueCount Initial max allocatable count
+ */
+ static std::shared_ptr<GraphicBufferAllocator> CreateGraphicBufferAllocator(
+ int maxDequeueCount);
+private:
+ GraphicBufferAllocator(int maxDequeueCount);
+
+ std::shared_ptr<GraphicsTracker> mGraphicsTracker;
+
+ friend class ::ndk::SharedRefBase;
+};
+
+} // namespace aidl::android::hardware::media::c2::implementation
diff --git a/media/codec2/hal/client/include/codec2/hidl/client.h b/media/codec2/hal/client/include/codec2/hidl/client.h
index 6fa19b0..0c7dd77 100644
--- a/media/codec2/hal/client/include/codec2/hidl/client.h
+++ b/media/codec2/hal/client/include/codec2/hidl/client.h
@@ -95,6 +95,11 @@
struct IClientManager;
} // namespace android::hardware::media::bufferpool::V2_0
+namespace aidl::android::hardware::media::bufferpool2 {
+class IClientManager;
+} // namespace aidl::android::hardware::media::c2
+
+
namespace android::hardware::graphics::bufferqueue::V1_0 {
struct IGraphicBufferProducer;
} // android::hardware::graphics::bufferqueue::V1_0
@@ -173,12 +178,12 @@
struct Codec2Client : public Codec2ConfigurableClient {
- typedef ::android::hardware::media::c2::V1_0::IComponentStore Base1_0;
- typedef ::android::hardware::media::c2::V1_1::IComponentStore Base1_1;
- typedef ::android::hardware::media::c2::V1_2::IComponentStore Base1_2;
- typedef Base1_0 Base;
+ typedef ::android::hardware::media::c2::V1_0::IComponentStore HidlBase1_0;
+ typedef ::android::hardware::media::c2::V1_1::IComponentStore HidlBase1_1;
+ typedef ::android::hardware::media::c2::V1_2::IComponentStore HidlBase1_2;
+ typedef HidlBase1_0 HidlBase;
- typedef ::android::hardware::media::c2::V1_0::IConfigurable IConfigurable;
+ typedef ::aidl::android::hardware::media::c2::IComponentStore AidlBase;
struct Listener;
@@ -194,10 +199,11 @@
typedef Codec2Client Store;
- sp<Base> const& getBase() const;
- sp<Base1_0> const& getBase1_0() const;
- sp<Base1_1> const& getBase1_1() const;
- sp<Base1_2> const& getBase1_2() const;
+ sp<HidlBase> const& getHidlBase() const;
+ sp<HidlBase1_0> const& getHidlBase1_0() const;
+ sp<HidlBase1_1> const& getHidlBase1_1() const;
+ sp<HidlBase1_2> const& getHidlBase1_2() const;
+ ::ndk::SpAIBinder getAidlBase() const;
std::string const& getServiceName() const;
@@ -266,14 +272,19 @@
// base and/or configurable cannot be null.
Codec2Client(
- sp<Base> const& base,
- sp<IConfigurable> const& configurable,
+ sp<HidlBase> const& base,
+ sp<Codec2ConfigurableClient::HidlBase> const& configurable,
+ size_t serviceIndex);
+ Codec2Client(
+ std::shared_ptr<AidlBase> const& base,
+ std::shared_ptr<Codec2ConfigurableClient::AidlBase> const& configurable,
size_t serviceIndex);
protected:
- sp<Base1_0> mBase1_0;
- sp<Base1_1> mBase1_1;
- sp<Base1_2> mBase1_2;
+ sp<HidlBase1_0> mHidlBase1_0;
+ sp<HidlBase1_1> mHidlBase1_1;
+ sp<HidlBase1_2> mHidlBase1_2;
+ std::shared_ptr<AidlBase> mAidlBase;
// Finds the first store where the predicate returns C2_OK and returns the
// last predicate result. The predicate will be tried on all stores. The
@@ -301,8 +312,11 @@
mutable std::vector<C2Component::Traits> mTraitsList;
sp<::android::hardware::media::bufferpool::V2_0::IClientManager>
- mHostPoolManager;
+ mHidlHostPoolManager;
+ std::shared_ptr<::aidl::android::hardware::media::bufferpool2::IClientManager>
+ mAidlHostPoolManager;
+ static std::vector<std::string> CacheServiceNames();
static std::shared_ptr<Codec2Client> _CreateFromIndex(size_t index);
std::vector<C2Component::Traits> _listComponents(bool* success) const;
@@ -312,12 +326,15 @@
struct Codec2Client::Interface : public Codec2Client::Configurable {
- typedef ::android::hardware::media::c2::V1_0::IComponentInterface Base;
+ typedef ::android::hardware::media::c2::V1_0::IComponentInterface HidlBase;
+ typedef ::aidl::android::hardware::media::c2::IComponentInterface AidlBase;
- Interface(const sp<Base>& base);
+ Interface(const sp<HidlBase>& base);
+ Interface(const std::shared_ptr<AidlBase>& base);
protected:
- sp<Base> mBase;
+ sp<HidlBase> mHidlBase;
+ std::shared_ptr<AidlBase> mAidlBase;
};
struct Codec2Client::Listener {
@@ -356,16 +373,17 @@
int32_t slotId,
int64_t timestampNs) = 0;
- virtual ~Listener();
-
+ virtual ~Listener() = default;
};
struct Codec2Client::Component : public Codec2Client::Configurable {
- typedef ::android::hardware::media::c2::V1_0::IComponent Base1_0;
- typedef ::android::hardware::media::c2::V1_1::IComponent Base1_1;
- typedef ::android::hardware::media::c2::V1_2::IComponent Base1_2;
- typedef Base1_0 Base;
+ typedef ::android::hardware::media::c2::V1_0::IComponent HidlBase1_0;
+ typedef ::android::hardware::media::c2::V1_1::IComponent HidlBase1_1;
+ typedef ::android::hardware::media::c2::V1_2::IComponent HidlBase1_2;
+ typedef HidlBase1_0 HidlBase;
+
+ typedef ::aidl::android::hardware::media::c2::IComponent AidlBase;
c2_status_t createBlockPool(
C2Allocator::id_t id,
@@ -469,19 +487,23 @@
c2_status_t disconnectFromInputSurface();
// base cannot be null.
- Component(const sp<Base>& base);
- Component(const sp<Base1_1>& base);
- Component(const sp<Base1_2>& base);
+ Component(const sp<HidlBase>& base);
+ Component(const sp<HidlBase1_1>& base);
+ Component(const sp<HidlBase1_2>& base);
+ Component(const std::shared_ptr<AidlBase>& base);
~Component();
protected:
- sp<Base1_0> mBase1_0;
- sp<Base1_1> mBase1_1;
- sp<Base1_2> mBase1_2;
+ sp<HidlBase1_0> mHidlBase1_0;
+ sp<HidlBase1_1> mHidlBase1_1;
+ sp<HidlBase1_2> mHidlBase1_2;
+ std::shared_ptr<AidlBase> mAidlBase;
- struct BufferPoolSender;
- std::unique_ptr<BufferPoolSender> mBufferPoolSender;
+ struct HidlBufferPoolSender;
+ struct AidlBufferPoolSender;
+ std::unique_ptr<HidlBufferPoolSender> mHidlBufferPoolSender;
+ std::unique_ptr<AidlBufferPoolSender> mAidlBufferPoolSender;
struct OutputBufferQueue;
std::unique_ptr<OutputBufferQueue> mOutputBufferQueue;
@@ -491,6 +513,10 @@
// In order to prevent the race condition mutex is added.
std::mutex mOutputMutex;
+ class AidlDeathManager;
+ static AidlDeathManager *GetAidlDeathManager();
+ std::optional<size_t> mAidlDeathSeq;
+
static c2_status_t setDeathListener(
const std::shared_ptr<Component>& component,
const std::shared_ptr<Listener>& listener);
@@ -499,16 +525,15 @@
friend struct Codec2Client;
struct HidlListener;
+ struct AidlListener;
void handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> &workItems);
-
};
struct Codec2Client::InputSurface : public Codec2Client::Configurable {
public:
typedef ::android::hardware::media::c2::V1_0::IInputSurface Base;
- typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection
- ConnectionBase;
+ typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection ConnectionBase;
typedef Codec2Client::InputSurfaceConnection Connection;
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/Android.bp b/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
index 0ae133c..1c5c7d6 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
@@ -29,10 +29,8 @@
srcs: [
"res/bbb_aac_stereo_128kbps_48000hz.aac",
"res/bbb_aac_stereo_128kbps_48000hz.info",
- "res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info",
"res/bbb_amrwb_1ch_14kbps_16000hz.amrwb",
"res/bbb_amrwb_1ch_14kbps_16000hz.info",
- "res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info",
"res/bbb_flac_stereo_680kbps_48000hz.flac",
"res/bbb_flac_stereo_680kbps_48000hz.info",
"res/bbb_g711alaw_1ch_8khz.info",
@@ -43,7 +41,6 @@
"res/bbb_gsm_1ch_8khz_13kbps.raw",
"res/bbb_mp3_stereo_192kbps_48000hz.info",
"res/bbb_mp3_stereo_192kbps_48000hz.mp3",
- "res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info",
"res/bbb_opus_stereo_128kbps_48000hz.info",
"res/bbb_opus_stereo_128kbps_48000hz.opus",
"res/bbb_raw_1ch_8khz_s32le.info",
@@ -52,7 +49,6 @@
"res/bbb_vorbis_stereo_128kbps_48000hz.vorbis",
"res/sine_amrnb_1ch_12kbps_8000hz.amrnb",
"res/sine_amrnb_1ch_12kbps_8000hz.info",
- "res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info",
],
}
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index d47ef67..222c3d2 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -44,17 +44,9 @@
std::vector<CompToFiles> gCompToFiles = {
{"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.info"},
- {"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac",
- "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"},
{"mpeg", "bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz.info"},
- {"mpeg", "bbb_mp3_stereo_192kbps_48000hz.mp3",
- "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"},
{"3gpp", "sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz.info"},
- {"3gpp", "sine_amrnb_1ch_12kbps_8000hz.amrnb",
- "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"},
{"amr-wb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz.info"},
- {"amr-wb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
- "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"},
{"vorbis", "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
"bbb_vorbis_stereo_128kbps_48000hz.info"},
{"opus", "bbb_opus_stereo_128kbps_48000hz.opus", "bbb_opus_stereo_128kbps_48000hz.info"},
@@ -341,7 +333,7 @@
ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
}
int64_t timestamp = (*Info)[frameID].timestamp;
- if ((*Info)[frameID].flags) flags = 1u << ((*Info)[frameID].flags - 1);
+ flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0;
if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
flags |= C2FrameData::FLAG_END_OF_STREAM;
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
index a22f8cf..6c04683 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
@@ -23,10 +23,8 @@
<!-- Files used for audio testing -->
<option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.aac" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.aac" />
<option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.info" />
- <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz_multi_frame.info" />
<option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.amrwb" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.amrwb" />
<option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.info" />
- <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" />
<option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.flac" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.flac" />
<option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.info" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.info" />
<option name="push-file" key="bbb_g711alaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.info" />
@@ -37,7 +35,6 @@
<option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.raw" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.raw" />
<option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.info" />
<option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.mp3" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.mp3" />
- <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" />
<option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.info" />
<option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.opus" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.opus" />
<option name="push-file" key="bbb_raw_1ch_8khz_s32le.info" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.info" />
@@ -46,7 +43,6 @@
<option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.vorbis" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis" />
<option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.amrnb" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.amrnb" />
<option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.info" />
- <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" />
</target_preparer>
@@ -55,4 +51,4 @@
<option name="module-name" value="vts_media_c2_v1_0_audio_dec_test" />
<option name="native-test-flag" value="-P /data/local/tmp/media/" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index 2222aaf..ecab0cb 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -28,6 +28,8 @@
#include <fstream>
#define FLAG_NON_DISPLAY_FRAME (1 << 4)
+#define FLAG_CONFIG_DATA (1 << 5)
+
#define MAX_RETRY 20
#define TIME_OUT 400ms
#define MAX_INPUT_BUFFERS 8
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
deleted file mode 100644
index 182af20..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
+++ /dev/null
@@ -1,443 +0,0 @@
-5 32 0
-5 32 0
-337 1 0
-322 1 21333
-279 1 42666
-563 1 64000
-635 1 106666
-634 1 149333
-629 1 192000
-680 1 234666
-688 1 277333
-1036 1 320000
-1040 1 384000
-1009 1 448000
-1020 1 512000
-1357 1 576000
-1353 1 661333
-1351 1 746666
-1351 1 832000
-343 1 917333
-335 1 938666
-339 1 960000
-342 1 981333
-348 1 1002666
-350 1 1024000
-351 1 1045333
-342 1 1066666
-366 1 1088000
-340 1 1109333
-354 1 1130666
-340 1 1152000
-334 1 1173333
-338 1 1194666
-340 1 1216000
-351 1 1237333
-346 1 1258666
-331 1 1280000
-321 1 1301333
-343 1 1322666
-342 1 1344000
-345 1 1365333
-326 1 1386666
-342 1 1408000
-356 1 1429333
-351 1 1450666
-343 1 1472000
-347 1 1493333
-349 1 1514666
-350 1 1536000
-330 1 1557333
-341 1 1578666
-340 1 1600000
-330 1 1621333
-340 1 1642666
-335 1 1664000
-344 1 1685333
-359 1 1706666
-337 1 1728000
-346 1 1749333
-330 1 1770666
-351 1 1792000
-355 1 1813333
-352 1 1834666
-325 1 1856000
-342 1 1877333
-327 1 1898666
-349 1 1920000
-326 1 1941333
-337 1 1962666
-378 1 1984000
-321 1 2005333
-319 1 2026666
-346 1 2048000
-352 1 2069333
-349 1 2090666
-331 1 2112000
-330 1 2133333
-329 1 2154666
-333 1 2176000
-367 1 2197333
-362 1 2218666
-337 1 2240000
-337 1 2261333
-360 1 2282666
-333 1 2304000
-317 1 2325333
-344 1 2346666
-335 1 2368000
-337 1 2389333
-349 1 2410666
-336 1 2432000
-348 1 2453333
-349 1 2474666
-342 1 2496000
-359 1 2517333
-340 1 2538666
-340 1 2560000
-348 1 2581333
-334 1 2602666
-328 1 2624000
-341 1 2645333
-339 1 2666666
-337 1 2688000
-350 1 2709333
-326 1 2730666
-360 1 2752000
-344 1 2773333
-340 1 2794666
-343 1 2816000
-361 1 2837333
-329 1 2858666
-345 1 2880000
-345 1 2901333
-330 1 2922666
-342 1 2944000
-344 1 2965333
-330 1 2986666
-329 1 3008000
-335 1 3029333
-366 1 3050666
-328 1 3072000
-349 1 3093333
-339 1 3114666
-340 1 3136000
-335 1 3157333
-327 1 3178666
-348 1 3200000
-339 1 3221333
-334 1 3242666
-350 1 3264000
-325 1 3285333
-361 1 3306666
-338 1 3328000
-350 1 3349333
-353 1 3370666
-327 1 3392000
-346 1 3413333
-348 1 3434666
-339 1 3456000
-342 1 3477333
-334 1 3498666
-350 1 3520000
-354 1 3541333
-363 1 3562666
-322 1 3584000
-337 1 3605333
-355 1 3626666
-329 1 3648000
-324 1 3669333
-338 1 3690666
-356 1 3712000
-330 1 3733333
-321 1 3754666
-337 1 3776000
-345 1 3797333
-335 1 3818666
-348 1 3840000
-342 1 3861333
-348 1 3882666
-335 1 3904000
-344 1 3925333
-357 1 3946666
-368 1 3968000
-324 1 3989333
-343 1 4010666
-341 1 4032000
-329 1 4053333
-356 1 4074666
-317 1 4096000
-351 1 4117333
-340 1 4138666
-340 1 4160000
-332 1 4181333
-355 1 4202666
-357 1 4224000
-327 1 4245333
-338 1 4266666
-323 1 4288000
-346 1 4309333
-352 1 4330666
-347 1 4352000
-343 1 4373333
-311 1 4394666
-338 1 4416000
-365 1 4437333
-349 1 4458666
-327 1 4480000
-355 1 4501333
-319 1 4522666
-349 1 4544000
-351 1 4565333
-337 1 4586666
-340 1 4608000
-349 1 4629333
-316 1 4650666
-344 1 4672000
-334 1 4693333
-344 1 4714666
-347 1 4736000
-348 1 4757333
-334 1 4778666
-338 1 4800000
-331 1 4821333
-344 1 4842666
-342 1 4864000
-336 1 4885333
-326 1 4906666
-364 1 4928000
-350 1 4949333
-350 1 4970666
-363 1 4992000
-358 1 5013333
-305 1 5034666
-344 1 5056000
-346 1 5077333
-342 1 5098666
-330 1 5120000
-318 1 5141333
-361 1 5162666
-354 1 5184000
-313 1 5205333
-330 1 5226666
-350 1 5248000
-347 1 5269333
-346 1 5290666
-357 1 5312000
-325 1 5333333
-335 1 5354666
-331 1 5376000
-366 1 5397333
-329 1 5418666
-349 1 5440000
-371 1 5461333
-326 1 5482666
-333 1 5504000
-319 1 5525333
-327 1 5546666
-353 1 5568000
-356 1 5589333
-348 1 5610666
-338 1 5632000
-331 1 5653333
-341 1 5674666
-362 1 5696000
-326 1 5717333
-359 1 5738666
-315 1 5760000
-376 1 5781333
-343 1 5802666
-354 1 5824000
-353 1 5845333
-344 1 5866666
-334 1 5888000
-345 1 5909333
-355 1 5930666
-322 1 5952000
-334 1 5973333
-353 1 5994666
-338 1 6016000
-351 1 6037333
-334 1 6058666
-339 1 6080000
-345 1 6101333
-347 1 6122666
-355 1 6144000
-312 1 6165333
-352 1 6186666
-354 1 6208000
-318 1 6229333
-344 1 6250666
-363 1 6272000
-321 1 6293333
-339 1 6314666
-356 1 6336000
-334 1 6357333
-354 1 6378666
-325 1 6400000
-321 1 6421333
-341 1 6442666
-337 1 6464000
-351 1 6485333
-343 1 6506666
-341 1 6528000
-344 1 6549333
-341 1 6570666
-364 1 6592000
-319 1 6613333
-348 1 6634666
-332 1 6656000
-333 1 6677333
-343 1 6698666
-348 1 6720000
-347 1 6741333
-350 1 6762666
-342 1 6784000
-341 1 6805333
-326 1 6826666
-351 1 6848000
-329 1 6869333
-323 1 6890666
-350 1 6912000
-361 1 6933333
-326 1 6954666
-345 1 6976000
-345 1 6997333
-311 1 7018666
-349 1 7040000
-358 1 7061333
-352 1 7082666
-347 1 7104000
-364 1 7125333
-328 1 7146666
-318 1 7168000
-351 1 7189333
-340 1 7210666
-341 1 7232000
-355 1 7253333
-336 1 7274666
-352 1 7296000
-341 1 7317333
-334 1 7338666
-348 1 7360000
-342 1 7381333
-335 1 7402666
-342 1 7424000
-359 1 7445333
-349 1 7466666
-329 1 7488000
-356 1 7509333
-292 1 7530666
-316 1 7552000
-318 1 7573333
-320 1 7594666
-342 1 7616000
-285 1 7637333
-326 1 7658666
-352 1 7680000
-392 1 7701333
-364 1 7722666
-384 1 7744000
-334 1 7765333
-317 1 7786666
-326 1 7808000
-373 1 7829333
-354 1 7850666
-329 1 7872000
-347 1 7893333
-353 1 7914666
-338 1 7936000
-317 1 7957333
-354 1 7978666
-345 1 8000000
-350 1 8021333
-351 1 8042666
-332 1 8064000
-358 1 8085333
-315 1 8106666
-336 1 8128000
-358 1 8149333
-343 1 8170666
-319 1 8192000
-370 1 8213333
-344 1 8234666
-361 1 8256000
-343 1 8277333
-337 1 8298666
-354 1 8320000
-332 1 8341333
-348 1 8362666
-328 1 8384000
-345 1 8405333
-340 1 8426666
-346 1 8448000
-341 1 8469333
-344 1 8490666
-342 1 8512000
-341 1 8533333
-345 1 8554666
-337 1 8576000
-335 1 8597333
-335 1 8618666
-340 1 8640000
-345 1 8661333
-341 1 8682666
-342 1 8704000
-338 1 8725333
-343 1 8746666
-336 1 8768000
-338 1 8789333
-353 1 8810666
-339 1 8832000
-329 1 8853333
-349 1 8874666
-323 1 8896000
-351 1 8917333
-359 1 8938666
-357 1 8960000
-341 1 8981333
-333 1 9002666
-335 1 9024000
-328 1 9045333
-347 1 9066666
-343 1 9088000
-369 1 9109333
-331 1 9130666
-344 1 9152000
-330 1 9173333
-346 1 9194666
-337 1 9216000
-341 1 9237333
-338 1 9258666
-329 1 9280000
-360 1 9301333
-336 1 9322666
-341 1 9344000
-341 1 9365333
-345 1 9386666
-351 1 9408000
-349 1 9429333
-336 1 9450666
-326 1 9472000
-349 1 9493333
-343 1 9514666
-357 1 9536000
-342 1 9557333
-325 1 9578666
-346 1 9600000
-326 1 9621333
-402 1 9642666
-331 1 9664000
-339 1 9685333
-371 1 9706666
-314 1 9728000
-310 1 9749333
-364 1 9770666
-338 1 9792000
-339 1 9813333
-337 1 9834666
-355 1 9856000
-351 1 9877333
-332 1 9898666
-316 1 9920000
-474 1 9941333
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
deleted file mode 100644
index c420009..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
+++ /dev/null
@@ -1,460 +0,0 @@
-41 1 0
-41 1 20000
-82 1 40000
-82 1 80000
-82 1 120000
-82 1 160000
-82 1 200000
-82 1 240000
-82 1 280000
-82 1 320000
-82 1 360000
-123 1 400000
-123 1 460000
-123 1 520000
-123 1 580000
-123 1 640000
-164 1 700000
-164 1 780000
-164 1 860000
-164 1 940000
-164 1 1020000
-41 1 1100000
-41 1 1120000
-41 1 1140000
-41 1 1160000
-41 1 1180000
-41 1 1200000
-41 1 1220000
-41 1 1240000
-41 1 1260000
-41 1 1280000
-41 1 1300000
-41 1 1320000
-41 1 1340000
-41 1 1360000
-41 1 1380000
-41 1 1400000
-41 1 1420000
-41 1 1440000
-41 1 1460000
-41 1 1480000
-41 1 1500000
-41 1 1520000
-41 1 1540000
-41 1 1560000
-41 1 1580000
-41 1 1600000
-41 1 1620000
-41 1 1640000
-41 1 1660000
-41 1 1680000
-41 1 1700000
-41 1 1720000
-41 1 1740000
-41 1 1760000
-41 1 1780000
-41 1 1800000
-41 1 1820000
-41 1 1840000
-41 1 1860000
-41 1 1880000
-41 1 1900000
-41 1 1920000
-41 1 1940000
-41 1 1960000
-41 1 1980000
-41 1 2000000
-41 1 2020000
-41 1 2040000
-41 1 2060000
-41 1 2080000
-41 1 2100000
-41 1 2120000
-41 1 2140000
-41 1 2160000
-41 1 2180000
-41 1 2200000
-41 1 2220000
-41 1 2240000
-41 1 2260000
-41 1 2280000
-41 1 2300000
-41 1 2320000
-41 1 2340000
-41 1 2360000
-41 1 2380000
-41 1 2400000
-41 1 2420000
-41 1 2440000
-41 1 2460000
-41 1 2480000
-41 1 2500000
-41 1 2520000
-41 1 2540000
-41 1 2560000
-41 1 2580000
-41 1 2600000
-41 1 2620000
-41 1 2640000
-41 1 2660000
-41 1 2680000
-41 1 2700000
-41 1 2720000
-41 1 2740000
-41 1 2760000
-41 1 2780000
-41 1 2800000
-41 1 2820000
-41 1 2840000
-41 1 2860000
-41 1 2880000
-41 1 2900000
-41 1 2920000
-41 1 2940000
-41 1 2960000
-41 1 2980000
-41 1 3000000
-41 1 3020000
-41 1 3040000
-41 1 3060000
-41 1 3080000
-41 1 3100000
-41 1 3120000
-41 1 3140000
-41 1 3160000
-41 1 3180000
-41 1 3200000
-41 1 3220000
-41 1 3240000
-41 1 3260000
-41 1 3280000
-41 1 3300000
-41 1 3320000
-41 1 3340000
-41 1 3360000
-41 1 3380000
-41 1 3400000
-41 1 3420000
-41 1 3440000
-41 1 3460000
-41 1 3480000
-41 1 3500000
-41 1 3520000
-41 1 3540000
-41 1 3560000
-41 1 3580000
-41 1 3600000
-41 1 3620000
-41 1 3640000
-41 1 3660000
-41 1 3680000
-41 1 3700000
-41 1 3720000
-41 1 3740000
-41 1 3760000
-41 1 3780000
-41 1 3800000
-41 1 3820000
-41 1 3840000
-41 1 3860000
-41 1 3880000
-41 1 3900000
-41 1 3920000
-41 1 3940000
-41 1 3960000
-41 1 3980000
-41 1 4000000
-41 1 4020000
-41 1 4040000
-41 1 4060000
-41 1 4080000
-41 1 4100000
-41 1 4120000
-41 1 4140000
-41 1 4160000
-41 1 4180000
-41 1 4200000
-41 1 4220000
-41 1 4240000
-41 1 4260000
-41 1 4280000
-41 1 4300000
-41 1 4320000
-41 1 4340000
-41 1 4360000
-41 1 4380000
-41 1 4400000
-41 1 4420000
-41 1 4440000
-41 1 4460000
-41 1 4480000
-41 1 4500000
-41 1 4520000
-41 1 4540000
-41 1 4560000
-41 1 4580000
-41 1 4600000
-41 1 4620000
-41 1 4640000
-41 1 4660000
-41 1 4680000
-41 1 4700000
-41 1 4720000
-41 1 4740000
-41 1 4760000
-41 1 4780000
-41 1 4800000
-41 1 4820000
-41 1 4840000
-41 1 4860000
-41 1 4880000
-41 1 4900000
-41 1 4920000
-41 1 4940000
-41 1 4960000
-41 1 4980000
-41 1 5000000
-41 1 5020000
-41 1 5040000
-41 1 5060000
-41 1 5080000
-41 1 5100000
-41 1 5120000
-41 1 5140000
-41 1 5160000
-41 1 5180000
-41 1 5200000
-41 1 5220000
-41 1 5240000
-41 1 5260000
-41 1 5280000
-41 1 5300000
-41 1 5320000
-41 1 5340000
-41 1 5360000
-41 1 5380000
-41 1 5400000
-41 1 5420000
-41 1 5440000
-41 1 5460000
-41 1 5480000
-41 1 5500000
-41 1 5520000
-41 1 5540000
-41 1 5560000
-41 1 5580000
-41 1 5600000
-41 1 5620000
-41 1 5640000
-41 1 5660000
-41 1 5680000
-41 1 5700000
-41 1 5720000
-41 1 5740000
-41 1 5760000
-41 1 5780000
-41 1 5800000
-41 1 5820000
-41 1 5840000
-41 1 5860000
-41 1 5880000
-41 1 5900000
-41 1 5920000
-41 1 5940000
-41 1 5960000
-41 1 5980000
-41 1 6000000
-41 1 6020000
-41 1 6040000
-41 1 6060000
-41 1 6080000
-41 1 6100000
-41 1 6120000
-41 1 6140000
-41 1 6160000
-41 1 6180000
-41 1 6200000
-41 1 6220000
-41 1 6240000
-41 1 6260000
-41 1 6280000
-41 1 6300000
-41 1 6320000
-41 1 6340000
-41 1 6360000
-41 1 6380000
-41 1 6400000
-41 1 6420000
-41 1 6440000
-41 1 6460000
-41 1 6480000
-41 1 6500000
-41 1 6520000
-41 1 6540000
-41 1 6560000
-41 1 6580000
-41 1 6600000
-41 1 6620000
-41 1 6640000
-41 1 6660000
-41 1 6680000
-41 1 6700000
-41 1 6720000
-41 1 6740000
-41 1 6760000
-41 1 6780000
-41 1 6800000
-41 1 6820000
-41 1 6840000
-41 1 6860000
-41 1 6880000
-41 1 6900000
-41 1 6920000
-41 1 6940000
-41 1 6960000
-41 1 6980000
-41 1 7000000
-41 1 7020000
-41 1 7040000
-41 1 7060000
-41 1 7080000
-41 1 7100000
-41 1 7120000
-41 1 7140000
-41 1 7160000
-41 1 7180000
-41 1 7200000
-41 1 7220000
-41 1 7240000
-41 1 7260000
-41 1 7280000
-41 1 7300000
-41 1 7320000
-41 1 7340000
-41 1 7360000
-41 1 7380000
-41 1 7400000
-41 1 7420000
-41 1 7440000
-41 1 7460000
-41 1 7480000
-41 1 7500000
-41 1 7520000
-41 1 7540000
-41 1 7560000
-41 1 7580000
-41 1 7600000
-41 1 7620000
-41 1 7640000
-41 1 7660000
-41 1 7680000
-41 1 7700000
-41 1 7720000
-41 1 7740000
-41 1 7760000
-41 1 7780000
-41 1 7800000
-41 1 7820000
-41 1 7840000
-41 1 7860000
-41 1 7880000
-41 1 7900000
-41 1 7920000
-41 1 7940000
-41 1 7960000
-41 1 7980000
-41 1 8000000
-41 1 8020000
-41 1 8040000
-41 1 8060000
-41 1 8080000
-41 1 8100000
-41 1 8120000
-41 1 8140000
-41 1 8160000
-41 1 8180000
-41 1 8200000
-41 1 8220000
-41 1 8240000
-41 1 8260000
-41 1 8280000
-41 1 8300000
-41 1 8320000
-41 1 8340000
-41 1 8360000
-41 1 8380000
-41 1 8400000
-41 1 8420000
-41 1 8440000
-41 1 8460000
-41 1 8480000
-41 1 8500000
-41 1 8520000
-41 1 8540000
-41 1 8560000
-41 1 8580000
-41 1 8600000
-41 1 8620000
-41 1 8640000
-41 1 8660000
-41 1 8680000
-41 1 8700000
-41 1 8720000
-41 1 8740000
-41 1 8760000
-41 1 8780000
-41 1 8800000
-41 1 8820000
-41 1 8840000
-41 1 8860000
-41 1 8880000
-41 1 8900000
-41 1 8920000
-41 1 8940000
-41 1 8960000
-41 1 8980000
-41 1 9000000
-41 1 9020000
-41 1 9040000
-41 1 9060000
-41 1 9080000
-41 1 9100000
-41 1 9120000
-41 1 9140000
-41 1 9160000
-41 1 9180000
-41 1 9200000
-41 1 9220000
-41 1 9240000
-41 1 9260000
-41 1 9280000
-41 1 9300000
-41 1 9320000
-41 1 9340000
-41 1 9360000
-41 1 9380000
-41 1 9400000
-41 1 9420000
-41 1 9440000
-41 1 9460000
-41 1 9480000
-41 1 9500000
-41 1 9520000
-41 1 9540000
-41 1 9560000
-41 1 9580000
-41 1 9600000
-41 1 9620000
-41 1 9640000
-41 1 9660000
-41 1 9680000
-41 1 9700000
-41 1 9720000
-41 1 9740000
-41 1 9760000
-41 1 9780000
-41 1 9800000
-41 1 9820000
-41 1 9840000
-41 1 9860000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
deleted file mode 100644
index 575c75f..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
+++ /dev/null
@@ -1,385 +0,0 @@
-576 1 0
-576 1 24000
-1152 1 48000
-1152 1 96000
-1152 1 144000
-1152 1 192000
-1728 1 240000
-1728 1 312000
-1728 1 384000
-1728 1 456000
-1728 1 528000
-2304 1 600000
-2304 1 696000
-2304 1 792000
-2304 1 888000
-2304 1 984000
-576 1 1080000
-576 1 1104000
-576 1 1128000
-576 1 1152000
-576 1 1176000
-576 1 1200000
-576 1 1224000
-576 1 1248000
-576 1 1272000
-576 1 1296000
-576 1 1320000
-576 1 1344000
-576 1 1368000
-576 1 1392000
-576 1 1416000
-576 1 1440000
-576 1 1464000
-576 1 1488000
-576 1 1512000
-576 1 1536000
-576 1 1560000
-576 1 1584000
-576 1 1608000
-576 1 1632000
-576 1 1656000
-576 1 1680000
-576 1 1704000
-576 1 1728000
-576 1 1752000
-576 1 1776000
-576 1 1800000
-576 1 1824000
-576 1 1848000
-576 1 1872000
-576 1 1896000
-576 1 1920000
-576 1 1944000
-576 1 1968000
-576 1 1992000
-576 1 2016000
-576 1 2040000
-576 1 2064000
-576 1 2088000
-576 1 2112000
-576 1 2136000
-576 1 2160000
-576 1 2184000
-576 1 2208000
-576 1 2232000
-576 1 2256000
-576 1 2280000
-576 1 2304000
-576 1 2328000
-576 1 2352000
-576 1 2376000
-576 1 2400000
-576 1 2424000
-576 1 2448000
-576 1 2472000
-576 1 2496000
-576 1 2520000
-576 1 2544000
-576 1 2568000
-576 1 2592000
-576 1 2616000
-576 1 2640000
-576 1 2664000
-576 1 2688000
-576 1 2712000
-576 1 2736000
-576 1 2760000
-576 1 2784000
-576 1 2808000
-576 1 2832000
-576 1 2856000
-576 1 2880000
-576 1 2904000
-576 1 2928000
-576 1 2952000
-576 1 2976000
-576 1 3000000
-576 1 3024000
-576 1 3048000
-576 1 3072000
-576 1 3096000
-576 1 3120000
-576 1 3144000
-576 1 3168000
-576 1 3192000
-576 1 3216000
-576 1 3240000
-576 1 3264000
-576 1 3288000
-576 1 3312000
-576 1 3336000
-576 1 3360000
-576 1 3384000
-576 1 3408000
-576 1 3432000
-576 1 3456000
-576 1 3480000
-576 1 3504000
-576 1 3528000
-576 1 3552000
-576 1 3576000
-576 1 3600000
-576 1 3624000
-576 1 3648000
-576 1 3672000
-576 1 3696000
-576 1 3720000
-576 1 3744000
-576 1 3768000
-576 1 3792000
-576 1 3816000
-576 1 3840000
-576 1 3864000
-576 1 3888000
-576 1 3912000
-576 1 3936000
-576 1 3960000
-576 1 3984000
-576 1 4008000
-576 1 4032000
-576 1 4056000
-576 1 4080000
-576 1 4104000
-576 1 4128000
-576 1 4152000
-576 1 4176000
-576 1 4200000
-576 1 4224000
-576 1 4248000
-576 1 4272000
-576 1 4296000
-576 1 4320000
-576 1 4344000
-576 1 4368000
-576 1 4392000
-576 1 4416000
-576 1 4440000
-576 1 4464000
-576 1 4488000
-576 1 4512000
-576 1 4536000
-576 1 4560000
-576 1 4584000
-576 1 4608000
-576 1 4632000
-576 1 4656000
-576 1 4680000
-576 1 4704000
-576 1 4728000
-576 1 4752000
-576 1 4776000
-576 1 4800000
-576 1 4824000
-576 1 4848000
-576 1 4872000
-576 1 4896000
-576 1 4920000
-576 1 4944000
-576 1 4968000
-576 1 4992000
-576 1 5016000
-576 1 5040000
-576 1 5064000
-576 1 5088000
-576 1 5112000
-576 1 5136000
-576 1 5160000
-576 1 5184000
-576 1 5208000
-576 1 5232000
-576 1 5256000
-576 1 5280000
-576 1 5304000
-576 1 5328000
-576 1 5352000
-576 1 5376000
-576 1 5400000
-576 1 5424000
-576 1 5448000
-576 1 5472000
-576 1 5496000
-576 1 5520000
-576 1 5544000
-576 1 5568000
-576 1 5592000
-576 1 5616000
-576 1 5640000
-576 1 5664000
-576 1 5688000
-576 1 5712000
-576 1 5736000
-576 1 5760000
-576 1 5784000
-576 1 5808000
-576 1 5832000
-576 1 5856000
-576 1 5880000
-576 1 5904000
-576 1 5928000
-576 1 5952000
-576 1 5976000
-576 1 6000000
-576 1 6024000
-576 1 6048000
-576 1 6072000
-576 1 6096000
-576 1 6120000
-576 1 6144000
-576 1 6168000
-576 1 6192000
-576 1 6216000
-576 1 6240000
-576 1 6264000
-576 1 6288000
-576 1 6312000
-576 1 6336000
-576 1 6360000
-576 1 6384000
-576 1 6408000
-576 1 6432000
-576 1 6456000
-576 1 6480000
-576 1 6504000
-576 1 6528000
-576 1 6552000
-576 1 6576000
-576 1 6600000
-576 1 6624000
-576 1 6648000
-576 1 6672000
-576 1 6696000
-576 1 6720000
-576 1 6744000
-576 1 6768000
-576 1 6792000
-576 1 6816000
-576 1 6840000
-576 1 6864000
-576 1 6888000
-576 1 6912000
-576 1 6936000
-576 1 6960000
-576 1 6984000
-576 1 7008000
-576 1 7032000
-576 1 7056000
-576 1 7080000
-576 1 7104000
-576 1 7128000
-576 1 7152000
-576 1 7176000
-576 1 7200000
-576 1 7224000
-576 1 7248000
-576 1 7272000
-576 1 7296000
-576 1 7320000
-576 1 7344000
-576 1 7368000
-576 1 7392000
-576 1 7416000
-576 1 7440000
-576 1 7464000
-576 1 7488000
-576 1 7512000
-576 1 7536000
-576 1 7560000
-576 1 7584000
-576 1 7608000
-576 1 7632000
-576 1 7656000
-576 1 7680000
-576 1 7704000
-576 1 7728000
-576 1 7752000
-576 1 7776000
-576 1 7800000
-576 1 7824000
-576 1 7848000
-576 1 7872000
-576 1 7896000
-576 1 7920000
-576 1 7944000
-576 1 7968000
-576 1 7992000
-576 1 8016000
-576 1 8040000
-576 1 8064000
-576 1 8088000
-576 1 8112000
-576 1 8136000
-576 1 8160000
-576 1 8184000
-576 1 8208000
-576 1 8232000
-576 1 8256000
-576 1 8280000
-576 1 8304000
-576 1 8328000
-576 1 8352000
-576 1 8376000
-576 1 8400000
-576 1 8424000
-576 1 8448000
-576 1 8472000
-576 1 8496000
-576 1 8520000
-576 1 8544000
-576 1 8568000
-576 1 8592000
-576 1 8616000
-576 1 8640000
-576 1 8664000
-576 1 8688000
-576 1 8712000
-576 1 8736000
-576 1 8760000
-576 1 8784000
-576 1 8808000
-576 1 8832000
-576 1 8856000
-576 1 8880000
-576 1 8904000
-576 1 8928000
-576 1 8952000
-576 1 8976000
-576 1 9000000
-576 1 9024000
-576 1 9048000
-576 1 9072000
-576 1 9096000
-576 1 9120000
-576 1 9144000
-576 1 9168000
-576 1 9192000
-576 1 9216000
-576 1 9240000
-576 1 9264000
-576 1 9288000
-576 1 9312000
-576 1 9336000
-576 1 9360000
-576 1 9384000
-576 1 9408000
-576 1 9432000
-576 1 9456000
-576 1 9480000
-576 1 9504000
-576 1 9528000
-576 1 9552000
-576 1 9576000
-576 1 9600000
-576 1 9624000
-576 1 9648000
-576 1 9672000
-576 1 9696000
-576 1 9720000
-576 1 9744000
-576 1 9768000
-576 1 9792000
-576 1 9816000
-576 1 9840000
-576 1 9864000
-576 1 9888000
-576 1 9912000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
deleted file mode 100644
index 0176eaf4..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
+++ /dev/null
@@ -1,807 +0,0 @@
-32 1 0
-32 1 20000
-64 1 40000
-64 1 80000
-64 1 120000
-96 1 160000
-96 1 220000
-96 1 280000
-96 1 340000
-128 1 400000
-128 1 480000
-128 1 560000
-128 1 640000
-128 1 720000
-32 1 800000
-32 1 820000
-32 1 840000
-32 1 860000
-32 1 880000
-32 1 900000
-32 1 920000
-32 1 940000
-32 1 960000
-32 1 980000
-32 1 1000000
-32 1 1020000
-32 1 1040000
-32 1 1060000
-32 1 1080000
-32 1 1100000
-32 1 1120000
-32 1 1140000
-32 1 1160000
-32 1 1180000
-32 1 1200000
-32 1 1220000
-32 1 1240000
-32 1 1260000
-32 1 1280000
-32 1 1300000
-32 1 1320000
-32 1 1340000
-32 1 1360000
-32 1 1380000
-32 1 1400000
-32 1 1420000
-32 1 1440000
-32 1 1460000
-32 1 1480000
-32 1 1500000
-32 1 1520000
-32 1 1540000
-32 1 1560000
-32 1 1580000
-32 1 1600000
-32 1 1620000
-32 1 1640000
-32 1 1660000
-32 1 1680000
-32 1 1700000
-32 1 1720000
-32 1 1740000
-32 1 1760000
-32 1 1780000
-32 1 1800000
-32 1 1820000
-32 1 1840000
-32 1 1860000
-32 1 1880000
-32 1 1900000
-32 1 1920000
-32 1 1940000
-32 1 1960000
-32 1 1980000
-32 1 2000000
-32 1 2020000
-32 1 2040000
-32 1 2060000
-32 1 2080000
-32 1 2100000
-32 1 2120000
-32 1 2140000
-32 1 2160000
-32 1 2180000
-32 1 2200000
-32 1 2220000
-32 1 2240000
-32 1 2260000
-32 1 2280000
-32 1 2300000
-32 1 2320000
-32 1 2340000
-32 1 2360000
-32 1 2380000
-32 1 2400000
-32 1 2420000
-32 1 2440000
-32 1 2460000
-32 1 2480000
-32 1 2500000
-32 1 2520000
-32 1 2540000
-32 1 2560000
-32 1 2580000
-32 1 2600000
-32 1 2620000
-32 1 2640000
-32 1 2660000
-32 1 2680000
-32 1 2700000
-32 1 2720000
-32 1 2740000
-32 1 2760000
-32 1 2780000
-32 1 2800000
-32 1 2820000
-32 1 2840000
-32 1 2860000
-32 1 2880000
-32 1 2900000
-32 1 2920000
-32 1 2940000
-32 1 2960000
-32 1 2980000
-32 1 3000000
-32 1 3020000
-32 1 3040000
-32 1 3060000
-32 1 3080000
-32 1 3100000
-32 1 3120000
-32 1 3140000
-32 1 3160000
-32 1 3180000
-32 1 3200000
-32 1 3220000
-32 1 3240000
-32 1 3260000
-32 1 3280000
-32 1 3300000
-32 1 3320000
-32 1 3340000
-32 1 3360000
-32 1 3380000
-32 1 3400000
-32 1 3420000
-32 1 3440000
-32 1 3460000
-32 1 3480000
-32 1 3500000
-32 1 3520000
-32 1 3540000
-32 1 3560000
-32 1 3580000
-32 1 3600000
-32 1 3620000
-32 1 3640000
-32 1 3660000
-32 1 3680000
-32 1 3700000
-32 1 3720000
-32 1 3740000
-32 1 3760000
-32 1 3780000
-32 1 3800000
-32 1 3820000
-32 1 3840000
-32 1 3860000
-32 1 3880000
-32 1 3900000
-32 1 3920000
-32 1 3940000
-32 1 3960000
-32 1 3980000
-32 1 4000000
-32 1 4020000
-32 1 4040000
-32 1 4060000
-32 1 4080000
-32 1 4100000
-32 1 4120000
-32 1 4140000
-32 1 4160000
-32 1 4180000
-32 1 4200000
-32 1 4220000
-32 1 4240000
-32 1 4260000
-32 1 4280000
-32 1 4300000
-32 1 4320000
-32 1 4340000
-32 1 4360000
-32 1 4380000
-32 1 4400000
-32 1 4420000
-32 1 4440000
-32 1 4460000
-32 1 4480000
-32 1 4500000
-32 1 4520000
-32 1 4540000
-32 1 4560000
-32 1 4580000
-32 1 4600000
-32 1 4620000
-32 1 4640000
-32 1 4660000
-32 1 4680000
-32 1 4700000
-32 1 4720000
-32 1 4740000
-32 1 4760000
-32 1 4780000
-32 1 4800000
-32 1 4820000
-32 1 4840000
-32 1 4860000
-32 1 4880000
-32 1 4900000
-32 1 4920000
-32 1 4940000
-32 1 4960000
-32 1 4980000
-32 1 5000000
-32 1 5020000
-32 1 5040000
-32 1 5060000
-32 1 5080000
-32 1 5100000
-32 1 5120000
-32 1 5140000
-32 1 5160000
-32 1 5180000
-32 1 5200000
-32 1 5220000
-32 1 5240000
-32 1 5260000
-32 1 5280000
-32 1 5300000
-32 1 5320000
-32 1 5340000
-32 1 5360000
-32 1 5380000
-32 1 5400000
-32 1 5420000
-32 1 5440000
-32 1 5460000
-32 1 5480000
-32 1 5500000
-32 1 5520000
-32 1 5540000
-32 1 5560000
-32 1 5580000
-32 1 5600000
-32 1 5620000
-32 1 5640000
-32 1 5660000
-32 1 5680000
-32 1 5700000
-32 1 5720000
-32 1 5740000
-32 1 5760000
-32 1 5780000
-32 1 5800000
-32 1 5820000
-32 1 5840000
-32 1 5860000
-32 1 5880000
-32 1 5900000
-32 1 5920000
-32 1 5940000
-32 1 5960000
-32 1 5980000
-32 1 6000000
-32 1 6020000
-32 1 6040000
-32 1 6060000
-32 1 6080000
-32 1 6100000
-32 1 6120000
-32 1 6140000
-32 1 6160000
-32 1 6180000
-32 1 6200000
-32 1 6220000
-32 1 6240000
-32 1 6260000
-32 1 6280000
-32 1 6300000
-32 1 6320000
-32 1 6340000
-32 1 6360000
-32 1 6380000
-32 1 6400000
-32 1 6420000
-32 1 6440000
-32 1 6460000
-32 1 6480000
-32 1 6500000
-32 1 6520000
-32 1 6540000
-32 1 6560000
-32 1 6580000
-32 1 6600000
-32 1 6620000
-32 1 6640000
-32 1 6660000
-32 1 6680000
-32 1 6700000
-32 1 6720000
-32 1 6740000
-32 1 6760000
-32 1 6780000
-32 1 6800000
-32 1 6820000
-32 1 6840000
-32 1 6860000
-32 1 6880000
-32 1 6900000
-32 1 6920000
-32 1 6940000
-32 1 6960000
-32 1 6980000
-32 1 7000000
-32 1 7020000
-32 1 7040000
-32 1 7060000
-32 1 7080000
-32 1 7100000
-32 1 7120000
-32 1 7140000
-32 1 7160000
-32 1 7180000
-32 1 7200000
-32 1 7220000
-32 1 7240000
-32 1 7260000
-32 1 7280000
-32 1 7300000
-32 1 7320000
-32 1 7340000
-32 1 7360000
-32 1 7380000
-32 1 7400000
-32 1 7420000
-32 1 7440000
-32 1 7460000
-32 1 7480000
-32 1 7500000
-32 1 7520000
-32 1 7540000
-32 1 7560000
-32 1 7580000
-32 1 7600000
-32 1 7620000
-32 1 7640000
-32 1 7660000
-32 1 7680000
-32 1 7700000
-32 1 7720000
-32 1 7740000
-32 1 7760000
-32 1 7780000
-32 1 7800000
-32 1 7820000
-32 1 7840000
-32 1 7860000
-32 1 7880000
-32 1 7900000
-32 1 7920000
-32 1 7940000
-32 1 7960000
-32 1 7980000
-32 1 8000000
-32 1 8020000
-32 1 8040000
-32 1 8060000
-32 1 8080000
-32 1 8100000
-32 1 8120000
-32 1 8140000
-32 1 8160000
-32 1 8180000
-32 1 8200000
-32 1 8220000
-32 1 8240000
-32 1 8260000
-32 1 8280000
-32 1 8300000
-32 1 8320000
-32 1 8340000
-32 1 8360000
-32 1 8380000
-32 1 8400000
-32 1 8420000
-32 1 8440000
-32 1 8460000
-32 1 8480000
-32 1 8500000
-32 1 8520000
-32 1 8540000
-32 1 8560000
-32 1 8580000
-32 1 8600000
-32 1 8620000
-32 1 8640000
-32 1 8660000
-32 1 8680000
-32 1 8700000
-32 1 8720000
-32 1 8740000
-32 1 8760000
-32 1 8780000
-32 1 8800000
-32 1 8820000
-32 1 8840000
-32 1 8860000
-32 1 8880000
-32 1 8900000
-32 1 8920000
-32 1 8940000
-32 1 8960000
-32 1 8980000
-32 1 9000000
-32 1 9020000
-32 1 9040000
-32 1 9060000
-32 1 9080000
-32 1 9100000
-32 1 9120000
-32 1 9140000
-32 1 9160000
-32 1 9180000
-32 1 9200000
-32 1 9220000
-32 1 9240000
-32 1 9260000
-32 1 9280000
-32 1 9300000
-32 1 9320000
-32 1 9340000
-32 1 9360000
-32 1 9380000
-32 1 9400000
-32 1 9420000
-32 1 9440000
-32 1 9460000
-32 1 9480000
-32 1 9500000
-32 1 9520000
-32 1 9540000
-32 1 9560000
-32 1 9580000
-32 1 9600000
-32 1 9620000
-32 1 9640000
-32 1 9660000
-32 1 9680000
-32 1 9700000
-32 1 9720000
-32 1 9740000
-32 1 9760000
-32 1 9780000
-32 1 9800000
-32 1 9820000
-32 1 9840000
-32 1 9860000
-32 1 9880000
-32 1 9900000
-32 1 9920000
-32 1 9940000
-32 1 9960000
-32 1 9980000
-32 1 10000000
-32 1 10020000
-32 1 10040000
-32 1 10060000
-32 1 10080000
-32 1 10100000
-32 1 10120000
-32 1 10140000
-32 1 10160000
-32 1 10180000
-32 1 10200000
-32 1 10220000
-32 1 10240000
-32 1 10260000
-32 1 10280000
-32 1 10300000
-32 1 10320000
-32 1 10340000
-32 1 10360000
-32 1 10380000
-32 1 10400000
-32 1 10420000
-32 1 10440000
-32 1 10460000
-32 1 10480000
-32 1 10500000
-32 1 10520000
-32 1 10540000
-32 1 10560000
-32 1 10580000
-32 1 10600000
-32 1 10620000
-32 1 10640000
-32 1 10660000
-32 1 10680000
-32 1 10700000
-32 1 10720000
-32 1 10740000
-32 1 10760000
-32 1 10780000
-32 1 10800000
-32 1 10820000
-32 1 10840000
-32 1 10860000
-32 1 10880000
-32 1 10900000
-32 1 10920000
-32 1 10940000
-32 1 10960000
-32 1 10980000
-32 1 11000000
-32 1 11020000
-32 1 11040000
-32 1 11060000
-32 1 11080000
-32 1 11100000
-32 1 11120000
-32 1 11140000
-32 1 11160000
-32 1 11180000
-32 1 11200000
-32 1 11220000
-32 1 11240000
-32 1 11260000
-32 1 11280000
-32 1 11300000
-32 1 11320000
-32 1 11340000
-32 1 11360000
-32 1 11380000
-32 1 11400000
-32 1 11420000
-32 1 11440000
-32 1 11460000
-32 1 11480000
-32 1 11500000
-32 1 11520000
-32 1 11540000
-32 1 11560000
-32 1 11580000
-32 1 11600000
-32 1 11620000
-32 1 11640000
-32 1 11660000
-32 1 11680000
-32 1 11700000
-32 1 11720000
-32 1 11740000
-32 1 11760000
-32 1 11780000
-32 1 11800000
-32 1 11820000
-32 1 11840000
-32 1 11860000
-32 1 11880000
-32 1 11900000
-32 1 11920000
-32 1 11940000
-32 1 11960000
-32 1 11980000
-32 1 12000000
-32 1 12020000
-32 1 12040000
-32 1 12060000
-32 1 12080000
-32 1 12100000
-32 1 12120000
-32 1 12140000
-32 1 12160000
-32 1 12180000
-32 1 12200000
-32 1 12220000
-32 1 12240000
-32 1 12260000
-32 1 12280000
-32 1 12300000
-32 1 12320000
-32 1 12340000
-32 1 12360000
-32 1 12380000
-32 1 12400000
-32 1 12420000
-32 1 12440000
-32 1 12460000
-32 1 12480000
-32 1 12500000
-32 1 12520000
-32 1 12540000
-32 1 12560000
-32 1 12580000
-32 1 12600000
-32 1 12620000
-32 1 12640000
-32 1 12660000
-32 1 12680000
-32 1 12700000
-32 1 12720000
-32 1 12740000
-32 1 12760000
-32 1 12780000
-32 1 12800000
-32 1 12820000
-32 1 12840000
-32 1 12860000
-32 1 12880000
-32 1 12900000
-32 1 12920000
-32 1 12940000
-32 1 12960000
-32 1 12980000
-32 1 13000000
-32 1 13020000
-32 1 13040000
-32 1 13060000
-32 1 13080000
-32 1 13100000
-32 1 13120000
-32 1 13140000
-32 1 13160000
-32 1 13180000
-32 1 13200000
-32 1 13220000
-32 1 13240000
-32 1 13260000
-32 1 13280000
-32 1 13300000
-32 1 13320000
-32 1 13340000
-32 1 13360000
-32 1 13380000
-32 1 13400000
-32 1 13420000
-32 1 13440000
-32 1 13460000
-32 1 13480000
-32 1 13500000
-32 1 13520000
-32 1 13540000
-32 1 13560000
-32 1 13580000
-32 1 13600000
-32 1 13620000
-32 1 13640000
-32 1 13660000
-32 1 13680000
-32 1 13700000
-32 1 13720000
-32 1 13740000
-32 1 13760000
-32 1 13780000
-32 1 13800000
-32 1 13820000
-32 1 13840000
-32 1 13860000
-32 1 13880000
-32 1 13900000
-32 1 13920000
-32 1 13940000
-32 1 13960000
-32 1 13980000
-32 1 14000000
-32 1 14020000
-32 1 14040000
-32 1 14060000
-32 1 14080000
-32 1 14100000
-32 1 14120000
-32 1 14140000
-32 1 14160000
-32 1 14180000
-32 1 14200000
-32 1 14220000
-32 1 14240000
-32 1 14260000
-32 1 14280000
-32 1 14300000
-32 1 14320000
-32 1 14340000
-32 1 14360000
-32 1 14380000
-32 1 14400000
-32 1 14420000
-32 1 14440000
-32 1 14460000
-32 1 14480000
-32 1 14500000
-32 1 14520000
-32 1 14540000
-32 1 14560000
-32 1 14580000
-32 1 14600000
-32 1 14620000
-32 1 14640000
-32 1 14660000
-32 1 14680000
-32 1 14700000
-32 1 14720000
-32 1 14740000
-32 1 14760000
-32 1 14780000
-32 1 14800000
-32 1 14820000
-32 1 14840000
-32 1 14860000
-32 1 14880000
-32 1 14900000
-32 1 14920000
-32 1 14940000
-32 1 14960000
-32 1 14980000
-32 1 15000000
-32 1 15020000
-32 1 15040000
-32 1 15060000
-32 1 15080000
-32 1 15100000
-32 1 15120000
-32 1 15140000
-32 1 15160000
-32 1 15180000
-32 1 15200000
-32 1 15220000
-32 1 15240000
-32 1 15260000
-32 1 15280000
-32 1 15300000
-32 1 15320000
-32 1 15340000
-32 1 15360000
-32 1 15380000
-32 1 15400000
-32 1 15420000
-32 1 15440000
-32 1 15460000
-32 1 15480000
-32 1 15500000
-32 1 15520000
-32 1 15540000
-32 1 15560000
-32 1 15580000
-32 1 15600000
-32 1 15620000
-32 1 15640000
-32 1 15660000
-32 1 15680000
-32 1 15700000
-32 1 15720000
-32 1 15740000
-32 1 15760000
-32 1 15780000
-32 1 15800000
-32 1 15820000
-32 1 15840000
-32 1 15860000
-32 1 15880000
-32 1 15900000
-32 1 15920000
-32 1 15940000
-32 1 15960000
-32 1 15980000
-32 1 16000000
-32 1 16020000
-32 1 16040000
-32 1 16060000
-32 1 16080000
-32 1 16100000
-32 1 16120000
-32 1 16140000
-32 1 16160000
-32 1 16180000
-32 1 16200000
-32 1 16220000
-32 1 16240000
-32 1 16260000
-32 1 16280000
-32 1 16300000
-32 1 16320000
-32 1 16340000
-32 1 16360000
-32 1 16380000
-32 1 16400000
-32 1 16420000
-32 1 16440000
-32 1 16460000
-32 1 16480000
-32 1 16500000
-32 1 16520000
-32 1 16540000
-32 1 16560000
-32 1 16580000
-32 1 16600000
-32 1 16620000
-32 1 16640000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 3dc5b29..d561adc 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -460,7 +460,8 @@
ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
}
int64_t timestamp = (*Info)[frameID].timestamp;
- if ((*Info)[frameID].flags) flags = (1 << ((*Info)[frameID].flags - 1));
+
+ flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0;
if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
flags |= C2FrameData::FLAG_END_OF_STREAM;
@@ -684,7 +685,7 @@
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
if (!(strcasestr(mMime.c_str(), "avc") || strcasestr(mMime.c_str(), "hevc") ||
strcasestr(mMime.c_str(), "vp8") || strcasestr(mMime.c_str(), "vp9") ||
- strcasestr(mMime.c_str(), "mpeg2"))) {
+ strcasestr(mMime.c_str(), "mpeg2") || strcasestr(mMime.c_str(), "av01"))) {
return;
}
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/hal/services/Android.bp b/media/codec2/hal/services/Android.bp
index 524519c..663e159 100644
--- a/media/codec2/hal/services/Android.bp
+++ b/media/codec2/hal/services/Android.bp
@@ -39,13 +39,17 @@
}
cc_binary {
- name: "android.hardware.media.c2@1.2-default-service",
+ name: "android.hardware.media.c2-default-service",
vendor: true,
relative_install_path: "hw",
- init_rc: ["android.hardware.media.c2@1.2-default-service.rc"],
+ init_rc: ["android.hardware.media.c2-default-service.rc"],
- defaults: ["libcodec2-hidl-defaults"],
+ defaults: [
+ "libcodec2-hidl-defaults",
+ "libcodec2-aidl-defaults",
+ ],
+
srcs: [
"vendor.cpp",
],
@@ -54,13 +58,14 @@
shared_libs: [
"libavservices_minijail",
"libbinder",
+ "libbinder_ndk",
],
- required: ["android.hardware.media.c2@1.2-default-seccomp_policy"],
+ required: ["android.hardware.media.c2-default-seccomp_policy"],
- // The content in manifest_media_c2_V1_1_default.xml can be included
+ // The content in manifest_media_c2_default.xml can be included
// directly in the main device manifest.xml file or via vintf_fragments.
// (Remove the line below if the entry is already in the main manifest.)
- vintf_fragments: ["manifest_media_c2_V1_1_default.xml"],
+ vintf_fragments: ["manifest_media_c2_default.xml"],
// Remove this line to enable this module.
enabled: false,
@@ -73,30 +78,29 @@
// Files in the "seccomp_policy" subdirectory are only provided as examples.
// They may not work on some devices and/or architectures without modification.
prebuilt_etc {
- name: "android.hardware.media.c2@1.2-default-seccomp_policy",
+ name: "android.hardware.media.c2-default-seccomp_policy",
vendor: true,
sub_dir: "seccomp_policy",
// If a specific architecture is targeted, multiple choices are not needed.
arch: {
arm: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-arm.policy",
},
arm64: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-arm64.policy",
},
riscv64: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-riscv64.policy",
},
x86: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-x86.policy",
},
x86_64: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-x86_64.policy",
},
},
// This may be removed.
required: ["crash_dump.policy"],
}
-
diff --git a/media/codec2/hal/services/android.hardware.media.c2-default-service.rc b/media/codec2/hal/services/android.hardware.media.c2-default-service.rc
new file mode 100644
index 0000000..dcc8e71
--- /dev/null
+++ b/media/codec2/hal/services/android.hardware.media.c2-default-service.rc
@@ -0,0 +1,7 @@
+service android-hardware-media-c2-hal /vendor/bin/hw/android.hardware.media.c2-default-service
+ class hal
+ user mediacodec
+ group camera mediadrm drmrpc
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh
+
diff --git a/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc b/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc
deleted file mode 100644
index 12da593..0000000
--- a/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service android-hardware-media-c2-hal-1-2 /vendor/bin/hw/android.hardware.media.c2@1.2-default-service
- class hal
- user mediacodec
- group camera mediadrm drmrpc
- ioprio rt 4
- task_profiles ProcessCapacityHigh
-
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml
deleted file mode 100644
index e97c3ce..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal>
- <name>android.hardware.media.c2</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>IComponentStore</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml
deleted file mode 100644
index bf0d72f..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal>
- <name>android.hardware.media.c2</name>
- <transport>hwbinder</transport>
- <version>1.1</version>
- <interface>
- <name>IComponentStore</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml
deleted file mode 100644
index a5e8d87..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal>
- <name>android.hardware.media.c2</name>
- <transport>hwbinder</transport>
- <version>1.2</version>
- <interface>
- <name>IComponentStore</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_default.xml b/media/codec2/hal/services/manifest_media_c2_default.xml
new file mode 100644
index 0000000..5e3d060
--- /dev/null
+++ b/media/codec2/hal/services/manifest_media_c2_default.xml
@@ -0,0 +1,18 @@
+<manifest version="1.0" type="device">
+ <!-- HIDL fragment -->
+ <hal>
+ <name>android.hardware.media.c2</name>
+ <transport>hwbinder</transport>
+ <version>1.2</version>
+ <interface>
+ <name>IComponentStore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <!-- AIDL fragment -->
+ <hal format="aidl">
+ <name>android.hardware.media.c2</name>
+ <version>1</version>
+ <fqname>IComponentStore/default</fqname>
+ </hal>
+</manifest>
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm64.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-riscv64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-riscv64.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86_64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86_64.policy
diff --git a/media/codec2/hal/services/vendor.cpp b/media/codec2/hal/services/vendor.cpp
index 0d0684d..7cb7e6d 100644
--- a/media/codec2/hal/services/vendor.cpp
+++ b/media/codec2/hal/services/vendor.cpp
@@ -15,29 +15,43 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "android.hardware.media.c2@1.2-service"
+#define LOG_TAG "android.hardware.media.c2-service"
#include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <codec2/hidl/1.2/ComponentStore.h>
-#include <hidl/HidlTransportSupport.h>
#include <minijail.h>
#include <util/C2InterfaceHelper.h>
#include <C2Component.h>
#include <C2Config.h>
+// HIDL
+#include <binder/ProcessState.h>
+#include <codec2/hidl/1.2/ComponentStore.h>
+#include <hidl/HidlTransportSupport.h>
+
+// AIDL
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/ParamTypes.h>
+
// This is the absolute on-device path of the prebuild_etc module
-// "android.hardware.media.c2@1.1-default-seccomp_policy" in Android.bp.
+// "android.hardware.media.c2-default-seccomp_policy" in Android.bp.
static constexpr char kBaseSeccompPolicyPath[] =
"/vendor/etc/seccomp_policy/"
- "android.hardware.media.c2@1.2-default-seccomp-policy";
+ "android.hardware.media.c2-default-seccomp_policy";
// Additional seccomp permissions can be added in this file.
// This file does not exist by default.
static constexpr char kExtSeccompPolicyPath[] =
"/vendor/etc/seccomp_policy/"
- "android.hardware.media.c2@1.2-extended-seccomp-policy";
+ "android.hardware.media.c2-extended-seccomp_policy";
+
+// We want multiple threads to be running so that a blocking operation
+// on one codec does not block the other codecs.
+// For HIDL: Extra threads may be needed to handle a stacked IPC sequence that
+// contains alternating binder and hwbinder calls. (See b/35283480.)
+static constexpr int kThreadCount = 8;
class StoreImpl : public C2ComponentStore {
public:
@@ -125,12 +139,12 @@
addParameter(
DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
- .withDefault(new C2StoreDmaBufUsageInfo())
+ .withDefault(C2StoreDmaBufUsageInfo::AllocShared(128))
.withFields({
- C2F(mDmaBufUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
- C2F(mDmaBufUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
- C2F(mDmaBufUsageInfo, heapName).any(),
- C2F(mDmaBufUsageInfo, allocFlags).flags({}),
+ C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
+ C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
+ C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
+ C2F(mDmaBufUsageInfo, m.heapName).any(),
})
.withSetter(SetDmaBufUsage)
.build());
@@ -162,21 +176,49 @@
Interface mInterface;
};
-int main(int /* argc */, char** /* argv */) {
- using namespace ::android;
- LOG(DEBUG) << "android.hardware.media.c2@1.2-service starting...";
+void runAidlService() {
+ ABinderProcess_setThreadPoolMaxThreadCount(kThreadCount);
+ ABinderProcess_startThreadPool();
- // Set up minijail to limit system calls.
- signal(SIGPIPE, SIG_IGN);
- SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+ // Create IComponentStore service.
+ using namespace ::aidl::android::hardware::media::c2;
+ std::shared_ptr<IComponentStore> store;
+
+ // TODO: Replace this with
+ // store = new utils::ComponentStore(
+ // /* implementation of C2ComponentStore */);
+ LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
+ store = ::ndk::SharedRefBase::make<utils::ComponentStore>(
+ std::make_shared<StoreImpl>());
+
+ if (store == nullptr) {
+ LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
+ } else {
+ const std::string serviceName =
+ std::string(IComponentStore::descriptor) + "/default";
+ binder_exception_t ex = AServiceManager_addService(
+ store->asBinder().get(), serviceName.c_str());
+ if (ex != EX_NONE) {
+ LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
+ " with instance name << \""
+ << serviceName << "\".";
+ } else {
+ LOG(DEBUG) << "Codec2's IComponentStore service registered. "
+ "Instance name: \"" << serviceName << "\".";
+ }
+ }
+
+ ABinderProcess_joinThreadPool();
+}
+
+void runHidlService() {
+ using namespace ::android;
// Enable vndbinder to allow vendor-to-vendor binder calls.
ProcessState::initWithDriver("/dev/vndbinder");
ProcessState::self()->startThreadPool();
- // Extra threads may be needed to handle a stacked IPC sequence that
- // contains alternating binder and hwbinder calls. (See b/35283480.)
- hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
+ hardware::configureRpcThreadpool(kThreadCount, true /* callerWillJoin */);
// Create IComponentStore service.
{
@@ -206,5 +248,20 @@
}
hardware::joinRpcThreadpool();
+}
+
+int main(int /* argc */, char** /* argv */) {
+ const bool aidlEnabled = ::aidl::android::hardware::media::c2::utils::IsEnabled();
+ LOG(DEBUG) << "android.hardware.media.c2" << (aidlEnabled ? "-V1" : "@1.2")
+ << "-service starting...";
+
+ // Set up minijail to limit system calls.
+ signal(SIGPIPE, SIG_IGN);
+ android::SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+ if (aidlEnabled) {
+ runAidlService();
+ } else {
+ runHidlService();
+ }
return 0;
}
diff --git a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
index 43533fd..7492cab 100644
--- a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
@@ -114,7 +114,6 @@
.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
- AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY |
AHARDWAREBUFFER_USAGE_VIDEO_ENCODE,
.stride = 0,
.rfu0 = 0,
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index f272499..0803dc3 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -23,6 +23,7 @@
#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
#include <android/hardware/graphics/common/1.2/types.h>
#include <cutils/native_handle.h>
+#include <drm/drm_fourcc.h>
#include <gralloctypes/Gralloc4.h>
#include <hardware/gralloc.h>
#include <ui/GraphicBufferAllocator.h>
@@ -478,7 +479,25 @@
// 'NATIVE' on Android means LITTLE_ENDIAN
constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
- switch (mFormat) {
+ // 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
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index 1eefd87..81cdb43 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -17,10 +17,14 @@
#ifndef ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
#define ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
-#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-
#include <C2Buffer.h>
+#include <utils/RefBase.h>
+
+namespace android::hardware::graphics::bufferqueue::V2_0 {
+struct IGraphicBufferProducer;
+}
+
// Note: HIDL-BufferPool and AIDL-BufferPool are not compatible
namespace android::hardware::media::bufferpool {
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index 45baa94..d9789f1 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -21,9 +21,9 @@
#include <set>
#include <gtest/gtest.h>
+#include <log/log.h>
#include <media/AidlConversionCppNdk.h>
#include <media/IAudioFlinger.h>
-#include <utils/Log.h>
#include "audio_test_utils.h"
@@ -277,23 +277,30 @@
GTEST_SKIP() << "No output devices returned by the audio system";
}
+ bool sourceFound = false, sinkFound = false;
for (const auto& port : ports) {
if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_DEVICE) {
sourcePort = port;
+ sourceFound = true;
}
if (port.role == AUDIO_PORT_ROLE_SINK && port.type == AUDIO_PORT_TYPE_DEVICE &&
port.ext.device.type == AUDIO_DEVICE_OUT_SPEAKER) {
sinkPort = port;
+ sinkFound = true;
}
+ if (sourceFound && sinkFound) break;
+ }
+ if (!sourceFound || !sinkFound) {
+ GTEST_SKIP() << "No ports suitable for testing";
}
audioPatch.sources[0] = sourcePort.active_config;
audioPatch.sinks[0] = sinkPort.active_config;
status = AudioSystem::createAudioPatch(&audioPatch, &audioPatchHandle);
- EXPECT_EQ(OK, status) << "AudioSystem::createAudiopatch failed between source "
- << sourcePort.ext.device.address << " and sink "
- << sinkPort.ext.device.address;
+ EXPECT_EQ(OK, status) << "AudioSystem::createAudioPatch failed between source "
+ << audio_device_to_string(sourcePort.ext.device.type) << " and sink "
+ << audio_device_to_string(sinkPort.ext.device.type);
// verify that patch is established between source and the sink.
ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
@@ -302,8 +309,8 @@
EXPECT_NE(AUDIO_PORT_HANDLE_NONE, audioPatchHandle);
status = AudioSystem::releaseAudioPatch(audioPatchHandle);
EXPECT_EQ(OK, status) << "AudioSystem::releaseAudioPatch failed between source "
- << sourcePort.ext.device.address << " and sink "
- << sinkPort.ext.device.address;
+ << audio_device_to_string(sourcePort.ext.device.type) << " and sink "
+ << audio_device_to_string(sinkPort.ext.device.type);
// verify that no patch is established between source and the sink after releaseAudioPatch.
ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
@@ -608,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);
@@ -689,3 +705,24 @@
EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
}
}
+
+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) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
+ return RUN_ALL_TESTS();
+}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index c911ac8..835080f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -42,6 +42,7 @@
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
@@ -97,9 +98,15 @@
}
void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
- portConfig->sampleRate = Int{ .value = config.base.sampleRate };
- portConfig->channelMask = config.base.channelMask;
- portConfig->format = config.base.format;
+ if (config.base.sampleRate != 0) {
+ portConfig->sampleRate = Int{ .value = config.base.sampleRate };
+ }
+ if (config.base.channelMask != AudioChannelLayout{}) {
+ portConfig->channelMask = config.base.channelMask;
+ }
+ if (config.base.format != AudioFormatDescription{}) {
+ portConfig->format = config.base.format;
+ }
}
// Note: these converters are for types defined in different AIDL files. Although these
@@ -706,7 +713,11 @@
aidlPatch.sourcePortConfigIds.clear();
aidlPatch.sinkPortConfigIds.clear();
}
- ALOGD("%s: sources: %s, sinks: %s",
+ // The IDs will be found by 'fillPortConfigs', however the original 'aidlSources' and
+ // 'aidlSinks' will not be updated because 'setAudioPatch' only needs IDs. Here we log
+ // the source arguments, where only the audio configuration and device specifications
+ // are relevant.
+ ALOGD("%s: [disregard IDs] sources: %s, sinks: %s",
__func__, ::android::internal::ToString(aidlSources).c_str(),
::android::internal::ToString(aidlSinks).c_str());
auto fillPortConfigs = [&](
@@ -999,7 +1010,7 @@
return mModule->dump(fd, Args(args).args(), args.size());
}
-int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
+status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
TIME_CHECK();
if (!mModule) return NO_INIT;
if (supports == nullptr) {
@@ -1032,11 +1043,12 @@
// There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
// Call `setConnectedState` instead.
// TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
- const status_t status = setConnectedState(port, false /*connected*/);
- if (status == NO_ERROR) {
+ if (const status_t status = setConnectedState(port, false /*connected*/); status == NO_ERROR) {
mDeviceDisconnectionNotified.insert(port->id);
}
- return status;
+ // Return that there was no error as otherwise the disconnection procedure will not be
+ // considered complete for upper layers, and 'setConnectedState' will not be called again.
+ return NO_ERROR;
}
status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
@@ -1069,10 +1081,14 @@
matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
auto portsIt = findPort(matchDevice);
if (portsIt == mPorts.end()) {
- ALOGW("%s: device port for device %s is not found in the module %s",
- __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ // Since 'setConnectedState' is called for all modules, it is normal when the device
+ // port not found in every one of them.
return BAD_VALUE;
+ } else {
+ ALOGD("%s: device port for device %s found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
}
+ resetUnusedPatchesAndPortConfigs();
// Use the ID of the "template" port, use all the information from the provided port.
aidlPort.id = portsIt->first;
AudioPort connectedPort;
@@ -1083,20 +1099,32 @@
"%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);
if (portsIt == mPorts.end()) {
- ALOGW("%s: device port for device %s is not found in the module %s",
- __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ // Since 'setConnectedState' is called for all modules, it is normal when the device
+ // port not found in every one of them.
return BAD_VALUE;
+ } else {
+ ALOGD("%s: device port for device %s found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
}
- // Any streams opened on the external device must be closed by this time,
- // thus we can clean up patches and port configs that were created for them.
resetUnusedPatchesAndPortConfigs();
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
- portsIt->second.id)));
- mPorts.erase(portsIt);
+ // Streams are closed by AudioFlinger independently from device disconnections.
+ // It is possible that the stream has not been closed yet.
+ const int32_t portId = portsIt->second.id;
+ if (!isPortHeldByAStream(portId)) {
+ 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);
+ mConnectedPorts[portId] = true;
+ }
}
return updateRoutes();
}
@@ -1104,6 +1132,7 @@
status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
TIME_CHECK();
if (!mModule) return NO_INIT;
+ resetUnusedPatchesAndPortConfigs();
ModuleDebug debug{ .simulateDeviceConnections = enabled };
status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
// This is important to log as it affects HAL behavior.
@@ -1518,7 +1547,7 @@
}
RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
created));
- } else if (!flags.has_value()) {
+ } else if (portConfigIt == mPortConfigs.end() && !flags.has_value()) {
ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
"and was not created as flags are not specified",
__func__, config.toString().c_str(), ioHandle, mInstance.c_str());
@@ -1593,8 +1622,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(
@@ -1672,6 +1718,28 @@
p.ext.template get<Tag::mix>().handle == ioHandle; });
}
+bool DeviceHalAidl::isPortHeldByAStream(int32_t portId) {
+ // It is assumed that mStreams has already been cleaned up.
+ for (const auto& streamPair : mStreams) {
+ int32_t patchId = streamPair.second;
+ auto patchIt = mPatches.find(patchId);
+ if (patchIt == mPatches.end()) continue;
+ for (int32_t id : patchIt->second.sourcePortConfigIds) {
+ auto portConfigIt = mPortConfigs.find(id);
+ if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
+ return true;
+ }
+ }
+ for (int32_t id : patchIt->second.sinkPortConfigIds) {
+ auto portConfigIt = mPortConfigs.find(id);
+ if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void DeviceHalAidl::resetPatch(int32_t patchId) {
if (auto it = mPatches.find(patchId); it != mPatches.end()) {
mPatches.erase(it);
@@ -1721,10 +1789,10 @@
// The assumption is that port configs are used to create patches
// (or to open streams, but that involves creation of patches, too). Thus,
// orphaned port configs can and should be reset.
- std::set<int32_t> portConfigIds;
+ std::map<int32_t, int32_t /*portID*/> portConfigIds;
std::transform(mPortConfigs.begin(), mPortConfigs.end(),
std::inserter(portConfigIds, portConfigIds.end()),
- [](const auto& pcPair) { return pcPair.first; });
+ [](const auto& pcPair) { return std::make_pair(pcPair.first, pcPair.second.portId); });
for (const auto& p : mPatches) {
for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
@@ -1732,7 +1800,28 @@
for (int32_t id : mInitialPortConfigIds) {
portConfigIds.erase(id);
}
- for (int32_t id : portConfigIds) resetPortConfig(id);
+ std::set<int32_t> retryDeviceDisconnection;
+ for (const auto& portConfigAndIdPair : portConfigIds) {
+ resetPortConfig(portConfigAndIdPair.first);
+ if (const auto it = mConnectedPorts.find(portConfigAndIdPair.second);
+ it != mConnectedPorts.end() && it->second) {
+ retryDeviceDisconnection.insert(portConfigAndIdPair.second);
+ }
+ }
+ for (int32_t portId : retryDeviceDisconnection) {
+ if (!isPortHeldByAStream(portId)) {
+ TIME_CHECK();
+ if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
+ mPorts.erase(portId);
+ mConnectedPorts.erase(portId);
+ ALOGD("%s: executed postponed external device disconnection for port ID %d",
+ __func__, portId);
+ }
+ }
+ }
+ if (!retryDeviceDisconnection.empty()) {
+ updateRoutes();
+ }
}
status_t DeviceHalAidl::updateRoutes() {
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 8f27369..6f45f1f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -165,7 +165,7 @@
error::Result<audio_hw_sync_t> getHwAvSync() override;
- int32_t supportsBluetoothVariableLatency(bool* supports __unused) override;
+ status_t supportsBluetoothVariableLatency(bool* supports __unused) override;
status_t getSoundDoseInterface(const std::string& module,
::ndk::SpAIBinder* soundDoseBinder) override;
@@ -191,6 +191,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*/,
@@ -261,6 +263,7 @@
const ::aidl::android::media::audio::common::AudioConfig& config,
const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle);
+ bool isPortHeldByAStream(int32_t portId);
status_t prepareToOpenStream(
int32_t aidlHandle,
const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
@@ -318,6 +321,7 @@
std::mutex mLock;
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
+ ConnectedPorts mConnectedPorts;
};
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index f96d419..0d71fd3 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -684,4 +684,26 @@
}
#endif
+status_t DeviceHalHidl::supportsBluetoothVariableLatency(bool* supports) {
+ if (supports == nullptr) {
+ return BAD_VALUE;
+ }
+ *supports = false;
+
+ String8 reply;
+ status_t status = getParameters(
+ String8(AUDIO_PARAMETER_BT_VARIABLE_LATENCY_SUPPORTED), &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ AudioParameter replyParams(reply);
+ String8 trueOrFalse;
+ status = replyParams.get(
+ String8(AUDIO_PARAMETER_BT_VARIABLE_LATENCY_SUPPORTED), trueOrFalse);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ *supports = trueOrFalse == AudioParameter::valueTrue;
+ return NO_ERROR;
+}
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 989c1f5..1a1db33 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -127,10 +127,7 @@
return INVALID_OPERATION;
}
- int32_t supportsBluetoothVariableLatency(bool* supports __unused) override {
- // TODO: Implement the HAL query when moving to AIDL HAL.
- return INVALID_OPERATION;
- }
+ status_t supportsBluetoothVariableLatency(bool* supports) override;
status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 4e34fca..ae73262 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -101,6 +101,8 @@
const void* pCmdData __unused, uint32_t* replySize,
void* pReplyData) {
if (!replySize || *replySize < sizeof(int) || !pReplyData) {
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -110,8 +112,10 @@
status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
- if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize ||
- *replySize < sizeof(int) || !pReplyData) {
+ if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || *replySize < sizeof(int) ||
+ !pReplyData) {
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -130,8 +134,8 @@
status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s illegal cmdSize %u pCmdData %p replySize %p replyData %p", __func__, cmdSize,
- pCmdData, replySize, pReplyData);
+ ALOGE("%s illegal cmdSize %u pCmdData %p replySize %s replyData %p", __func__, cmdSize,
+ pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -158,28 +162,29 @@
uint32_t* replySize, void* pReplyData) {
if (!replySize || *replySize != sizeof(int) || !pReplyData ||
cmdSize != sizeof(effect_config_t)) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
effect_config_t* config = (effect_config_t*)pCmdData;
Parameter::Common common = {
+ .session = mCommon.session,
+ .ioHandle = mCommon.ioHandle,
.input =
VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
config->inputCfg, mIsInputStream)),
.output =
VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
- config->outputCfg, mIsInputStream)),
- .session = mCommon.session,
- .ioHandle = mCommon.ioHandle};
+ config->outputCfg, mIsInputStream))};
State state;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
// in case of buffer/ioHandle re-configure for an opened effect, close it and re-open
if (state != State::INIT && mCommon != common) {
- ALOGI("%s at state %s, closing effect", __func__,
- android::internal::ToString(state).c_str());
+ ALOGI("%s at state %s, common parameter change from %s to %s, closing effect", __func__,
+ android::internal::ToString(state).c_str(), mCommon.toString().c_str(),
+ common.toString().c_str());
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->close()));
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
mStatusQ.reset();
@@ -224,13 +229,19 @@
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
Parameter param;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(
Parameter::Id::make<Parameter::Id::commonTag>(Parameter::common), ¶m)));
+ if (param.getTag() != Parameter::common) {
+ *replySize = 0;
+ ALOGW("%s no valid common tag return from HAL: %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
const auto& common = param.get<Parameter::common>();
effect_config_t* pConfig = (effect_config_t*)pReplyData;
@@ -245,7 +256,8 @@
const void* pCmdData __unused, uint32_t* replySize,
void* pReplyData) {
if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -256,7 +268,8 @@
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -267,7 +280,8 @@
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -277,8 +291,8 @@
status_t EffectConversionHelperAidl::handleSetAudioSource(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
if (!getDescriptor().common.flags.audioSourceIndication) {
@@ -297,8 +311,8 @@
status_t EffectConversionHelperAidl::handleSetAudioMode(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
if (!getDescriptor().common.flags.audioModeIndication) {
@@ -316,8 +330,8 @@
status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
if (!getDescriptor().common.flags.deviceIndication) {
@@ -353,14 +367,28 @@
}
constexpr uint32_t unityGain = 1 << 24;
- Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / unityGain,
- .right = (float)(*(uint32_t*)pCmdData + 1) / unityGain};
+ uint32_t vl = *(uint32_t*)pCmdData;
+ uint32_t vr = *((uint32_t*)pCmdData + 1);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
+ mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(Parameter::VolumeStereo(
+ {.left = (float)vl / unityGain, .right = (float)vr / unityGain})))));
- // write unity gain back if volume was successfully set
+ // get volume from effect and set if changed, return the volume in command if HAL not return
+ // correct parameter.
+ Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
+ Parameter volParam;
+ const status_t getParamStatus = statusTFromBinderStatus(mEffect->getParameter(id, &volParam));
+ if (getParamStatus != OK || volParam.getTag() != Parameter::volumeStereo) {
+ ALOGW("%s no valid volume return from HAL, status %d: %s, return volume in command",
+ __func__, getParamStatus, volParam.toString().c_str());
+ } else {
+ Parameter::VolumeStereo appliedVolume = volParam.get<Parameter::volumeStereo>();
+ vl = (uint32_t)(appliedVolume.left * unityGain);
+ vr = (uint32_t)(appliedVolume.right * unityGain);
+ }
+
if (replySize && *replySize == 2 * sizeof(uint32_t) && pReplyData) {
- constexpr uint32_t vol_ret[2] = {unityGain, unityGain};
+ uint32_t vol_ret[2] = {vl, vr};
memcpy(pReplyData, vol_ret, sizeof(vol_ret));
}
return OK;
@@ -369,8 +397,8 @@
status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
effect_offload_param_t* offload = (effect_offload_param_t*)pCmdData;
@@ -402,7 +430,8 @@
uint32_t* replySize,
void* pReplyData) {
if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -422,7 +451,8 @@
uint32_t* replySize,
void* pReplyData) {
if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -447,8 +477,9 @@
efGroup);
status = (status == OK) ? BAD_VALUE : status;
}
- } else if (isBypassing()) {
- // for effect with bypass (no processing) flag, it's okay to not have statusQ
+ } else if (isBypassingOrTunnel()) {
+ // for effect with bypass (no processing) or offloadIndication flag, it's okay to not have
+ // statusQ
return OK;
}
@@ -456,12 +487,22 @@
return status;
}
+bool EffectConversionHelperAidl::isBypassingOrTunnel() const {
+ return isBypassing() || isTunnel();
+}
+
bool EffectConversionHelperAidl::isBypassing() const {
return mEffect &&
(mDesc.common.flags.bypass ||
(mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
}
+bool EffectConversionHelperAidl::isTunnel() const {
+ return mEffect &&
+ (mDesc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL ||
+ (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isTunnel()));
+}
+
Descriptor EffectConversionHelperAidl::getDescriptor() const {
if (!mIsProxyEffect) {
return mDesc;
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 85e877e..5db334c 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -41,7 +41,10 @@
std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
+
bool isBypassing() const;
+ bool isTunnel() const;
+ bool isBypassingOrTunnel() const;
::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
@@ -72,6 +75,11 @@
static constexpr int kDefaultframeCount = 0x100;
+ template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
+ static inline std::string numericPointerToString(T* pt) {
+ return pt ? std::to_string(*pt) : "nullptr";
+ }
+
using AudioChannelLayout = aidl::android::media::audio::common::AudioChannelLayout;
const aidl::android::media::audio::common::AudioConfig kDefaultAudioConfig = {
.base = {.sampleRate = 44100,
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 7b5e195..1099b6d 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -278,6 +278,11 @@
return mSubEffects[mActiveSubIdx].descriptor.common.flags.bypass;
}
+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) {
const std::string dumpString = toString();
write(fd, dumpString.c_str(), dumpString.size());
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
index 18e1567..0d62642 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -98,6 +98,7 @@
}
bool isBypassing() 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 f9aea37..c058386 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -840,7 +840,7 @@
parameters, String8(AudioParameter::keyOffloadCodecDelaySamples),
[&](int value) {
// The legacy keys are misnamed, the value is in frames.
- return value > 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
+ return value >= 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
}))) {
updateMetadata = true;
}
@@ -848,7 +848,7 @@
parameters, String8(AudioParameter::keyOffloadCodecPaddingSamples),
[&](int value) {
// The legacy keys are misnamed, the value is in frames.
- return value > 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
+ return value >= 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
}))) {
updateMetadata = true;
}
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
index 89f8b83..f77c093 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -227,7 +227,7 @@
RETURN_IF_ERROR(param.readFromValue(&enable));
return DynamicsProcessing::ChannelConfig(
- {.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable)), .channel = channel});
+ {.channel = channel, .enable = VALUE_OR_RETURN(convertIntegral<bool>(enable))});
}
ConversionResult<DynamicsProcessing::EqBandConfig>
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index a965709..dd14135 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -142,7 +142,7 @@
virtual int32_t getAAudioMixerBurstCount() = 0;
virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
- virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0;
+ virtual status_t supportsBluetoothVariableLatency(bool* supports) = 0;
// Update the connection status of an external device.
virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) = 0;
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index fba1a30..9074574 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -96,13 +96,19 @@
status_t setDataSource(
const sp<IDataSource>& dataSource, const char *mime = NULL);
sp<IMemory> getFrameAtTime(int64_t timeUs, int option,
- int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
+ int colorFormat, bool metaOnly = false);
+ sp<IMemory> getFrameAtTime(int64_t timeUs, int option,
+ bool metaOnly = false);
sp<IMemory> getImageAtIndex(int index,
- int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false, bool thumbnail = false);
+ int colorFormat, bool metaOnly = false, bool thumbnail = false);
+ sp<IMemory> getImageAtIndex(int index,
+ bool metaOnly = false, bool thumbnail = false);
sp<IMemory> getImageRectAtIndex(
int index, int colorFormat, int left, int top, int right, int bottom);
sp<IMemory> getFrameAtIndex(
- int index, int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
+ int index, int colorFormat, bool metaOnly = false);
+ sp<IMemory> getFrameAtIndex(
+ int index, bool metaOnly = false);
sp<IMemory> extractAlbumArt();
const char* extractMetadata(int keyCode);
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 2ae76b3..427a3bd 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -142,6 +142,11 @@
}
sp<IMemory> MediaMetadataRetriever::getFrameAtTime(
+ int64_t timeUs, int option, bool metaOnly) {
+ return getFrameAtTime(timeUs, option, HAL_PIXEL_FORMAT_RGB_565, metaOnly);
+}
+
+sp<IMemory> MediaMetadataRetriever::getFrameAtTime(
int64_t timeUs, int option, int colorFormat, bool metaOnly)
{
ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d) colorFormat(%d) metaOnly(%d)",
@@ -155,6 +160,11 @@
}
sp<IMemory> MediaMetadataRetriever::getImageAtIndex(
+ int index, bool metaOnly, bool thumbnail) {
+ return getImageAtIndex(index, HAL_PIXEL_FORMAT_RGB_565, metaOnly, thumbnail);
+}
+
+sp<IMemory> MediaMetadataRetriever::getImageAtIndex(
int index, int colorFormat, bool metaOnly, bool thumbnail) {
ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)",
index, colorFormat, metaOnly, thumbnail);
@@ -180,6 +190,11 @@
}
sp<IMemory> MediaMetadataRetriever::getFrameAtIndex(
+ int index, bool metaOnly) {
+ return getFrameAtIndex(index, HAL_PIXEL_FORMAT_RGB_565, metaOnly);
+}
+
+sp<IMemory> MediaMetadataRetriever::getFrameAtIndex(
int index, int colorFormat, bool metaOnly) {
ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)",
index, colorFormat, metaOnly);
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 44e78d6..718f782 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -47,6 +47,7 @@
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
"libbase",
+ "libbinder_ndk",
"libactivitymanager_aidl",
"libandroid_net",
"libaudioclient",
diff --git a/media/libmediaplayerservice/DeathNotifier.cpp b/media/libmediaplayerservice/DeathNotifier.cpp
index d13bdf5..ab22f67 100644
--- a/media/libmediaplayerservice/DeathNotifier.cpp
+++ b/media/libmediaplayerservice/DeathNotifier.cpp
@@ -31,6 +31,10 @@
DeathRecipient(Notify const& notify): mNotify{notify} {
}
+ void initNdk() {
+ mNdkRecipient.set(AIBinder_DeathRecipient_new(OnBinderDied));
+ }
+
virtual void binderDied(wp<IBinder> const&) override {
mNotify();
}
@@ -39,8 +43,18 @@
mNotify();
}
+ static void OnBinderDied(void *cookie) {
+ DeathRecipient *thiz = (DeathRecipient *)cookie;
+ thiz->mNotify();
+ }
+
+ AIBinder_DeathRecipient *getNdkRecipient() {
+ return mNdkRecipient.get();;
+ }
+
private:
Notify mNotify;
+ ::ndk::ScopedAIBinder_DeathRecipient mNdkRecipient;
};
DeathNotifier::DeathNotifier(sp<IBinder> const& service, Notify const& notify)
@@ -55,6 +69,14 @@
service->linkToDeath(mDeathRecipient, 0);
}
+DeathNotifier::DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify)
+ : mService{std::in_place_index<3>, service},
+ mDeathRecipient{new DeathRecipient(notify)} {
+ mDeathRecipient->initNdk();
+ AIBinder_linkToDeath(
+ service.get(), mDeathRecipient->getNdkRecipient(), mDeathRecipient.get());
+}
+
DeathNotifier::DeathNotifier(DeathNotifier&& other)
: mService{other.mService}, mDeathRecipient{other.mDeathRecipient} {
other.mService.emplace<0>();
@@ -71,6 +93,12 @@
case 2:
std::get<2>(mService)->unlinkToDeath(mDeathRecipient);
break;
+ case 3:
+ AIBinder_unlinkToDeath(
+ std::get<3>(mService).get(),
+ mDeathRecipient->getNdkRecipient(),
+ mDeathRecipient.get());
+ break;
default:
CHECK(false) << "Corrupted service type during destruction.";
}
diff --git a/media/libmediaplayerservice/DeathNotifier.h b/media/libmediaplayerservice/DeathNotifier.h
index 7bc2611..24e45a3 100644
--- a/media/libmediaplayerservice/DeathNotifier.h
+++ b/media/libmediaplayerservice/DeathNotifier.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
#define ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
+#include <android/binder_auto_utils.h>
#include <android/hidl/base/1.0/IBase.h>
#include <binder/Binder.h>
#include <hidl/HidlSupport.h>
@@ -32,11 +33,12 @@
DeathNotifier(sp<IBinder> const& service, Notify const& notify);
DeathNotifier(sp<HBase> const& service, Notify const& notify);
+ DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify);
DeathNotifier(DeathNotifier&& other);
~DeathNotifier();
private:
- std::variant<std::monostate, sp<IBinder>, sp<HBase>> mService;
+ std::variant<std::monostate, sp<IBinder>, sp<HBase>, ::ndk::SpAIBinder> mService;
class DeathRecipient;
sp<DeathRecipient> mDeathRecipient;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 91599e7..10a1da7 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -927,10 +927,10 @@
{
for (std::shared_ptr<Codec2Client> const& client :
Codec2Client::CreateFromAllServices()) {
- sp<IBase> base = client->getBase();
- deathNotifiers.emplace_back(
- base, [l = wp<MediaPlayerBase>(p),
- name = std::string(client->getServiceName())]() {
+ sp<IBase> hidlBase = client->getHidlBase();
+ ::ndk::SpAIBinder aidlBase = client->getAidlBase();
+ auto onBinderDied = [l = wp<MediaPlayerBase>(p),
+ name = std::string(client->getServiceName())]() {
sp<MediaPlayerBase> listener = l.promote();
if (listener) {
ALOGI("Codec2 service \"%s\" died. "
@@ -944,7 +944,12 @@
"without a death handler.",
name.c_str());
}
- });
+ };
+ if (hidlBase) {
+ deathNotifiers.emplace_back(hidlBase, onBinderDied);
+ } else if (aidlBase.get() != nullptr) {
+ deathNotifiers.emplace_back(aidlBase, onBinderDied);
+ }
}
}
}
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index d6b1c90..ed3ec89 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -22,6 +22,7 @@
#include "MediaPlayerService.h"
#include "StagefrightRecorder.h"
+#include <android/binder_auto_utils.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <binder/IPCThreadState.h>
@@ -490,9 +491,9 @@
{
for (std::shared_ptr<Codec2Client> const& client :
Codec2Client::CreateFromAllServices()) {
- sp<IBase> base = client->getBase();
- mDeathNotifiers.emplace_back(
- base, [l = wp<IMediaRecorderClient>(listener),
+ sp<IBase> hidlBase = client->getHidlBase();
+ ::ndk::SpAIBinder aidlBase = client->getAidlBase();
+ auto onBinderDied = [l = wp<IMediaRecorderClient>(listener),
name = std::string(client->getServiceName())]() {
sp<IMediaRecorderClient> listener = l.promote();
if (listener) {
@@ -507,7 +508,12 @@
"without a death handler",
name.c_str());
}
- });
+ };
+ if (hidlBase) {
+ mDeathNotifiers.emplace_back(hidlBase, onBinderDied);
+ } else if (aidlBase.get() != nullptr) {
+ mDeathNotifiers.emplace_back(aidlBase, onBinderDied);
+ }
}
}
}
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index 017f403..c3d6c89 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -35,6 +35,7 @@
shared_libs: [
"framework-permission-aidl-cpp",
"libbinder",
+ "libbinder_ndk",
"libcutils",
"libmedia",
"libstagefright",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 91286b9..e75ca2e 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1791,23 +1791,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/exports.lds b/media/libstagefright/exports.lds
index 7fe6d6c..ee38550 100644
--- a/media/libstagefright/exports.lds
+++ b/media/libstagefright/exports.lds
@@ -171,7 +171,6 @@
FixedDiv1_C;
FixedDiv_C;
fixed_invtbl8;
- GetARGBBlend;
H420ToABGR;
H420ToARGB;
H422ToABGR;
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 41e9aff..bc57ef7 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -105,6 +105,7 @@
mRTCPAddr = mRTPAddr;
mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
+ mVPSBuf = NULL;
mSPSBuf = NULL;
mPPSBuf = NULL;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index fcf3833..a6a0355 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1910,7 +1910,7 @@
config->type = AUDIO_PORT_TYPE_MIX;
config->ext.mix.handle = mId;
config->sample_rate = mSampleRate;
- config->format = mFormat;
+ config->format = mHALFormat;
config->channel_mask = mChannelMask;
config->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
AUDIO_PORT_CONFIG_FORMAT;
@@ -6557,12 +6557,11 @@
// Ensure volumeshaper state always advances even when muted.
const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
- const size_t framesReleased = proxy->framesReleased();
const int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
const int64_t time = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
- ALOGV("%s: Direct/Offload bufferConsumed:%zu timestamp frames:%lld time:%lld",
- __func__, framesReleased, (long long)frames, (long long)time);
+ ALOGVV("%s: Direct/Offload bufferConsumed:%zu timestamp frames:%lld time:%lld",
+ __func__, proxy->framesReleased(), (long long)frames, (long long)time);
const int64_t volumeShaperFrames =
mMonotonicFrameCounter.updateAndGetMonotonicFrameCount(frames, time);
@@ -9619,6 +9618,7 @@
Mutex::Autolock _l(mLock);
AudioStreamIn *input = mInput;
mInput = NULL;
+ mInputSource.clear();
return input;
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 3d5c1d2..6f19a7a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -618,13 +618,15 @@
}
// Convert Sink name to port pointer
sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
- if (sink == NULL && !mIgnoreVendorExtensions) {
- ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
- return BAD_VALUE;
- } else if (sink == NULL) {
- ALOGW("Skipping route to sink \"%s\" as it likely has vendor extension type",
- sinkAttr.c_str());
- return NO_INIT;
+ if (sink == NULL) {
+ if (!mIgnoreVendorExtensions) {
+ ALOGE("%s: no sink found with name \"%s\"", __func__, sinkAttr.c_str());
+ return BAD_VALUE;
+ } else {
+ ALOGW("%s: skipping route to sink \"%s\" as it likely has vendor extension type",
+ __func__, sinkAttr.c_str());
+ return NO_INIT;
+ }
}
route->setSink(sink);
@@ -641,12 +643,14 @@
while (devTag != NULL) {
if (strlen(devTag) != 0) {
sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
- if (source == NULL && !mIgnoreVendorExtensions) {
- ALOGE("%s: no source found with name=%s", __func__, devTag);
- return BAD_VALUE;
- } else if (source == NULL) {
- ALOGW("Skipping route source \"%s\" as it likely has vendor extension type",
- devTag);
+ if (source == NULL) {
+ if (!mIgnoreVendorExtensions) {
+ ALOGE("%s: no source found with name \"%s\"", __func__, devTag);
+ return BAD_VALUE;
+ } else {
+ ALOGW("%s: skipping route source \"%s\" as it likely has vendor extension type",
+ __func__, devTag);
+ }
} else {
sources.add(source);
}
@@ -728,10 +732,16 @@
sp<DeviceDescriptor> device = module->getDeclaredDevices().
getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
attachedDevice.get())));
- if (device == nullptr && mIgnoreVendorExtensions) {
- ALOGW("Skipped attached device \"%s\" because it likely uses a vendor"
- "extension type",
- reinterpret_cast<const char*>(attachedDevice.get()));
+ if (device == NULL) {
+ if (mIgnoreVendorExtensions) {
+ ALOGW("%s: skipped attached device \"%s\" because it likely uses a "
+ "vendor extension type",
+ __func__,
+ reinterpret_cast<const char*>(attachedDevice.get()));
+ } else {
+ ALOGE("%s: got null device in %s, \"%s\"", __func__, child->name,
+ reinterpret_cast<const char*>(attachedDevice.get()));
+ }
continue;
}
ctx->addDevice(device);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index a2ec576..28be652 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 a0e2778..7db3787 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>
@@ -770,8 +771,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;
}
}
@@ -2339,6 +2339,9 @@
// deadlocks (http://b/143513518)
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
+ // Make sure status tracker is flushed
+ mStatusTracker->flushPendingStates();
+
Mutex::Autolock l(mLock);
if (checkAbandonedStreamsLocked()) {
ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
@@ -3032,6 +3035,7 @@
mDoPause(false),
mPaused(true),
mNotifyPipelineDrain(false),
+ mPrevTriggers(0),
mFrameNumber(0),
mLatestRequestId(NAME_NOT_FOUND),
mCurrentAfTriggerId(0),
@@ -3040,7 +3044,6 @@
mAutoframingOverride(ANDROID_CONTROL_AUTOFRAMING_OFF),
mComposerOutput(false),
mCameraMute(ANDROID_SENSOR_TEST_PATTERN_MODE_OFF),
- mCameraMuteChanged(false),
mSettingsOverride(ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF),
mRepeatingLastFrameNumber(
hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
@@ -4235,7 +4238,6 @@
Mutex::Autolock l(mTriggerMutex);
if (muteMode != mCameraMute) {
mCameraMute = muteMode;
- mCameraMuteChanged = true;
}
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 0c1bbcb..dfa3b19 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -703,6 +703,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.
@@ -1156,7 +1165,6 @@
camera_metadata_enum_android_control_autoframing_t mAutoframingOverride;
bool mComposerOutput;
int32_t mCameraMute; // 0 = no mute, otherwise the TEST_PATTERN_MODE to use
- bool mCameraMuteChanged;
int32_t mSettingsOverride; // -1 = use original, otherwise
// the settings override to use.
diff --git a/services/camera/libcameraservice/device3/StatusTracker.cpp b/services/camera/libcameraservice/device3/StatusTracker.cpp
index bd78e0a..f13109a 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.cpp
+++ b/services/camera/libcameraservice/device3/StatusTracker.cpp
@@ -34,7 +34,8 @@
mParent(parent),
mNextComponentId(0),
mIdleFence(new Fence()),
- mDeviceState(IDLE) {
+ mDeviceState(IDLE),
+ mFlushed(true) {
}
StatusTracker::~StatusTracker() {
@@ -111,16 +112,33 @@
const sp<Fence>& componentFence) {
ALOGV("%s: Component %d is now %s", __FUNCTION__, id,
state == IDLE ? "idle" : "active");
- Mutex::Autolock l(mPendingLock);
- StateChange newState = {
- id,
- state,
- componentFence
- };
+ // If any component state changes, the status tracker is considered
+ // not flushed.
+ {
+ Mutex::Autolock l(mFlushLock);
+ mFlushed = false;
+ }
- mPendingChangeQueue.add(newState);
- mPendingChangeSignal.signal();
+ {
+ Mutex::Autolock l(mPendingLock);
+
+ StateChange newState = {
+ id,
+ state,
+ componentFence
+ };
+
+ mPendingChangeQueue.add(newState);
+ mPendingChangeSignal.signal();
+ }
+}
+
+void StatusTracker::flushPendingStates() {
+ Mutex::Autolock l(mFlushLock);
+ while (!mFlushed && isRunning()) {
+ mFlushCondition.waitRelative(mFlushLock, kWaitDuration);
+ }
}
void StatusTracker::requestExit() {
@@ -128,6 +146,7 @@
Thread::requestExit();
// Then exit any waits
mPendingChangeSignal.signal();
+ mFlushCondition.signal();
}
StatusTracker::ComponentState StatusTracker::getDeviceStateLocked() {
@@ -231,6 +250,17 @@
}
mStateTransitions.clear();
+ // After all pending changes are cleared and notified, mark the tracker
+ // as flushed.
+ {
+ Mutex::Autolock fl(mFlushLock);
+ Mutex::Autolock pl(mPendingLock);
+ if (mPendingChangeQueue.size() == 0) {
+ mFlushed = true;
+ mFlushCondition.signal();
+ }
+ }
+
if (waitForIdleFence) {
auto ret = mIdleFence->wait(kWaitDuration);
if (ret == NO_ERROR) {
diff --git a/services/camera/libcameraservice/device3/StatusTracker.h b/services/camera/libcameraservice/device3/StatusTracker.h
index 069bff6..fc65502 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.h
+++ b/services/camera/libcameraservice/device3/StatusTracker.h
@@ -70,6 +70,10 @@
void dumpActiveComponents();
+ // Flush all pending states inflight in the tracker, and return upon
+ // completion.
+ void flushPendingStates();
+
virtual void requestExit();
protected:
@@ -113,6 +117,11 @@
// Current overall device state
ComponentState mDeviceState;
+ // For flushing all pending states transitions
+ bool mFlushed;
+ Mutex mFlushLock;
+ Condition mFlushCondition;
+
// Private to threadLoop
// Determine current overall device state
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index af48dd6..272c390 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>
@@ -313,6 +314,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();
}
@@ -1580,6 +1595,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 e0be367..21813d4 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -257,6 +257,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;
@@ -277,6 +281,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 06af5ff..4488067 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 2cfdf9d..350b072 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -218,6 +218,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;