Merge "AAudio: Add _Nullable and _Nonnull annotations"
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index 713f0b7..4dc5fb1 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -33,7 +33,7 @@
# TODO: replace the following when apex has a way to auto-generate this list
# namespace.default.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
+namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
###############################################################################
# "platform" namespace
@@ -138,7 +138,7 @@
# TODO: replace the following when apex has a way to auto-generate this list
# namespace.sphal.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
+namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
# Add a link for libz.so which is llndk on devices where VNDK is not enforced.
namespace.sphal.link.platform.shared_libs += libz.so
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 7be4bd3..239cb31 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -470,18 +470,6 @@
* <a href="http://developer.android.com/reference/android/media/CamcorderProfile.html">
* CamcorderProfiles</a>.</li>
*
- * <li>For efficient YUV processing with <a href=
- * "http://developer.android.com/reference/android/renderscript/package-summary.html">
- * RenderScript</a>:
- * Create a RenderScript
- * <a href="http://developer.android.com/reference/android/renderscript/Allocation.html">
- * Allocation</a> with a supported YUV
- * type, the IO_INPUT flag, and one of the YUV output sizes returned by
- * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS},
- * Then obtain the Surface with
- * <a href="http://developer.android.com/reference/android/renderscript/Allocation.html#getSurface()">
- * Allocation#getSurface}</a>.</li>
- *
* <li>For access to RAW, uncompressed YUV, or compressed JPEG data in the application: Create an
* {@link AImageReader} object using the {@link AImageReader_new} method with one of the supported
* output formats given by {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}. Then obtain a
diff --git a/drm/README.md b/drm/README.md
new file mode 100644
index 0000000..2681aac
--- /dev/null
+++ b/drm/README.md
@@ -0,0 +1,13 @@
+## AIDL error handling
+
+Starting in **Android U (14)**, `libmediadrm` (app-side) understands extra error
+details from **AIDL** DRM HALs passed through the binder exception message
+as a json string. The supported fields are:
+* `cdmError` (*int*)
+* `oemError` (*int*)
+* `context` (*int*)
+* `errorMessage` (*str*)
+
+The errors details will be reported to apps through the java interface
+`android.media.MediaDrmThrowable`. Please see the javadoc of `MediaDrmThrowable`
+for detailed definitions of each field above.
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
index 2e0bfee..56d63c5 100644
--- a/drm/libmediadrm/DrmHalHidl.cpp
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -514,10 +514,14 @@
if (mimeType == "") {
// isCryptoSchemeSupported(uuid)
*isSupported = true;
- } else {
- // isCryptoSchemeSupported(uuid, mimeType)
- *isSupported = factory->isContentTypeSupported(mimeType.string());
+ return DrmStatus(OK);
}
+ // isCryptoSchemeSupported(uuid, mimeType)
+ auto hResult = factory->isContentTypeSupported(mimeType.string());
+ if (!hResult.isOk()) {
+ return DrmStatus(DEAD_OBJECT);
+ }
+ *isSupported = hResult;
return DrmStatus(OK);
} else if (mimeType == "") {
return DrmStatus(BAD_VALUE);
@@ -527,8 +531,12 @@
if (factoryV1_2 == NULL) {
return DrmStatus(ERROR_UNSUPPORTED);
} else {
- *isSupported = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
+ auto hResult = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
toHidlSecurityLevel(level));
+ if (!hResult.isOk()) {
+ return DrmStatus(DEAD_OBJECT);
+ }
+ *isSupported = hResult;
return DrmStatus(OK);
}
}
@@ -538,7 +546,8 @@
Mutex::Autolock autoLock(mLock);
*isSupported = false;
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
- if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ auto hResult = mFactories[i]->isCryptoSchemeSupported(uuid);
+ if (hResult.isOk() && hResult) {
return matchMimeTypeAndSecurityLevel(mFactories[i], uuid, mimeType, level, isSupported);
}
}
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
index 9c737a0..f7653ff 100644
--- a/drm/libmediadrm/DrmMetricsLogger.cpp
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "DrmMetricsLogger"
#include <media/MediaMetrics.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
#include <mediadrm/DrmHal.h>
#include <mediadrm/DrmMetricsLogger.h>
#include <mediadrm/DrmUtils.h>
@@ -34,7 +36,7 @@
} // namespace
DrmMetricsLogger::DrmMetricsLogger(IDrmFrontend frontend)
- : mImpl(sp<DrmHal>::make()), mUuid(), mObjNonceMsb(0), mObjNonceLsb(0), mFrontend(frontend) {}
+ : mImpl(sp<DrmHal>::make()), mUuid(), mObjNonce(), mFrontend(frontend) {}
DrmMetricsLogger::~DrmMetricsLogger() {}
@@ -57,18 +59,22 @@
}
DrmStatus DrmMetricsLogger::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
- std::memcpy(mUuid, uuid, sizeof(mUuid));
- if (checkGetRandom(&mObjNonceMsb, __func__) == OK &&
- checkGetRandom(&mObjNonceLsb, __func__) == OK) {
- DrmStatus status = mImpl->createPlugin(uuid, appPackageName);
- if (status == OK) {
- reportMediaDrmCreated();
- } else {
- reportMediaDrmErrored(status, __func__);
- }
- return status;
+ std::memcpy(mUuid.data(), uuid, mUuid.size());
+ if (kUuidSchemeMap.count(mUuid)) {
+ mScheme = kUuidSchemeMap.at(mUuid);
+ } else {
+ mScheme = "Other";
}
- return ERROR_DRM_RESOURCE_BUSY;
+ if (generateNonce(&mObjNonce, kNonceSize, __func__) != OK) {
+ return ERROR_DRM_RESOURCE_BUSY;
+ }
+ DrmStatus status = mImpl->createPlugin(uuid, appPackageName);
+ if (status == OK) {
+ reportMediaDrmCreated();
+ } else {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
}
DrmStatus DrmMetricsLogger::destroyPlugin() {
@@ -82,26 +88,25 @@
DrmStatus DrmMetricsLogger::openSession(DrmPlugin::SecurityLevel securityLevel,
Vector<uint8_t>& sessionId) {
SessionContext ctx{};
- if (checkGetRandom(&ctx.mNonceMsb, __func__) == OK &&
- checkGetRandom(&ctx.mNonceLsb, __func__) == OK) {
- DrmStatus status = mImpl->openSession(securityLevel, sessionId);
- if (status == OK) {
- std::vector<uint8_t> sessionKey = toStdVec(sessionId);
- ctx.mTargetSecurityLevel = securityLevel;
- if (getSecurityLevel(sessionId, &ctx.mActualSecurityLevel) != OK) {
- ctx.mActualSecurityLevel = DrmPlugin::kSecurityLevelUnknown;
- }
- {
- const std::lock_guard<std::mutex> lock(mSessionMapMutex);
- mSessionMap.insert({sessionKey, ctx});
- }
- reportMediaDrmSessionOpened(sessionKey);
- } else {
- reportMediaDrmErrored(status, __func__);
- }
- return status;
+ if (generateNonce(&ctx.mNonce, kNonceSize, __func__) != OK) {
+ return ERROR_DRM_RESOURCE_BUSY;
}
- return ERROR_DRM_RESOURCE_BUSY;
+ DrmStatus status = mImpl->openSession(securityLevel, sessionId);
+ if (status == OK) {
+ std::vector<uint8_t> sessionKey = toStdVec(sessionId);
+ ctx.mTargetSecurityLevel = securityLevel;
+ if (getSecurityLevel(sessionId, &ctx.mActualSecurityLevel) != OK) {
+ ctx.mActualSecurityLevel = DrmPlugin::kSecurityLevelUnknown;
+ }
+ {
+ const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+ mSessionMap.insert({sessionKey, ctx});
+ }
+ reportMediaDrmSessionOpened(sessionKey);
+ } else {
+ reportMediaDrmErrored(status, __func__);
+ }
+ return status;
}
DrmStatus DrmMetricsLogger::closeSession(Vector<uint8_t> const& sessionId) {
@@ -419,7 +424,7 @@
bool* required) const {
DrmStatus status = mImpl->requiresSecureDecoder(mime, securityLevel, required);
if (status != OK) {
- reportMediaDrmErrored(status, __func__);
+ reportMediaDrmErrored(status, "requiresSecureDecoderLevel");
}
return status;
}
@@ -451,26 +456,29 @@
void DrmMetricsLogger::reportMediaDrmCreated() const {
mediametrics_handle_t handle(mediametrics_create("mediadrm.created"));
+ mediametrics_setCString(handle, "scheme", mScheme.c_str());
mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
mediametrics_setInt32(handle, "frontend", mFrontend);
+ mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
mediametrics_selfRecord(handle);
mediametrics_delete(handle);
}
void DrmMetricsLogger::reportMediaDrmSessionOpened(const std::vector<uint8_t>& sessionId) const {
mediametrics_handle_t handle(mediametrics_create("mediadrm.session_opened"));
- mediametrics_setInt64(handle, "obj_nonce_msb", mObjNonceMsb);
- mediametrics_setInt64(handle, "obj_nonce_lsb", mObjNonceLsb);
+ mediametrics_setCString(handle, "scheme", mScheme.c_str());
+ mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
+ mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
+ mediametrics_setInt32(handle, "frontend", mFrontend);
+ mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
const std::lock_guard<std::mutex> lock(mSessionMapMutex);
auto it = mSessionMap.find(sessionId);
if (it != mSessionMap.end()) {
- mediametrics_setInt64(handle, "session_nonce_msb", it->second.mNonceMsb);
- mediametrics_setInt64(handle, "session_nonce_lsb", it->second.mNonceLsb);
- mediametrics_setInt64(handle, "target_seucrity_level", it->second.mTargetSecurityLevel);
- mediametrics_setInt64(handle, "actual_seucrity_level", it->second.mActualSecurityLevel);
+ mediametrics_setCString(handle, "session_nonce", it->second.mNonce.c_str());
+ mediametrics_setInt64(handle, "requested_seucrity_level", it->second.mTargetSecurityLevel);
+ mediametrics_setInt64(handle, "opened_seucrity_level", it->second.mActualSecurityLevel);
}
- mediametrics_setInt32(handle, "frontend", mFrontend);
mediametrics_selfRecord(handle);
mediametrics_delete(handle);
}
@@ -478,36 +486,74 @@
void DrmMetricsLogger::reportMediaDrmErrored(const DrmStatus& error_code, const char* api,
const std::vector<uint8_t>& sessionId) const {
mediametrics_handle_t handle(mediametrics_create("mediadrm.errored"));
- mediametrics_setInt64(handle, "obj_nonce_msb", mObjNonceMsb);
- mediametrics_setInt64(handle, "obj_nonce_lsb", mObjNonceLsb);
+ mediametrics_setCString(handle, "scheme", mScheme.c_str());
+ mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
+ mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
+ mediametrics_setInt32(handle, "frontend", mFrontend);
+ mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
if (!sessionId.empty()) {
const std::lock_guard<std::mutex> lock(mSessionMapMutex);
auto it = mSessionMap.find(sessionId);
if (it != mSessionMap.end()) {
- mediametrics_setInt64(handle, "session_nonce_msb", it->second.mNonceMsb);
- mediametrics_setInt64(handle, "session_nonce_lsb", it->second.mNonceLsb);
+ mediametrics_setCString(handle, "session_nonce", it->second.mNonce.c_str());
+ mediametrics_setInt64(handle, "seucrity_level", it->second.mActualSecurityLevel);
}
}
- mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
- mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
+ mediametrics_setCString(handle, "api", api);
mediametrics_setInt32(handle, "error_code", error_code);
mediametrics_setInt32(handle, "cdm_err", error_code.getCdmErr());
mediametrics_setInt32(handle, "oem_err", error_code.getOemErr());
mediametrics_setInt32(handle, "error_context", error_code.getContext());
- mediametrics_setCString(handle, "api", api);
- mediametrics_setInt32(handle, "frontend", mFrontend);
mediametrics_selfRecord(handle);
mediametrics_delete(handle);
}
-DrmStatus DrmMetricsLogger::checkGetRandom(int64_t* nonce, const char* api) {
- ssize_t bytes = getrandom(nonce, sizeof(int64_t), GRND_NONBLOCK);
- if (bytes < sizeof(int64_t)) {
+DrmStatus DrmMetricsLogger::generateNonce(std::string* out, size_t size, const char* api) {
+ std::vector<uint8_t> buf(size);
+ ssize_t bytes = getrandom(buf.data(), size, GRND_NONBLOCK);
+ if (bytes < size) {
ALOGE("getrandom failed: %d", errno);
reportMediaDrmErrored(ERROR_DRM_RESOURCE_BUSY, api);
return ERROR_DRM_RESOURCE_BUSY;
}
+ android::AString tmp;
+ encodeBase64(buf.data(), size, &tmp);
+ out->assign(tmp.c_str());
return OK;
}
+const std::map<std::array<int64_t, 2>, std::string> DrmMetricsLogger::kUuidSchemeMap {
+ {{(int64_t)0x6DD8B3C345F44A68, (int64_t)0xBF3A64168D01A4A6}, "ABV DRM (MoDRM)"},
+ {{(int64_t)0xF239E769EFA34850, (int64_t)0x9C16A903C6932EFB},
+ "Adobe Primetime DRM version 4"},
+ {{(int64_t)0x616C746963617374, (int64_t)0x2D50726F74656374}, "Alticast"},
+ {{(int64_t)0x94CE86FB07FF4F43, (int64_t)0xADB893D2FA968CA2}, "Apple FairPlay"},
+ {{(int64_t)0x279FE473512C48FE, (int64_t)0xADE8D176FEE6B40F}, "Arris Titanium"},
+ {{(int64_t)0x3D5E6D359B9A41E8, (int64_t)0xB843DD3C6E72C42C}, "ChinaDRM"},
+ {{(int64_t)0x3EA8778F77424BF9, (int64_t)0xB18BE834B2ACBD47}, "Clear Key AES-128"},
+ {{(int64_t)0xBE58615B19C44684, (int64_t)0x88B3C8C57E99E957}, "Clear Key SAMPLE-AES"},
+ {{(int64_t)0xE2719D58A985B3C9, (int64_t)0x781AB030AF78D30E}, "Clear Key DASH-IF"},
+ {{(int64_t)0x644FE7B5260F4FAD, (int64_t)0x949A0762FFB054B4}, "CMLA (OMA DRM)"},
+ {{(int64_t)0x37C332587B994C7E, (int64_t)0xB15D19AF74482154}, "Commscope Titanium V3"},
+ {{(int64_t)0x45D481CB8FE049C0, (int64_t)0xADA9AB2D2455B2F2}, "CoreCrypt"},
+ {{(int64_t)0xDCF4E3E362F15818, (int64_t)0x7BA60A6FE33FF3DD}, "DigiCAP SmartXess"},
+ {{(int64_t)0x35BF197B530E42D7, (int64_t)0x8B651B4BF415070F}, "DivX DRM Series 5"},
+ {{(int64_t)0x80A6BE7E14484C37, (int64_t)0x9E70D5AEBE04C8D2}, "Irdeto Content Protection"},
+ {{(int64_t)0x5E629AF538DA4063, (int64_t)0x897797FFBD9902D4},
+ "Marlin Adaptive Streaming Simple Profile V1.0"},
+ {{(int64_t)0x9A04F07998404286, (int64_t)0xAB92E65BE0885F95}, "Microsoft PlayReady"},
+ {{(int64_t)0x6A99532D869F5922, (int64_t)0x9A91113AB7B1E2F3}, "MobiTV DRM"},
+ {{(int64_t)0xADB41C242DBF4A6D, (int64_t)0x958B4457C0D27B95}, "Nagra MediaAccess PRM 3.0"},
+ {{(int64_t)0x1F83E1E86EE94F0D, (int64_t)0xBA2F5EC4E3ED1A66}, "SecureMedia"},
+ {{(int64_t)0x992C46E6C4374899, (int64_t)0xB6A050FA91AD0E39}, "SecureMedia SteelKnot"},
+ {{(int64_t)0xA68129D3575B4F1A, (int64_t)0x9CBA3223846CF7C3},
+ "Synamedia/Cisco/NDS VideoGuard DRM"},
+ {{(int64_t)0xAA11967FCC014A4A, (int64_t)0x8E99C5D3DDDFEA2D}, "Unitend DRM (UDRM)"},
+ {{(int64_t)0x9A27DD82FDE24725, (int64_t)0x8CBC4234AA06EC09}, "Verimatrix VCAS"},
+ {{(int64_t)0xB4413586C58CFFB0, (int64_t)0x94A5D4896C1AF6C3}, "Viaccess-Orca DRM (VODRM)"},
+ {{(int64_t)0x793B79569F944946, (int64_t)0xA94223E7EF7E44B4}, "VisionCrypt"},
+ {{(int64_t)0x1077EFECC0B24D02, (int64_t)0xACE33C1E52E2FB4B}, "W3C Common PSSH box"},
+ {{(int64_t)0xEDEF8BA979D64ACE, (int64_t)0xA3C827DCD51D21ED}, "Widevine Content Protection"},
+};
+
} // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
index b618314..d2e9a56 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
@@ -26,8 +26,7 @@
namespace android {
struct SessionContext {
- int64_t mNonceMsb;
- int64_t mNonceLsb;
+ std::string mNonce;
int64_t mTargetSecurityLevel;
DrmPlugin::SecurityLevel mActualSecurityLevel;
};
@@ -150,12 +149,15 @@
const DrmStatus& error_code, const char* api,
const std::vector<uint8_t>& sessionId = std::vector<uint8_t>()) const;
- DrmStatus checkGetRandom(int64_t* nonce, const char* api);
+ DrmStatus generateNonce(std::string* out, size_t size, const char* api);
private:
+ static const size_t kNonceSize = 16;
+ static const std::map<std::array<int64_t, 2>, std::string> kUuidSchemeMap;
sp<IDrm> mImpl;
- int64_t mUuid[2] = {};
- int64_t mObjNonceMsb, mObjNonceLsb;
+ std::array<int64_t, 2> mUuid;
+ std::string mObjNonce;
+ std::string mScheme;
std::map<std::vector<uint8_t>, SessionContext> mSessionMap;
mutable std::mutex mSessionMapMutex;
IDrmFrontend mFrontend;
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index 2732aa7..eaf5051 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -37,6 +37,7 @@
static_libs: [
"android.hardware.common-V2-ndk",
"libclearkeybase",
+ "libjsoncpp",
],
local_include_dirs: ["include"],
@@ -99,6 +100,7 @@
static_libs: [
"android.hardware.common-V2-ndk",
"libclearkeybase_fuzz",
+ "libjsoncpp",
],
local_include_dirs: ["include"],
@@ -114,13 +116,10 @@
"fuzz_aidl_clearkey_service_defaults",
"service_fuzzer_defaults",
],
- static_libs: [
- "liblog",
- ],
srcs: ["fuzzer.cpp"],
fuzz_config: {
cc: [
"hamzeh@google.com",
],
},
-}
\ No newline at end of file
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
index 054eabd..31cb7c0 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "clearkey-DrmPlugin"
#include <aidl/android/hardware/drm/DrmMetric.h>
+#include <android-base/parseint.h>
#include <utils/Log.h>
#include <inttypes.h>
@@ -83,12 +84,14 @@
void DrmPlugin::initProperties() {
mStringProperties.clear();
mStringProperties[kVendorKey] = kAidlVendorValue;
- mStringProperties[kVersionKey] = kAidlVersionValue;
+ mStringProperties[kVersionKey] = kVersionValue;
mStringProperties[kPluginDescriptionKey] = kAidlPluginDescriptionValue;
mStringProperties[kAlgorithmsKey] = kAidlAlgorithmsValue;
mStringProperties[kListenerTestSupportKey] = kAidlListenerTestSupportValue;
mStringProperties[kDrmErrorTestKey] = kAidlDrmErrorTestValue;
mStringProperties[kAidlVersionKey] = kAidlVersionValue;
+ mStringProperties[kOemErrorKey] = "0";
+ mStringProperties[kErrorContextKey] = "0";
std::vector<uint8_t> valueVector;
valueVector.clear();
@@ -102,6 +105,26 @@
mByteArrayProperties[kMetricsKey] = valueVector;
}
+int32_t DrmPlugin::getIntProperty(const std::string& prop, int32_t defaultVal) const {
+ if (!mStringProperties.count(prop)) {
+ return defaultVal;
+ }
+ int32_t out = defaultVal;
+ if (!::android::base::ParseInt(mStringProperties.at(prop), &out)) {
+ return defaultVal;
+ }
+ return out;
+}
+
+int32_t DrmPlugin::getOemError() const {
+ return getIntProperty(kOemErrorKey);
+}
+
+int32_t DrmPlugin::getErrorContext() const {
+ return getIntProperty(kErrorContextKey);
+}
+
+//
// The secure stop in ClearKey implementation is not installed securely.
// This function merely creates a test environment for testing secure stops APIs.
// The content in this secure stop is implementation dependent, the clearkey
@@ -127,7 +150,10 @@
mSessionLibrary->destroySession(session);
if (session->getMockError() != clearkeydrm::OK) {
sendSessionLostState(in_sessionId);
- return toNdkScopedAStatus(Status::ERROR_DRM_INVALID_STATE);
+ return toNdkScopedAStatus(Status::ERROR_DRM_INVALID_STATE,
+ nullptr,
+ getOemError(),
+ getErrorContext());
}
mCloseSessionOkCount++;
return toNdkScopedAStatus(Status::OK);
@@ -198,7 +224,8 @@
if (!session.get()) {
return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED);
} else if (session->getMockError() != clearkeydrm::OK) {
- return toNdkScopedAStatus(session->getMockError());
+ auto err = static_cast<Status>(session->getMockError());
+ return toNdkScopedAStatus(err, nullptr, getOemError(), getErrorContext());
}
keyRequestType = KeyRequestType::INITIAL;
}
@@ -381,6 +408,10 @@
value = mStringProperties[kDrmErrorTestKey];
} else if (name == kAidlVersionKey) {
value = mStringProperties[kAidlVersionKey];
+ } else if (name == kOemErrorKey) {
+ value = mStringProperties[kOemErrorKey];
+ } else if (name == kErrorContextKey) {
+ value = mStringProperties[kErrorContextKey];
} else {
ALOGE("App requested unknown string property %s", name.c_str());
status = Status::ERROR_DRM_CANNOT_HANDLE;
@@ -921,6 +952,13 @@
}
}
+ if (in_propertyName == kOemErrorKey || in_propertyName == kErrorContextKey) {
+ int32_t err = 0;
+ if (!::android::base::ParseInt(in_value, &err)) {
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+ }
+
mStringProperties[key] = std::string(in_value.c_str());
return toNdkScopedAStatus(Status::OK);
}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
index 9257b17..0db3c37 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
@@ -15,9 +15,12 @@
*/
#pragma once
+#include <cstdint>
#include <string>
#include <vector>
+#include <json/json.h>
+
#include <android/binder_auto_utils.h>
#include "aidl/android/hardware/drm/Status.h"
#include "ClearKeyTypes.h"
@@ -41,17 +44,32 @@
}
inline ::ndk::ScopedAStatus toNdkScopedAStatus(::aidl::android::hardware::drm::Status status,
- const char* msg = nullptr) {
+ const char* msg = nullptr,
+ int32_t oemError = 0,
+ int32_t errorContext = 0) {
+
+
if (Status::OK == status) {
return ::ndk::ScopedAStatus::ok();
- } else {
- auto err = static_cast<int32_t>(status);
- if (msg) {
- return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(err, msg);
- } else {
- return ::ndk::ScopedAStatus::fromServiceSpecificError(err);
- }
}
+
+ Json::Value errObj(Json::objectValue);
+ auto err = static_cast<int32_t>(status);
+ errObj["cdmError"] = err;
+
+ if (oemError) {
+ errObj["oemError"] = oemError;
+ }
+ if (errorContext) {
+ errObj["context"] = errorContext;
+ }
+ if (msg) {
+ errObj["errorMessage"] = msg;
+ }
+
+ Json::FastWriter writer;
+ return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ err, writer.write(errObj).c_str());
}
inline ::ndk::ScopedAStatus toNdkScopedAStatus(clearkeydrm::CdmResponseType res) {
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
index 7acc1b6..694013a 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
@@ -148,6 +148,9 @@
private:
void initProperties();
+ int32_t getIntProperty(const std::string& prop, int32_t defaultVal = 0) const;
+ int32_t getOemError() const;
+ int32_t getErrorContext() const;
void installSecureStop(const std::vector<uint8_t>& sessionId);
bool makeKeySetId(std::string* keySetId);
void setPlayPolicy();
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
index bfda388..d4e641e 100644
--- a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
@@ -21,7 +21,7 @@
static const std::string kVendorKey("vendor");
static const std::string kVendorValue("Google");
static const std::string kVersionKey("version");
-static const std::string kVersionValue("1.2");
+static const std::string kVersionValue("14"); // sync with Android OS version
static const std::string kPluginDescriptionKey("description");
static const std::string kPluginDescriptionValue("ClearKey CDM");
static const std::string kAlgorithmsKey("algorithms");
@@ -35,6 +35,8 @@
static const std::string kFrameTooLargeValue("frameTooLarge");
static const std::string kInvalidStateValue("invalidState");
static const std::string kAidlVersionKey("aidlVersion");
+static const std::string kOemErrorKey("oemError");
+static const std::string kErrorContextKey("errorContext");
static const std::string kDeviceIdKey("deviceId");
static const uint8_t kTestDeviceIdData[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index cb25ddd..d0ff091 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -69,6 +69,8 @@
using media::audio::common::AudioOffloadInfo;
using media::audio::common::AudioOutputFlags;
using media::audio::common::AudioPlaybackRate;
+using media::audio::common::AudioPort;
+using media::audio::common::AudioPortConfig;
using media::audio::common::AudioPortDeviceExt;
using media::audio::common::AudioPortExt;
using media::audio::common::AudioPortMixExt;
@@ -1774,6 +1776,60 @@
return aidl;
}
+ConversionResult<AudioPortDirection> portDirection(audio_port_role_t role, audio_port_type_t type) {
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ case AUDIO_PORT_TYPE_SESSION:
+ break; // must be listed -Werror,-Wswitch
+ case AUDIO_PORT_TYPE_DEVICE:
+ switch (role) {
+ case AUDIO_PORT_ROLE_NONE:
+ break; // must be listed -Werror,-Wswitch
+ case AUDIO_PORT_ROLE_SOURCE:
+ return AudioPortDirection::INPUT;
+ case AUDIO_PORT_ROLE_SINK:
+ return AudioPortDirection::OUTPUT;
+ }
+ break;
+ case AUDIO_PORT_TYPE_MIX:
+ switch (role) {
+ case AUDIO_PORT_ROLE_NONE:
+ break; // must be listed -Werror,-Wswitch
+ case AUDIO_PORT_ROLE_SOURCE:
+ return AudioPortDirection::OUTPUT;
+ case AUDIO_PORT_ROLE_SINK:
+ return AudioPortDirection::INPUT;
+ }
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_port_role_t> portRole(AudioPortDirection direction, audio_port_type_t type) {
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ case AUDIO_PORT_TYPE_SESSION:
+ break; // must be listed -Werror,-Wswitch
+ case AUDIO_PORT_TYPE_DEVICE:
+ switch (direction) {
+ case AudioPortDirection::INPUT:
+ return AUDIO_PORT_ROLE_SOURCE;
+ case AudioPortDirection::OUTPUT:
+ return AUDIO_PORT_ROLE_SINK;
+ }
+ break;
+ case AUDIO_PORT_TYPE_MIX:
+ switch (direction) {
+ case AudioPortDirection::OUTPUT:
+ return AUDIO_PORT_ROLE_SOURCE;
+ case AudioPortDirection::INPUT:
+ return AUDIO_PORT_ROLE_SINK;
+ }
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
ConversionResult<audio_config_t>
aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
const audio_config_base_t legacyBase = VALUE_OR_RETURN(
@@ -1917,6 +1973,396 @@
enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
}
+ConversionResult<audio_port_config_mix_ext_usecase>
+aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ const AudioPortMixExtUseCase& aidl, bool isInput) {
+ audio_port_config_mix_ext_usecase legacy{};
+ if (aidl.getTag() != AudioPortMixExtUseCase::Tag::unspecified) {
+ if (!isInput) {
+ legacy.stream = VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
+ VALUE_OR_RETURN(UNION_GET(aidl, stream))));
+ } else {
+ legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
+ VALUE_OR_RETURN(UNION_GET(aidl, source))));
+ }
+ }
+ return legacy;
+}
+
+ConversionResult<AudioPortMixExtUseCase>
+legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ const audio_port_config_mix_ext_usecase& legacy, bool isInput) {
+ AudioPortMixExtUseCase aidl;
+ if (!isInput) {
+ UNION_SET(aidl, stream, VALUE_OR_RETURN(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream)));
+ } else {
+ UNION_SET(aidl, source, VALUE_OR_RETURN(
+ legacy2aidl_audio_source_t_AudioSource(legacy.source)));
+ }
+ return aidl;
+}
+
+ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_config_mix_ext(
+ const AudioPortMixExt& aidl, bool isInput) {
+ audio_port_config_mix_ext legacy{};
+ legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
+ legacy.usecase = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ aidl.usecase, isInput));
+ return legacy;
+}
+
+ConversionResult<AudioPortMixExt> legacy2aidl_audio_port_config_mix_ext_AudioPortMixExt(
+ const audio_port_config_mix_ext& legacy, bool isInput) {
+ AudioPortMixExt aidl;
+ aidl.handle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
+ aidl.usecase = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ legacy.usecase, isInput));
+ return aidl;
+}
+
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(const AudioPortDeviceExt& aidl) {
+ audio_port_config_device_ext legacy{};
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl.device, &legacy.type, legacy.address));
+ return legacy;
+}
+
+ConversionResult<AudioPortDeviceExt> legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+ const audio_port_config_device_ext& legacy) {
+ AudioPortDeviceExt aidl;
+ aidl.device = VALUE_OR_RETURN(
+ legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
+ return aidl;
+}
+
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_config_ext = decltype(audio_port_config::ext);
+
+status_t aidl2legacy_AudioPortExt_audio_port_config_ext(
+ const AudioPortExt& aidl, bool isInput,
+ audio_port_config_ext* legacy, audio_port_type_t* type) {
+ switch (aidl.getTag()) {
+ case AudioPortExt::Tag::unspecified:
+ // Just verify that the union is empty.
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, unspecified));
+ *legacy = {};
+ *type = AUDIO_PORT_TYPE_NONE;
+ return OK;
+ case AudioPortExt::Tag::device:
+ legacy->device = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, device))));
+ *type = AUDIO_PORT_TYPE_DEVICE;
+ return OK;
+ case AudioPortExt::Tag::mix:
+ legacy->mix = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPortMixExt_audio_port_config_mix_ext(
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, mix)), isInput));
+ *type = AUDIO_PORT_TYPE_MIX;
+ return OK;
+ case AudioPortExt::Tag::session:
+ // This variant is not used in the HAL scenario.
+ legacy->session.session = AUDIO_SESSION_NONE;
+ *type = AUDIO_PORT_TYPE_SESSION;
+ return OK;
+
+ }
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<AudioPortExt> legacy2aidl_audio_port_config_ext_AudioPortExt(
+ const audio_port_config_ext& legacy, audio_port_type_t type, bool isInput) {
+ AudioPortExt aidl;
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ UNION_SET(aidl, unspecified, false);
+ return aidl;
+ case AUDIO_PORT_TYPE_DEVICE: {
+ AudioPortDeviceExt device = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(legacy.device));
+ UNION_SET(aidl, device, device);
+ return aidl;
+ }
+ case AUDIO_PORT_TYPE_MIX: {
+ AudioPortMixExt mix = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_mix_ext_AudioPortMixExt(legacy.mix, isInput));
+ UNION_SET(aidl, mix, mix);
+ return aidl;
+ }
+ case AUDIO_PORT_TYPE_SESSION:
+ // This variant is not used in the HAL scenario.
+ UNION_SET(aidl, unspecified, false);
+ return aidl;
+ }
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+status_t aidl2legacy_AudioPortConfig_audio_port_config(
+ const AudioPortConfig& aidl, bool isInput, audio_port_config* legacy, int32_t* portId) {
+ legacy->id = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_port_handle_t(aidl.id));
+ *portId = aidl.portId;
+ if (aidl.sampleRate.has_value()) {
+ legacy->sample_rate = VALUE_OR_RETURN_STATUS(
+ convertIntegral<unsigned int>(aidl.sampleRate.value().value));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
+ }
+ if (aidl.channelMask.has_value()) {
+ legacy->channel_mask =
+ VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ aidl.channelMask.value(), isInput));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
+ }
+ if (aidl.format.has_value()) {
+ legacy->format = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format.value()));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
+ }
+ if (aidl.gain.has_value()) {
+ legacy->gain = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioGainConfig_audio_gain_config(
+ aidl.gain.value(), isInput));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_GAIN;
+ }
+ if (aidl.flags.has_value()) {
+ legacy->flags = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioIoFlags_audio_io_flags(aidl.flags.value(), isInput));
+ legacy->config_mask |= AUDIO_PORT_CONFIG_FLAGS;
+ }
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioPortExt_audio_port_config_ext(
+ aidl.ext, isInput, &legacy->ext, &legacy->type));
+ legacy->role = VALUE_OR_RETURN_STATUS(portRole(isInput ?
+ AudioPortDirection::INPUT : AudioPortDirection::OUTPUT, legacy->type));
+ return OK;
+}
+
+ConversionResult<AudioPortConfig>
+legacy2aidl_audio_port_config_AudioPortConfig(
+ const audio_port_config& legacy, bool isInput, int32_t portId) {
+ AudioPortConfig aidl;
+ aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ aidl.portId = portId;
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+ Int aidl_sampleRate;
+ aidl_sampleRate.value = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+ aidl.sampleRate = aidl_sampleRate;
+ }
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+ aidl.channelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+ }
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+ aidl.format = VALUE_OR_RETURN(
+ legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+ }
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_GAIN) {
+ aidl.gain = VALUE_OR_RETURN(
+ legacy2aidl_audio_gain_config_AudioGainConfig(legacy.gain, isInput));
+ }
+ if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
+ aidl.flags = VALUE_OR_RETURN(
+ legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, isInput));
+ }
+ aidl.ext = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_ext_AudioPortExt(legacy.ext, legacy.type, isInput));
+ return aidl;
+}
+
+ConversionResult<audio_port_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+ const AudioPortMixExt& aidl) {
+ audio_port_mix_ext legacy{};
+ legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
+ return legacy;
+}
+
+ConversionResult<AudioPortMixExt> legacy2aidl_audio_port_mix_ext_AudioPortMixExt(
+ const audio_port_mix_ext& legacy) {
+ AudioPortMixExt aidl;
+ aidl.handle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
+ return aidl;
+}
+
+ConversionResult<audio_port_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(const AudioPortDeviceExt& aidl) {
+ audio_port_device_ext legacy{};
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl.device, &legacy.type, legacy.address));
+ return legacy;
+}
+
+ConversionResult<AudioPortDeviceExt> legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
+ const audio_port_device_ext& legacy) {
+ AudioPortDeviceExt aidl;
+ aidl.device = VALUE_OR_RETURN(
+ legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
+ return aidl;
+}
+
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_v7_ext = decltype(audio_port_v7::ext);
+
+status_t aidl2legacy_AudioPortExt_audio_port_v7_ext(
+ const AudioPortExt& aidl, audio_port_v7_ext* legacy, audio_port_type_t* type) {
+ switch (aidl.getTag()) {
+ case AudioPortExt::Tag::unspecified:
+ // Just verify that the union is empty.
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, unspecified));
+ *legacy = {};
+ *type = AUDIO_PORT_TYPE_NONE;
+ return OK;
+ case AudioPortExt::Tag::device:
+ legacy->device = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, device))));
+ *type = AUDIO_PORT_TYPE_DEVICE;
+ return OK;
+ case AudioPortExt::Tag::mix:
+ legacy->mix = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+ VALUE_OR_RETURN_STATUS(UNION_GET(aidl, mix))));
+ *type = AUDIO_PORT_TYPE_MIX;
+ return OK;
+ case AudioPortExt::Tag::session:
+ // This variant is not used in the HAL scenario.
+ legacy->session.session = AUDIO_SESSION_NONE;
+ *type = AUDIO_PORT_TYPE_SESSION;
+ return OK;
+
+ }
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<AudioPortExt> legacy2aidl_audio_port_v7_ext_AudioPortExt(
+ const audio_port_v7_ext& legacy, audio_port_type_t type) {
+ AudioPortExt aidl;
+ switch (type) {
+ case AUDIO_PORT_TYPE_NONE:
+ UNION_SET(aidl, unspecified, false);
+ return aidl;
+ case AUDIO_PORT_TYPE_DEVICE: {
+ AudioPortDeviceExt device = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(legacy.device));
+ UNION_SET(aidl, device, device);
+ return aidl;
+ }
+ case AUDIO_PORT_TYPE_MIX: {
+ AudioPortMixExt mix = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_mix_ext_AudioPortMixExt(legacy.mix));
+ UNION_SET(aidl, mix, mix);
+ return aidl;
+ }
+ case AUDIO_PORT_TYPE_SESSION:
+ // This variant is not used in the HAL scenario.
+ UNION_SET(aidl, unspecified, false);
+ return aidl;
+ }
+ LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<audio_port_v7>
+aidl2legacy_AudioPort_audio_port_v7(const AudioPort& aidl, bool isInput) {
+ audio_port_v7 legacy;
+ legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.id));
+ RETURN_IF_ERROR(aidl2legacy_string(aidl.name, legacy.name, sizeof(legacy.name)));
+
+ if (aidl.profiles.size() > std::size(legacy.audio_profiles)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(convertRange(
+ aidl.profiles.begin(), aidl.profiles.end(), legacy.audio_profiles,
+ [isInput](const AudioProfile& p) {
+ return aidl2legacy_AudioProfile_audio_profile(p, isInput);
+ }));
+ legacy.num_audio_profiles = aidl.profiles.size();
+
+ if (aidl.extraAudioDescriptors.size() > std::size(legacy.extra_audio_descriptors)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(
+ aidl.extraAudioDescriptors.begin(), aidl.extraAudioDescriptors.end(),
+ legacy.extra_audio_descriptors,
+ aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor));
+ legacy.num_extra_audio_descriptors = aidl.extraAudioDescriptors.size();
+
+ if (aidl.gains.size() > std::size(legacy.gains)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(convertRange(aidl.gains.begin(), aidl.gains.end(), legacy.gains,
+ [isInput](const AudioGain& g) {
+ return aidl2legacy_AudioGain_audio_gain(g, isInput);
+ }));
+ legacy.num_gains = aidl.gains.size();
+
+ RETURN_IF_ERROR(aidl2legacy_AudioPortExt_audio_port_v7_ext(
+ aidl.ext, &legacy.ext, &legacy.type));
+ legacy.role = VALUE_OR_RETURN(portRole(
+ isInput ? AudioPortDirection::INPUT : AudioPortDirection::OUTPUT, legacy.type));
+
+ AudioPortConfig aidlPortConfig;
+ int32_t portId;
+ aidlPortConfig.flags = aidl.flags;
+ aidlPortConfig.ext = aidl.ext;
+ RETURN_IF_ERROR(aidl2legacy_AudioPortConfig_audio_port_config(
+ aidlPortConfig, isInput, &legacy.active_config, &portId));
+ return legacy;
+}
+
+ConversionResult<AudioPort>
+legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy, bool isInput) {
+ AudioPort aidl;
+ aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ aidl.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
+
+ if (legacy.num_audio_profiles > std::size(legacy.audio_profiles)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(legacy.audio_profiles, legacy.audio_profiles + legacy.num_audio_profiles,
+ std::back_inserter(aidl.profiles),
+ [isInput](const audio_profile& p) {
+ return legacy2aidl_audio_profile_AudioProfile(p, isInput);
+ }));
+
+ if (legacy.num_extra_audio_descriptors > std::size(legacy.extra_audio_descriptors)) {
+ return unexpected(BAD_VALUE);
+ }
+ aidl.profiles.resize(legacy.num_audio_profiles);
+ RETURN_IF_ERROR(
+ convertRange(legacy.extra_audio_descriptors,
+ legacy.extra_audio_descriptors + legacy.num_extra_audio_descriptors,
+ std::back_inserter(aidl.extraAudioDescriptors),
+ legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor));
+
+ if (legacy.num_gains > std::size(legacy.gains)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(legacy.gains, legacy.gains + legacy.num_gains,
+ std::back_inserter(aidl.gains),
+ [isInput](const audio_gain& g) {
+ return legacy2aidl_audio_gain_AudioGain(g, isInput);
+ }));
+ aidl.gains.resize(legacy.num_gains);
+
+ aidl.ext = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_v7_ext_AudioPortExt(legacy.ext, legacy.type));
+
+ AudioPortConfig aidlPortConfig = VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfig(
+ legacy.active_config, isInput, aidl.id));
+ if (aidlPortConfig.flags.has_value()) {
+ aidl.flags = aidlPortConfig.flags.value();
+ } else {
+ aidl.flags = isInput ?
+ AudioIoFlags::make<AudioIoFlags::Tag::input>(0) :
+ AudioIoFlags::make<AudioIoFlags::Tag::output>(0);
+ }
+ return aidl;
+}
+
ConversionResult<audio_profile>
aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
audio_profile legacy;
diff --git a/media/audioaidlconversion/AidlConversionEffect.cpp b/media/audioaidlconversion/AidlConversionEffect.cpp
new file mode 100644
index 0000000..9660072
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionEffect.cpp
@@ -0,0 +1,352 @@
+/*
+ * 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 <utility>
+
+#define LOG_TAG "AidlConversionEffect"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionEffect.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AIDL NDK backend to legacy audio data structure conversion utilities.
+
+namespace aidl {
+namespace android {
+
+using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControl;
+using ::aidl::android::hardware::audio::effect::BassBoost;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Downmix;
+using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+
+using ::android::BAD_VALUE;
+using ::android::base::unexpected;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Converters
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Type_uint32(Flags::Type type) {
+ switch (type) {
+ case Flags::Type::INSERT:
+ return EFFECT_FLAG_TYPE_INSERT;
+ case Flags::Type::AUXILIARY:
+ return EFFECT_FLAG_TYPE_AUXILIARY;
+ case Flags::Type::REPLACE:
+ return EFFECT_FLAG_TYPE_REPLACE;
+ case Flags::Type::PRE_PROC:
+ return EFFECT_FLAG_TYPE_PRE_PROC;
+ case Flags::Type::POST_PROC:
+ return EFFECT_FLAG_TYPE_POST_PROC;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Type> legacy2aidl_uint32_Flags_Type(uint32_t legacy) {
+ switch (legacy & EFFECT_FLAG_TYPE_MASK) {
+ case EFFECT_FLAG_TYPE_INSERT:
+ return Flags::Type::INSERT;
+ case EFFECT_FLAG_TYPE_AUXILIARY:
+ return Flags::Type::AUXILIARY;
+ case EFFECT_FLAG_TYPE_REPLACE:
+ return Flags::Type::REPLACE;
+ case EFFECT_FLAG_TYPE_PRE_PROC:
+ return Flags::Type::PRE_PROC;
+ case EFFECT_FLAG_TYPE_POST_PROC:
+ return Flags::Type::POST_PROC;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Insert_uint32(Flags::Insert insert) {
+ switch (insert) {
+ case Flags::Insert::ANY:
+ return EFFECT_FLAG_INSERT_ANY;
+ case Flags::Insert::FIRST:
+ return EFFECT_FLAG_INSERT_FIRST;
+ case Flags::Insert::LAST:
+ return EFFECT_FLAG_INSERT_LAST;
+ case Flags::Insert::EXCLUSIVE:
+ return EFFECT_FLAG_INSERT_EXCLUSIVE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Insert> legacy2aidl_uint32_Flags_Insert(uint32_t legacy) {
+ switch (legacy & EFFECT_FLAG_INSERT_MASK) {
+ case EFFECT_FLAG_INSERT_ANY:
+ return Flags::Insert::ANY;
+ case EFFECT_FLAG_INSERT_FIRST:
+ return Flags::Insert::FIRST;
+ case EFFECT_FLAG_INSERT_LAST:
+ return Flags::Insert::LAST;
+ case EFFECT_FLAG_INSERT_EXCLUSIVE:
+ return Flags::Insert::EXCLUSIVE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Volume_uint32(Flags::Volume volume) {
+ switch (volume) {
+ case Flags::Volume::NONE:
+ return 0;
+ case Flags::Volume::CTRL:
+ return EFFECT_FLAG_VOLUME_CTRL;
+ case Flags::Volume::IND:
+ return EFFECT_FLAG_VOLUME_IND;
+ case Flags::Volume::MONITOR:
+ return EFFECT_FLAG_VOLUME_MONITOR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Volume> legacy2aidl_uint32_Flags_Volume(uint32_t legacy) {
+ switch (legacy & EFFECT_FLAG_VOLUME_MASK) {
+ case EFFECT_FLAG_VOLUME_CTRL:
+ return Flags::Volume::CTRL;
+ case EFFECT_FLAG_VOLUME_IND:
+ return Flags::Volume::IND;
+ case EFFECT_FLAG_VOLUME_MONITOR:
+ return Flags::Volume::MONITOR;
+ case EFFECT_FLAG_VOLUME_NONE:
+ return Flags::Volume::NONE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_uint32(Flags aidl) {
+ uint32_t legacy = 0;
+ legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Type_uint32(aidl.type));
+ legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Insert_uint32(aidl.insert));
+ legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Volume_uint32(aidl.volume));
+ legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_HardwareAccelerator_uint32(aidl.hwAcceleratorMode));
+
+ if (aidl.offloadIndication) {
+ legacy |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
+ }
+ if (aidl.deviceIndication) {
+ legacy |= EFFECT_FLAG_DEVICE_IND;
+ }
+ if (aidl.audioModeIndication) {
+ legacy |= EFFECT_FLAG_AUDIO_MODE_IND;
+ }
+ if (aidl.audioSourceIndication) {
+ legacy |= EFFECT_FLAG_AUDIO_SOURCE_IND;
+ }
+ if (aidl.noProcessing) {
+ legacy |= EFFECT_FLAG_NO_PROCESS;
+ }
+ return legacy;
+}
+
+ConversionResult<Flags> legacy2aidl_uint32_Flags(uint32_t legacy) {
+ Flags aidl;
+
+ aidl.type = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Type(legacy));
+ aidl.insert = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Insert(legacy));
+ aidl.volume = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Volume(legacy));
+ aidl.hwAcceleratorMode = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_HardwareAccelerator(legacy));
+ aidl.offloadIndication = (legacy & EFFECT_FLAG_OFFLOAD_SUPPORTED);
+ aidl.deviceIndication = (legacy & EFFECT_FLAG_DEVICE_IND);
+ aidl.audioModeIndication = (legacy & EFFECT_FLAG_AUDIO_MODE_IND);
+ aidl.audioSourceIndication = (legacy & EFFECT_FLAG_AUDIO_SOURCE_IND);
+ aidl.noProcessing = (legacy & EFFECT_FLAG_NO_PROCESS);
+ return aidl;
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_HardwareAccelerator_uint32(
+ Flags::HardwareAccelerator hwAcceleratorMode) {
+ switch (hwAcceleratorMode) {
+ case Flags::HardwareAccelerator::NONE:
+ return 0;
+ case Flags::HardwareAccelerator::SIMPLE:
+ return EFFECT_FLAG_HW_ACC_SIMPLE;
+ case Flags::HardwareAccelerator::TUNNEL:
+ return EFFECT_FLAG_HW_ACC_TUNNEL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::HardwareAccelerator> legacy2aidl_uint32_Flags_HardwareAccelerator(
+ uint32_t legacy) {
+ switch (legacy & EFFECT_FLAG_HW_ACC_MASK) {
+ case EFFECT_FLAG_HW_ACC_SIMPLE:
+ return Flags::HardwareAccelerator::SIMPLE;
+ case EFFECT_FLAG_HW_ACC_TUNNEL:
+ return Flags::HardwareAccelerator::TUNNEL;
+ case 0:
+ return Flags::HardwareAccelerator::NONE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<effect_descriptor_t>
+aidl2legacy_Descriptor_effect_descriptor(const Descriptor& aidl) {
+ effect_descriptor_t legacy;
+ legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.common.id.type));
+ legacy.uuid = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.common.id.uuid));
+ // legacy descriptor doesn't have proxy information
+ // proxy = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.proxy));
+ legacy.apiVersion = EFFECT_CONTROL_API_VERSION;
+ legacy.flags = VALUE_OR_RETURN(aidl2legacy_Flags_uint32(aidl.common.flags));
+ legacy.cpuLoad = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.common.cpuLoad));
+ legacy.memoryUsage = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.common.memoryUsage));
+ RETURN_IF_ERROR(aidl2legacy_string(aidl.common.name, legacy.name, sizeof(legacy.name)));
+ RETURN_IF_ERROR(aidl2legacy_string(aidl.common.implementor, legacy.implementor,
+ sizeof(legacy.implementor)));
+ return legacy;
+}
+
+ConversionResult<Descriptor>
+legacy2aidl_effect_descriptor_Descriptor(const effect_descriptor_t& legacy) {
+ Descriptor aidl;
+ aidl.common.id.type = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.type));
+ aidl.common.id.uuid = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.uuid));
+ // legacy descriptor doesn't have proxy information
+ // aidl.common.id.proxy
+ aidl.common.flags = VALUE_OR_RETURN(legacy2aidl_uint32_Flags(legacy.flags));
+ aidl.common.cpuLoad = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.cpuLoad));
+ aidl.common.memoryUsage = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.memoryUsage));
+ aidl.common.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
+ aidl.common.implementor =
+ VALUE_OR_RETURN(legacy2aidl_string(legacy.implementor, sizeof(legacy.implementor)));
+ return aidl;
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_echoDelay(const Parameter& aidl) {
+ int echoDelay = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AcousticEchoCanceler, acousticEchoCanceler,
+ AcousticEchoCanceler::echoDelayUs, int));
+ return VALUE_OR_RETURN(convertReinterpret<uint32_t>(echoDelay));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_echoDelay_Parameter_aec(uint32_t legacy) {
+ int delay = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, echoDelayUs, delay);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_mobileMode(const Parameter& aidl) {
+ bool mobileMode = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AcousticEchoCanceler, acousticEchoCanceler,
+ AcousticEchoCanceler::mobileMode, bool));
+ return VALUE_OR_RETURN(convertIntegral<uint32_t>(mobileMode));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_mobileMode_Parameter_aec(uint32_t legacy) {
+ bool mode = VALUE_OR_RETURN(convertIntegral<bool>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, mobileMode, mode);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
+ const Parameter& aidl) {
+ int gain = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControl, automaticGainControl,
+ AutomaticGainControl::fixedDigitalGainMb, int));
+ return VALUE_OR_RETURN(convertReinterpret<uint32_t>(gain));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy) {
+ int gain = VALUE_OR_RETURN(convertReinterpret<int>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, fixedDigitalGainMb,
+ gain);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
+ const Parameter& aidl) {
+ const auto& le = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
+ aidl, AutomaticGainControl, automaticGainControl, AutomaticGainControl::levelEstimator,
+ AutomaticGainControl::LevelEstimator));
+ return static_cast<uint32_t>(le);
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy) {
+ if (legacy > (uint32_t) AutomaticGainControl::LevelEstimator::PEAK) {
+ return unexpected(BAD_VALUE);
+ }
+ AutomaticGainControl::LevelEstimator le =
+ static_cast<AutomaticGainControl::LevelEstimator>(legacy);
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, levelEstimator, le);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
+ const Parameter& aidl) {
+ int saturationMargin = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControl, automaticGainControl,
+ AutomaticGainControl::saturationMarginMb, int));
+ return VALUE_OR_RETURN(convertIntegral<uint32_t>(saturationMargin));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy) {
+ int saturationMargin = VALUE_OR_RETURN(convertIntegral<int>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, saturationMarginMb,
+ saturationMargin);
+}
+
+ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
+ const Parameter& aidl) {
+ int strength = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, BassBoost, bassBoost, BassBoost::strengthPm, int));
+ return VALUE_OR_RETURN(convertIntegral<uint16_t>(strength));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint16_strengthPm_Parameter_BassBoost(uint16_t legacy) {
+ int strength = VALUE_OR_RETURN(convertIntegral<int>(legacy));
+ return MAKE_SPECIFIC_PARAMETER(BassBoost, bassBoost, strengthPm, strength);
+}
+
+ConversionResult<int16_t> aidl2legacy_Parameter_Downmix_int16_type(const Parameter& aidl) {
+ Downmix::Type aidlType = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, Downmix, downmix, Downmix::type, Downmix::Type));
+ return VALUE_OR_RETURN(convertIntegral<int16_t>(static_cast<uint32_t>(aidlType)));
+}
+
+ConversionResult<Parameter> legacy2aidl_int16_type_Parameter_Downmix(int16_t legacy) {
+ if (legacy > (uint32_t) Downmix::Type::FOLD) {
+ return unexpected(BAD_VALUE);
+ }
+ Downmix::Type aidlType = static_cast<Downmix::Type>(legacy);
+ return MAKE_SPECIFIC_PARAMETER(Downmix, downmix, type, aidlType);
+}
+
+ConversionResult<int16_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_uint32_(
+ const Parameter& aidl) {
+ Downmix::Type aidlType = VALUE_OR_RETURN(
+ GET_PARAMETER_SPECIFIC_FIELD(aidl, Downmix, downmix, Downmix::type, Downmix::Type));
+ return VALUE_OR_RETURN(convertIntegral<int16_t>(static_cast<uint32_t>(aidlType)));
+}
+
+ConversionResult<DynamicsProcessing::ResolutionPreference>
+legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(int32_t legacy) {
+ if (legacy > (int32_t)DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION) {
+ return unexpected(BAD_VALUE);
+ }
+ return static_cast<DynamicsProcessing::ResolutionPreference>(legacy);
+}
+
+ConversionResult<int32_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+ DynamicsProcessing::ResolutionPreference aidl) {
+ return static_cast<int32_t>(aidl);
+}
+
+
+} // namespace android
+} // aidl
diff --git a/media/audioaidlconversion/AidlConversionNdk.cpp b/media/audioaidlconversion/AidlConversionNdk.cpp
index 8fec660..7c63339 100644
--- a/media/audioaidlconversion/AidlConversionNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionNdk.cpp
@@ -29,208 +29,6 @@
namespace aidl {
namespace android {
-using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
-using ::aidl::android::hardware::audio::effect::AutomaticGainControl;
-using ::aidl::android::hardware::audio::effect::BassBoost;
-using ::aidl::android::hardware::audio::effect::Descriptor;
-using ::aidl::android::hardware::audio::effect::Downmix;
-using ::aidl::android::hardware::audio::effect::Flags;
-using ::aidl::android::hardware::audio::effect::Parameter;
-using ::aidl::android::media::audio::common::AudioDeviceDescription;
-
-using ::android::BAD_VALUE;
-using ::android::base::unexpected;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Converters
-
-ConversionResult<uint32_t> aidl2legacy_Flags_Type_uint32(Flags::Type type) {
- switch (type) {
- case Flags::Type::INSERT:
- return EFFECT_FLAG_TYPE_INSERT;
- case Flags::Type::AUXILIARY:
- return EFFECT_FLAG_TYPE_AUXILIARY;
- case Flags::Type::REPLACE:
- return EFFECT_FLAG_TYPE_REPLACE;
- case Flags::Type::PRE_PROC:
- return EFFECT_FLAG_TYPE_PRE_PROC;
- case Flags::Type::POST_PROC:
- return EFFECT_FLAG_TYPE_POST_PROC;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<Flags::Type> legacy2aidl_uint32_Flags_Type(uint32_t legacy) {
- switch (legacy & EFFECT_FLAG_TYPE_MASK) {
- case EFFECT_FLAG_TYPE_INSERT:
- return Flags::Type::INSERT;
- case EFFECT_FLAG_TYPE_AUXILIARY:
- return Flags::Type::AUXILIARY;
- case EFFECT_FLAG_TYPE_REPLACE:
- return Flags::Type::REPLACE;
- case EFFECT_FLAG_TYPE_PRE_PROC:
- return Flags::Type::PRE_PROC;
- case EFFECT_FLAG_TYPE_POST_PROC:
- return Flags::Type::POST_PROC;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<uint32_t> aidl2legacy_Flags_Insert_uint32(Flags::Insert insert) {
- switch (insert) {
- case Flags::Insert::ANY:
- return EFFECT_FLAG_INSERT_ANY;
- case Flags::Insert::FIRST:
- return EFFECT_FLAG_INSERT_FIRST;
- case Flags::Insert::LAST:
- return EFFECT_FLAG_INSERT_LAST;
- case Flags::Insert::EXCLUSIVE:
- return EFFECT_FLAG_INSERT_EXCLUSIVE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<Flags::Insert> legacy2aidl_uint32_Flags_Insert(uint32_t legacy) {
- switch (legacy & EFFECT_FLAG_INSERT_MASK) {
- case EFFECT_FLAG_INSERT_ANY:
- return Flags::Insert::ANY;
- case EFFECT_FLAG_INSERT_FIRST:
- return Flags::Insert::FIRST;
- case EFFECT_FLAG_INSERT_LAST:
- return Flags::Insert::LAST;
- case EFFECT_FLAG_INSERT_EXCLUSIVE:
- return Flags::Insert::EXCLUSIVE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<uint32_t> aidl2legacy_Flags_Volume_uint32(Flags::Volume volume) {
- switch (volume) {
- case Flags::Volume::NONE:
- return 0;
- case Flags::Volume::CTRL:
- return EFFECT_FLAG_VOLUME_CTRL;
- case Flags::Volume::IND:
- return EFFECT_FLAG_VOLUME_IND;
- case Flags::Volume::MONITOR:
- return EFFECT_FLAG_VOLUME_MONITOR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<Flags::Volume> legacy2aidl_uint32_Flags_Volume(uint32_t legacy) {
- switch (legacy & EFFECT_FLAG_VOLUME_MASK) {
- case EFFECT_FLAG_VOLUME_CTRL:
- return Flags::Volume::CTRL;
- case EFFECT_FLAG_VOLUME_IND:
- return Flags::Volume::IND;
- case EFFECT_FLAG_VOLUME_MONITOR:
- return Flags::Volume::MONITOR;
- case EFFECT_FLAG_VOLUME_NONE:
- return Flags::Volume::NONE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<uint32_t> aidl2legacy_Flags_uint32(Flags aidl) {
- uint32_t legacy = 0;
- legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Type_uint32(aidl.type));
- legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Insert_uint32(aidl.insert));
- legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Volume_uint32(aidl.volume));
- legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_HardwareAccelerator_uint32(aidl.hwAcceleratorMode));
-
- if (aidl.offloadIndication) {
- legacy |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
- }
- if (aidl.deviceIndication) {
- legacy |= EFFECT_FLAG_DEVICE_IND;
- }
- if (aidl.audioModeIndication) {
- legacy |= EFFECT_FLAG_AUDIO_MODE_IND;
- }
- if (aidl.audioSourceIndication) {
- legacy |= EFFECT_FLAG_AUDIO_SOURCE_IND;
- }
- if (aidl.noProcessing) {
- legacy |= EFFECT_FLAG_NO_PROCESS;
- }
- return legacy;
-}
-
-ConversionResult<Flags> legacy2aidl_uint32_Flags(uint32_t legacy) {
- Flags aidl;
-
- aidl.type = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Type(legacy));
- aidl.insert = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Insert(legacy));
- aidl.volume = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Volume(legacy));
- aidl.hwAcceleratorMode = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_HardwareAccelerator(legacy));
- aidl.offloadIndication = (legacy & EFFECT_FLAG_OFFLOAD_SUPPORTED);
- aidl.deviceIndication = (legacy & EFFECT_FLAG_DEVICE_IND);
- aidl.audioModeIndication = (legacy & EFFECT_FLAG_AUDIO_MODE_IND);
- aidl.audioSourceIndication = (legacy & EFFECT_FLAG_AUDIO_SOURCE_IND);
- aidl.noProcessing = (legacy & EFFECT_FLAG_NO_PROCESS);
- return aidl;
-}
-
-ConversionResult<uint32_t> aidl2legacy_Flags_HardwareAccelerator_uint32(
- Flags::HardwareAccelerator hwAcceleratorMode) {
- switch (hwAcceleratorMode) {
- case Flags::HardwareAccelerator::NONE:
- return 0;
- case Flags::HardwareAccelerator::SIMPLE:
- return EFFECT_FLAG_HW_ACC_SIMPLE;
- case Flags::HardwareAccelerator::TUNNEL:
- return EFFECT_FLAG_HW_ACC_TUNNEL;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<Flags::HardwareAccelerator> legacy2aidl_uint32_Flags_HardwareAccelerator(
- uint32_t legacy) {
- switch (legacy & EFFECT_FLAG_HW_ACC_MASK) {
- case EFFECT_FLAG_HW_ACC_SIMPLE:
- return Flags::HardwareAccelerator::SIMPLE;
- case EFFECT_FLAG_HW_ACC_TUNNEL:
- return Flags::HardwareAccelerator::TUNNEL;
- case 0:
- return Flags::HardwareAccelerator::NONE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<effect_descriptor_t>
-aidl2legacy_Descriptor_effect_descriptor(const Descriptor& aidl) {
- effect_descriptor_t legacy;
- legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.common.id.type));
- legacy.uuid = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.common.id.uuid));
- // legacy descriptor doesn't have proxy information
- // proxy = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.proxy));
- legacy.apiVersion = EFFECT_CONTROL_API_VERSION;
- legacy.flags = VALUE_OR_RETURN(aidl2legacy_Flags_uint32(aidl.common.flags));
- legacy.cpuLoad = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.common.cpuLoad));
- legacy.memoryUsage = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.common.memoryUsage));
- RETURN_IF_ERROR(aidl2legacy_string(aidl.common.name, legacy.name, sizeof(legacy.name)));
- RETURN_IF_ERROR(aidl2legacy_string(aidl.common.implementor, legacy.implementor,
- sizeof(legacy.implementor)));
- return legacy;
-}
-
-ConversionResult<Descriptor>
-legacy2aidl_effect_descriptor_Descriptor(const effect_descriptor_t& legacy) {
- Descriptor aidl;
- aidl.common.id.type = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.type));
- aidl.common.id.uuid = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.uuid));
- // legacy descriptor doesn't have proxy information
- // aidl.common.id.proxy
- aidl.common.flags = VALUE_OR_RETURN(legacy2aidl_uint32_Flags(legacy.flags));
- aidl.common.cpuLoad = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.cpuLoad));
- aidl.common.memoryUsage = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.memoryUsage));
- aidl.common.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
- aidl.common.implementor =
- VALUE_OR_RETURN(legacy2aidl_string(legacy.implementor, sizeof(legacy.implementor)));
- return aidl;
-}
-
// buffer_provider_t is not supported thus skipped
ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
const media::audio::common::AudioConfigBase& aidl, bool isInput) {
@@ -270,96 +68,5 @@
return aidl;
}
-ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_echoDelay(const Parameter& aidl) {
- int echoDelay = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
- aidl, AcousticEchoCanceler, acousticEchoCanceler, echoDelayUs, int));
- return VALUE_OR_RETURN(convertReinterpret<uint32_t>(echoDelay));
-}
-
-ConversionResult<Parameter> legacy2aidl_uint32_echoDelay_Parameter_aec(uint32_t legacy) {
- int delay = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy));
- return MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, echoDelayUs, delay);
-}
-
-ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_mobileMode(const Parameter& aidl) {
- bool mobileMode = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
- aidl, AcousticEchoCanceler, acousticEchoCanceler, mobileMode, bool));
- return VALUE_OR_RETURN(convertIntegral<uint32_t>(mobileMode));
-}
-
-ConversionResult<Parameter> legacy2aidl_uint32_mobileMode_Parameter_aec(uint32_t legacy) {
- bool mode = VALUE_OR_RETURN(convertIntegral<bool>(legacy));
- return MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, mobileMode, mode);
-}
-
-ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
- const Parameter& aidl) {
- int gain = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
- aidl, AutomaticGainControl, automaticGainControl, fixedDigitalGainMb, int));
- return VALUE_OR_RETURN(convertReinterpret<uint32_t>(gain));
-}
-
-ConversionResult<Parameter> legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy) {
- int gain = VALUE_OR_RETURN(convertReinterpret<int>(legacy));
- return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, fixedDigitalGainMb,
- gain);
-}
-
-ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
- const Parameter& aidl) {
- const auto& le = VALUE_OR_RETURN(
- GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControl, automaticGainControl,
- levelEstimator, AutomaticGainControl::LevelEstimator));
- return static_cast<uint32_t>(le);
-}
-
-ConversionResult<Parameter> legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy) {
- if (legacy > (uint32_t) AutomaticGainControl::LevelEstimator::PEAK) {
- return unexpected(BAD_VALUE);
- }
- AutomaticGainControl::LevelEstimator le =
- static_cast<AutomaticGainControl::LevelEstimator>(legacy);
- return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, levelEstimator, le);
-}
-
-ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
- const Parameter& aidl) {
- int saturationMargin = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
- aidl, AutomaticGainControl, automaticGainControl, saturationMarginMb, int));
- return VALUE_OR_RETURN(convertIntegral<uint32_t>(saturationMargin));
-}
-
-ConversionResult<Parameter> legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy) {
- int saturationMargin = VALUE_OR_RETURN(convertIntegral<int>(legacy));
- return MAKE_SPECIFIC_PARAMETER(AutomaticGainControl, automaticGainControl, saturationMarginMb,
- saturationMargin);
-}
-
-ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
- const Parameter& aidl) {
- int strength = VALUE_OR_RETURN(
- GET_PARAMETER_SPECIFIC_FIELD(aidl, BassBoost, bassBoost, strengthPm, int));
- return VALUE_OR_RETURN(convertIntegral<uint16_t>(strength));
-}
-
-ConversionResult<Parameter> legacy2aidl_uint16_strengthPm_Parameter_BassBoost(uint16_t legacy) {
- int strength = VALUE_OR_RETURN(convertIntegral<int>(legacy));
- return MAKE_SPECIFIC_PARAMETER(BassBoost, bassBoost, strengthPm, strength);
-}
-
-ConversionResult<int16_t> aidl2legacy_Parameter_Downmix_int16_type(const Parameter& aidl) {
- Downmix::Type aidlType = VALUE_OR_RETURN(
- GET_PARAMETER_SPECIFIC_FIELD(aidl, Downmix, downmix, type, Downmix::Type));
- return VALUE_OR_RETURN(convertIntegral<int16_t>(static_cast<uint32_t>(aidlType)));
-}
-
-ConversionResult<Parameter> legacy2aidl_int16_type_Parameter_Downmix(int16_t legacy) {
- if (legacy > (uint32_t) Downmix::Type::FOLD) {
- return unexpected(BAD_VALUE);
- }
- Downmix::Type aidlType = static_cast<Downmix::Type>(legacy);
- return MAKE_SPECIFIC_PARAMETER(Downmix, downmix, type, aidlType);
-}
-
} // namespace android
} // aidl
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
index 86f455e..c0024ef 100644
--- a/media/audioaidlconversion/Android.bp
+++ b/media/audioaidlconversion/Android.bp
@@ -135,11 +135,40 @@
],
defaults: [
"audio_aidl_conversion_common_default",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libbase",
+ ],
+ cflags: [
+ "-DBACKEND_NDK",
+ ],
+ min_sdk_version: "31", //AParcelableHolder has been introduced in 31
+}
+
+/**
+ * Only including AIDL effect HAL conversion.
+ */
+cc_library {
+ name: "libaudio_aidl_conversion_effect_ndk",
+ srcs: [
+ "AidlConversionEffect.cpp",
+ ],
+ header_libs: [
+ "libaudio_aidl_conversion_common_util_ndk",
+ ],
+ export_header_lib_headers: [
+ "libaudio_aidl_conversion_common_util_ndk",
+ ],
+ defaults: [
+ "audio_aidl_conversion_common_default",
"latest_android_hardware_audio_common_ndk_shared",
"latest_android_hardware_audio_effect_ndk_shared",
"latest_android_media_audio_common_types_ndk_shared",
],
shared_libs: [
+ "libaudio_aidl_conversion_common_ndk",
"libbinder_ndk",
"libbase",
],
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
index c25ddb1..c412238 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -49,6 +49,8 @@
#include PREFIX(android/media/audio/common/AudioMode.h)
#include PREFIX(android/media/audio/common/AudioOffloadInfo.h)
#include PREFIX(android/media/audio/common/AudioOutputFlags.h)
+#include PREFIX(android/media/audio/common/AudioPort.h)
+#include PREFIX(android/media/audio/common/AudioPortConfig.h)
#include PREFIX(android/media/audio/common/AudioPortExt.h)
#include PREFIX(android/media/audio/common/AudioPortMixExt.h)
#include PREFIX(android/media/audio/common/AudioPlaybackRate.h)
@@ -67,6 +69,7 @@
using ::android::String16;
using ::android::String8;
+using ::android::status_t;
#if defined(BACKEND_NDK)
namespace aidl {
@@ -76,7 +79,7 @@
// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
// the string.
-::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
+status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize);
ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl);
@@ -122,6 +125,12 @@
ConversionResult<media::audio::common::AudioChannelLayout>
legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
+enum class AudioPortDirection {
+ INPUT, OUTPUT
+};
+ConversionResult<AudioPortDirection> portDirection(audio_port_role_t role, audio_port_type_t type);
+ConversionResult<audio_port_role_t> portRole(AudioPortDirection direction, audio_port_type_t type);
+
ConversionResult<audio_config_t>
aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
ConversionResult<media::audio::common::AudioConfig>
@@ -172,13 +181,13 @@
ConversionResult<media::audio::common::AudioDeviceDescription>
legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
-::android::status_t aidl2legacy_AudioDevice_audio_device(
+status_t aidl2legacy_AudioDevice_audio_device(
const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
char* legacyAddress);
-::android::status_t aidl2legacy_AudioDevice_audio_device(
+status_t aidl2legacy_AudioDevice_audio_device(
const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
String8* legacyAddress);
-::android::status_t aidl2legacy_AudioDevice_audio_device(
+status_t aidl2legacy_AudioDevice_audio_device(
const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
std::string* legacyAddress);
@@ -265,6 +274,48 @@
ConversionResult<media::audio::common::AudioOutputFlags>
legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
+ConversionResult<audio_port_config_mix_ext_usecase>
+aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ const media::audio::common::AudioPortMixExtUseCase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioPortMixExtUseCase>
+legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ const audio_port_config_mix_ext_usecase& legacy, bool isInput);
+
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+ const media::audio::common::AudioPortDeviceExt& aidl);
+ConversionResult<media::audio::common::AudioPortDeviceExt>
+ legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+ const audio_port_config_device_ext& legacy);
+
+status_t aidl2legacy_AudioPortConfig_audio_port_config(
+ const media::audio::common::AudioPortConfig& aidl, bool isInput,
+ audio_port_config* legacy, int32_t* portId);
+ConversionResult<media::audio::common::AudioPortConfig>
+legacy2aidl_audio_port_config_AudioPortConfig(
+ const audio_port_config& legacy, bool isInput, int32_t portId);
+
+ConversionResult<audio_port_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+ const media::audio::common::AudioPortMixExt& aidl);
+ConversionResult<media::audio::common::AudioPortMixExt>
+legacy2aidl_audio_port_mix_ext_AudioPortMixExt(
+ const audio_port_mix_ext& legacy);
+
+ConversionResult<audio_port_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+ const media::audio::common::AudioPortDeviceExt& aidl);
+ConversionResult<media::audio::common::AudioPortDeviceExt>
+legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
+ const audio_port_device_ext& legacy);
+
+ConversionResult<audio_port_v7>
+aidl2legacy_AudioPort_audio_port_v7(
+ const media::audio::common::AudioPort& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioPort>
+legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy, bool isInput);
+
ConversionResult<audio_profile> aidl2legacy_AudioProfile_audio_profile(
const media::audio::common::AudioProfile& aidl, bool isInput);
ConversionResult<media::audio::common::AudioProfile> legacy2aidl_audio_profile_AudioProfile(
diff --git a/media/audioaidlconversion/include/media/AidlConversionEffect.h b/media/audioaidlconversion/include/media/AidlConversionEffect.h
new file mode 100644
index 0000000..83aa614
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionEffect.h
@@ -0,0 +1,130 @@
+/*
+ * 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 <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+/**
+ * Can only handle conversion between AIDL (NDK backend) and legacy type.
+ */
+#include <hardware/audio_effect.h>
+#include <media/AidlConversionUtil.h>
+#include <system/audio_effect.h>
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+
+namespace aidl {
+namespace android {
+
+template <typename P, typename T, typename P::Specific::Tag tag>
+ConversionResult<T> getParameterSpecific(const P& u) {
+ const auto& spec = VALUE_OR_RETURN(UNION_GET(u, specific));
+ return unionGetField<typename P::Specific, tag>(spec);
+}
+
+template <typename P, typename T, typename P::Specific::Tag tag, typename T::Tag field, typename F>
+ConversionResult<F> getParameterSpecificField(const P& u) {
+ const auto& spec =
+ VALUE_OR_RETURN((getParameterSpecific<std::decay_t<decltype(u)>, T, tag>(u)));
+ return VALUE_OR_RETURN((unionGetField<T, field>(spec)));
+}
+
+#define GET_PARAMETER_SPECIFIC_FIELD(u, specific, tag, field, fieldType) \
+ getParameterSpecificField<std::decay_t<decltype(u)>, specific, \
+ aidl::android::hardware::audio::effect::Parameter::Specific::tag, \
+ specific::field, fieldType>(u)
+
+#define MAKE_SPECIFIC_PARAMETER(spec, tag, field, value) \
+ UNION_MAKE(aidl::android::hardware::audio::effect::Parameter, specific, \
+ UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Specific, tag, \
+ UNION_MAKE(spec, field, value)))
+
+#define MAKE_SPECIFIC_PARAMETER_ID(spec, tag, field) \
+ UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Id, tag, \
+ UNION_MAKE(spec::Id, commonTag, field))
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Type_uint32(
+ ::aidl::android::hardware::audio::effect::Flags::Type type);
+ConversionResult<uint32_t> aidl2legacy_Flags_Insert_uint32(
+ ::aidl::android::hardware::audio::effect::Flags::Insert insert);
+ConversionResult<uint32_t> aidl2legacy_Flags_Volume_uint32(
+ ::aidl::android::hardware::audio::effect::Flags::Volume volume);
+ConversionResult<uint32_t> aidl2legacy_Flags_HardwareAccelerator_uint32(
+ ::aidl::android::hardware::audio::effect::Flags::HardwareAccelerator hwAcceleratorMode);
+ConversionResult<uint32_t> aidl2legacy_Flags_uint32(
+ const ::aidl::android::hardware::audio::effect::Flags aidl);
+
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Type>
+legacy2aidl_uint32_Flags_Type(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Insert>
+legacy2aidl_uint32_Flags_Insert(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Volume>
+legacy2aidl_uint32_Flags_Volume(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::HardwareAccelerator>
+legacy2aidl_uint32_Flags_HardwareAccelerator(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags> legacy2aidl_uint32_Flags(
+ uint32_t hal);
+
+ConversionResult<effect_descriptor_t> aidl2legacy_Descriptor_effect_descriptor(
+ const ::aidl::android::hardware::audio::effect::Descriptor& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Descriptor>
+legacy2aidl_effect_descriptor_Descriptor(const effect_descriptor_t& hal);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_echoDelay(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_echoDelay_Parameter_aec(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_mobileMode(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_mobileMode_Parameter_aec(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint16_strengthPm_Parameter_BassBoost(uint16_t legacy);
+
+ConversionResult<int16_t> aidl2legacy_Parameter_Downmix_int16_type(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_int16_type_Parameter_Downmix(int16_t legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::DynamicsProcessing::ResolutionPreference>
+legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(int32_t legacy);
+ConversionResult<int32_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+ ::aidl::android::hardware::audio::effect::DynamicsProcessing::ResolutionPreference aidl);
+
+} // namespace android
+} // namespace aidl
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdk.h b/media/audioaidlconversion/include/media/AidlConversionNdk.h
index d094dff..98a7d41 100644
--- a/media/audioaidlconversion/include/media/AidlConversionNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionNdk.h
@@ -26,105 +26,15 @@
#include <hardware/audio_effect.h>
#include <media/AidlConversionUtil.h>
#include <system/audio_effect.h>
-
-#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/media/audio/common/AudioConfig.h>
namespace aidl {
namespace android {
-template <typename P, typename T, typename P::Specific::Tag tag>
-ConversionResult<T> getParameterSpecific(const P& u) {
- const auto& spec = VALUE_OR_RETURN(UNION_GET(u, specific));
- return unionGetField<typename P::Specific, tag>(spec);
-}
-
-template <typename P, typename T, typename P::Specific::Tag tag, typename T::Tag field, typename F>
-ConversionResult<F> getParameterSpecificField(const P& u) {
- const auto& spec =
- VALUE_OR_RETURN((getParameterSpecific<std::decay_t<decltype(u)>, T, tag>(u)));
- return VALUE_OR_RETURN((unionGetField<T, field>(spec)));
-}
-
-#define GET_PARAMETER_SPECIFIC_FIELD(u, specific, tag, field, fieldType) \
- getParameterSpecificField<std::decay_t<decltype(u)>, specific, \
- aidl::android::hardware::audio::effect::Parameter::Specific::tag, \
- specific::field, fieldType>(u)
-
-#define MAKE_SPECIFIC_PARAMETER(spec, tag, field, value) \
- UNION_MAKE(aidl::android::hardware::audio::effect::Parameter, specific, \
- UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Specific, tag, \
- UNION_MAKE(spec, field, value)))
-
-#define MAKE_SPECIFIC_PARAMETER_ID(spec, tag, field) \
- UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Id, tag, \
- UNION_MAKE(spec::Id, commonTag, spec::field))
-
-ConversionResult<uint32_t> aidl2legacy_Flags_Type_uint32(
- ::aidl::android::hardware::audio::effect::Flags::Type type);
-ConversionResult<uint32_t> aidl2legacy_Flags_Insert_uint32(
- ::aidl::android::hardware::audio::effect::Flags::Insert insert);
-ConversionResult<uint32_t> aidl2legacy_Flags_Volume_uint32(
- ::aidl::android::hardware::audio::effect::Flags::Volume volume);
-ConversionResult<uint32_t> aidl2legacy_Flags_HardwareAccelerator_uint32(
- ::aidl::android::hardware::audio::effect::Flags::HardwareAccelerator hwAcceleratorMode);
-ConversionResult<uint32_t> aidl2legacy_Flags_uint32(
- const ::aidl::android::hardware::audio::effect::Flags aidl);
-
-ConversionResult<::aidl::android::hardware::audio::effect::Flags::Type>
-legacy2aidl_uint32_Flags_Type(uint32_t legacy);
-ConversionResult<::aidl::android::hardware::audio::effect::Flags::Insert>
-legacy2aidl_uint32_Flags_Insert(uint32_t legacy);
-ConversionResult<::aidl::android::hardware::audio::effect::Flags::Volume>
-legacy2aidl_uint32_Flags_Volume(uint32_t legacy);
-ConversionResult<::aidl::android::hardware::audio::effect::Flags::HardwareAccelerator>
-legacy2aidl_uint32_Flags_HardwareAccelerator(uint32_t legacy);
-ConversionResult<::aidl::android::hardware::audio::effect::Flags> legacy2aidl_uint32_Flags(
- uint32_t hal);
-
-ConversionResult<effect_descriptor_t> aidl2legacy_Descriptor_effect_descriptor(
- const ::aidl::android::hardware::audio::effect::Descriptor& aidl);
-ConversionResult<::aidl::android::hardware::audio::effect::Descriptor>
-legacy2aidl_effect_descriptor_Descriptor(const effect_descriptor_t& hal);
-
ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
const media::audio::common::AudioConfigBase& aidl, bool isInput);
ConversionResult<media::audio::common::AudioConfigBase> legacy2aidl_buffer_config_t_AudioConfigBase(
const buffer_config_t& legacy, bool isInput);
-ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_echoDelay(
- const ::aidl::android::hardware::audio::effect::Parameter& aidl);
-ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
-legacy2aidl_uint32_echoDelay_Parameter_aec(uint32_t legacy);
-
-ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_mobileMode(
- const ::aidl::android::hardware::audio::effect::Parameter& aidl);
-ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
-legacy2aidl_uint32_mobileMode_Parameter_aec(uint32_t legacy);
-
-ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
- const ::aidl::android::hardware::audio::effect::Parameter& aidl);
-ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
-legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy);
-
-ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
- const ::aidl::android::hardware::audio::effect::Parameter& aidl);
-ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
-legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy);
-
-ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
- const ::aidl::android::hardware::audio::effect::Parameter& aidl);
-ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
-legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy);
-
-ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
- const ::aidl::android::hardware::audio::effect::Parameter& aidl);
-ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
-legacy2aidl_uint16_strengthPm_Parameter_BassBoost(uint16_t legacy);
-
-ConversionResult<int16_t> aidl2legacy_Parameter_Downmix_int16_type(
- const ::aidl::android::hardware::audio::effect::Parameter& aidl);
-ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
-legacy2aidl_int16_type_Parameter_Downmix(int16_t legacy);
-
} // namespace android
} // namespace aidl
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index 96b81d7..0eb47f4 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -578,7 +578,8 @@
size_t srcVStride = img->stride[AOM_PLANE_V];
C2PlanarLayout layout = wView.layout();
size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
- size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+ size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+ size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
if (img->fmt == AOM_IMG_FMT_I42016) {
const uint16_t *srcY = (const uint16_t *)img->planes[AOM_PLANE_Y];
@@ -592,7 +593,7 @@
std::static_pointer_cast<const C2ColorAspectsStruct>(defaultColorAspects));
} else {
convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
- srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
mWidth, mHeight);
}
} else {
@@ -600,7 +601,7 @@
const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
- srcVStride, dstYStride, dstUVStride, mWidth, mHeight);
+ srcVStride, dstYStride, dstUStride, dstVStride, mWidth, mHeight);
}
finishWork(*(int64_t*)img->user_priv, work, std::move(block));
block = nullptr;
diff --git a/media/codec2/components/aom/C2SoftAomEnc.cpp b/media/codec2/components/aom/C2SoftAomEnc.cpp
index f5620a4..8b852a2 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.cpp
+++ b/media/codec2/components/aom/C2SoftAomEnc.cpp
@@ -22,6 +22,7 @@
#include <media/stagefright/foundation/MediaDefs.h>
#include <C2Debug.h>
+#include <Codec2Mapper.h>
#include <C2PlatformSupport.h>
#include <SimpleC2Interface.h>
@@ -390,6 +391,36 @@
codec_return = aom_codec_control(mCodecContext, AV1E_SET_MAX_REFERENCE_FRAMES, 3);
if (codec_return != AOM_CODEC_OK) goto BailOut;
+ ColorAspects sfAspects;
+ if (!C2Mapper::map(mColorAspects->primaries, &sfAspects.mPrimaries)) {
+ sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->range, &sfAspects.mRange)) {
+ sfAspects.mRange = android::ColorAspects::RangeUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->matrix, &sfAspects.mMatrixCoeffs)) {
+ sfAspects.mMatrixCoeffs = android::ColorAspects::MatrixUnspecified;
+ }
+ if (!C2Mapper::map(mColorAspects->transfer, &sfAspects.mTransfer)) {
+ sfAspects.mTransfer = android::ColorAspects::TransferUnspecified;
+ }
+ int32_t primaries, transfer, matrixCoeffs;
+ bool range;
+ ColorUtils::convertCodecColorAspectsToIsoAspects(sfAspects,
+ &primaries,
+ &transfer,
+ &matrixCoeffs,
+ &range);
+
+ codec_return = aom_codec_control(mCodecContext, AV1E_SET_COLOR_RANGE, range);
+ if (codec_return != AOM_CODEC_OK) goto BailOut;
+ codec_return = aom_codec_control(mCodecContext, AV1E_SET_COLOR_PRIMARIES, primaries);
+ if (codec_return != AOM_CODEC_OK) goto BailOut;
+ codec_return = aom_codec_control(mCodecContext, AV1E_SET_TRANSFER_CHARACTERISTICS, transfer);
+ if (codec_return != AOM_CODEC_OK) goto BailOut;
+ codec_return = aom_codec_control(mCodecContext, AV1E_SET_MATRIX_COEFFICIENTS, matrixCoeffs);
+ if (codec_return != AOM_CODEC_OK) goto BailOut;
+
BailOut:
return codec_return;
}
@@ -406,6 +437,7 @@
mFrameRate = mIntf->getFrameRate_l();
mIntraRefresh = mIntf->getIntraRefresh_l();
mRequestSync = mIntf->getRequestSync_l();
+ mColorAspects = mIntf->getCodedColorAspects_l();
}
diff --git a/media/codec2/components/aom/C2SoftAomEnc.h b/media/codec2/components/aom/C2SoftAomEnc.h
index 2d1bb07..3e42855 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.h
+++ b/media/codec2/components/aom/C2SoftAomEnc.h
@@ -104,6 +104,7 @@
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
+ std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
aom_codec_err_t setupCodecParameters();
};
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index d549c3b..32f8fa8 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -38,8 +38,8 @@
void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
size_t srcUStride, size_t srcVStride, size_t dstYStride,
- size_t dstUVStride, uint32_t width, uint32_t height,
- bool isMonochrome) {
+ size_t dstUStride, size_t dstVStride, uint32_t width,
+ uint32_t height, bool isMonochrome) {
for (size_t i = 0; i < height; ++i) {
memcpy(dstY, srcY, width);
srcY += srcYStride;
@@ -51,8 +51,8 @@
for (size_t i = 0; i < (height + 1) / 2; ++i) {
memset(dstV, kNeutralUVBitDepth8, (width + 1) / 2);
memset(dstU, kNeutralUVBitDepth8, (width + 1) / 2);
- dstV += dstUVStride;
- dstU += dstUVStride;
+ dstV += dstVStride;
+ dstU += dstUStride;
}
return;
}
@@ -60,13 +60,13 @@
for (size_t i = 0; i < (height + 1) / 2; ++i) {
memcpy(dstV, srcV, (width + 1) / 2);
srcV += srcVStride;
- dstV += dstUVStride;
+ dstV += dstVStride;
}
for (size_t i = 0; i < (height + 1) / 2; ++i) {
memcpy(dstU, srcU, (width + 1) / 2);
srcU += srcUStride;
- dstU += dstUVStride;
+ dstU += dstUStride;
}
}
diff --git a/media/codec2/components/base/include/SimpleC2Component.h b/media/codec2/components/base/include/SimpleC2Component.h
index 38b7825..051f798 100644
--- a/media/codec2/components/base/include/SimpleC2Component.h
+++ b/media/codec2/components/base/include/SimpleC2Component.h
@@ -33,8 +33,8 @@
void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
size_t srcUStride, size_t srcVStride, size_t dstYStride,
- size_t dstUVStride, uint32_t width, uint32_t height,
- bool isMonochrome = false);
+ size_t dstUStride, size_t dstVStride, uint32_t width,
+ uint32_t height, bool isMonochrome = false);
void convertYUV420Planar16ToY410OrRGBA1010102(
uint32_t *dst, const uint16_t *srcY,
diff --git a/media/codec2/components/gav1/Android.bp b/media/codec2/components/gav1/Android.bp
index 162339f..9781b6d 100644
--- a/media/codec2/components/gav1/Android.bp
+++ b/media/codec2/components/gav1/Android.bp
@@ -21,7 +21,10 @@
],
srcs: ["C2SoftGav1Dec.cpp"],
- static_libs: ["libgav1"],
+ static_libs: [
+ "libgav1",
+ "libyuv_static",
+ ],
apex_available: [
"//apex_available:platform",
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index d234f21..8aed623 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -24,6 +24,7 @@
#include <Codec2CommonUtils.h>
#include <Codec2Mapper.h>
#include <SimpleC2Interface.h>
+#include <libyuv.h>
#include <log/log.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/MediaDefs.h>
@@ -725,6 +726,24 @@
}
}
+void C2SoftGav1Dec::setError(const std::unique_ptr<C2Work> &work, c2_status_t error) {
+ mSignalledError = true;
+ work->result = error;
+ work->workletsProcessed = 1u;
+}
+
+bool C2SoftGav1Dec::allocTmpFrameBuffer(size_t size) {
+ if (size > mTmpFrameBufferSize) {
+ mTmpFrameBuffer = std::make_unique<uint16_t[]>(size);
+ if (mTmpFrameBuffer == nullptr) {
+ mTmpFrameBufferSize = 0;
+ return false;
+ }
+ mTmpFrameBufferSize = size;
+ }
+ return true;
+}
+
bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work) {
if (!(work && pool)) return false;
@@ -771,14 +790,6 @@
getHDRStaticParams(buffer, work);
getHDR10PlusInfoData(buffer, work);
- if (!(buffer->image_format == libgav1::kImageFormatYuv420 ||
- buffer->image_format == libgav1::kImageFormatMonochrome400)) {
- ALOGE("image_format %d not supported", buffer->image_format);
- mSignalledError = true;
- work->workletsProcessed = 1u;
- work->result = C2_CORRUPTED;
- return false;
- }
const bool isMonochrome =
buffer->image_format == libgav1::kImageFormatMonochrome400;
@@ -851,40 +862,112 @@
uint8_t *dstY = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
uint8_t *dstU = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_U]);
uint8_t *dstV = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_V]);
- size_t srcYStride = buffer->stride[0];
- size_t srcUStride = buffer->stride[1];
- size_t srcVStride = buffer->stride[2];
C2PlanarLayout layout = wView.layout();
size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
- size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+ size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+ size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
if (buffer->bitdepth == 10) {
const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
const uint16_t *srcU = (const uint16_t *)buffer->plane[1];
const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
+ size_t srcYStride = buffer->stride[0] / 2;
+ size_t srcUStride = buffer->stride[1] / 2;
+ size_t srcVStride = buffer->stride[2] / 2;
if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
convertYUV420Planar16ToY410OrRGBA1010102(
- (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2,
- srcUStride / 2, srcVStride / 2,
+ (uint32_t *)dstY, srcY, srcU, srcV, srcYStride,
+ srcUStride, srcVStride,
dstYStride / sizeof(uint32_t), mWidth, mHeight,
std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
} else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
- convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
- srcYStride / 2, srcUStride / 2, srcVStride / 2, dstYStride / 2,
- dstUVStride / 2, mWidth, mHeight, isMonochrome);
+ dstYStride /= 2;
+ dstUStride /= 2;
+ dstVStride /= 2;
+ if (buffer->image_format == libgav1::kImageFormatYuv444 ||
+ buffer->image_format == libgav1::kImageFormatYuv422) {
+ // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010 and
+ // libyuv::I210ToP010 when they are available.
+ // Note it may be safe to alias dstY in I010ToP010, but the libyuv API doesn't make any
+ // guarantees.
+ const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
+ if (!allocTmpFrameBuffer(tmpSize)) {
+ ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+ setError(work, C2_NO_MEMORY);
+ return false;
+ }
+ uint16_t *const tmpY = mTmpFrameBuffer.get();
+ uint16_t *const tmpU = tmpY + dstYStride * mHeight;
+ uint16_t *const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
+ if (buffer->image_format == libgav1::kImageFormatYuv444) {
+ libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+ tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
+ mWidth, mHeight);
+ } else {
+ libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+ tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
+ mWidth, mHeight);
+ }
+ libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
+ (uint16_t*)dstY, dstYStride, (uint16_t*)dstU, dstUStride,
+ mWidth, mHeight);
+ } else {
+ convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
+ srcYStride, srcUStride, srcVStride, dstYStride,
+ dstUStride, mWidth, mHeight, isMonochrome);
+ }
} else {
- convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
- srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride, mWidth,
- mHeight, isMonochrome);
+ if (buffer->image_format == libgav1::kImageFormatYuv444) {
+ // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420 when
+ // it's available.
+ const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
+ if (!allocTmpFrameBuffer(tmpSize)) {
+ ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+ setError(work, C2_NO_MEMORY);
+ return false;
+ }
+ uint16_t *const tmpY = mTmpFrameBuffer.get();
+ uint16_t *const tmpU = tmpY + dstYStride * mHeight;
+ uint16_t *const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
+ libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+ tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
+ mWidth, mHeight);
+ libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
+ dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
+ mWidth, mHeight);
+ } else if (buffer->image_format == libgav1::kImageFormatYuv422) {
+ libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+ dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
+ mWidth, mHeight);
+ } else {
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
+ mWidth, mHeight, isMonochrome);
+ }
}
} else {
const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
- convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
- srcVStride, dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
+ size_t srcYStride = buffer->stride[0];
+ size_t srcUStride = buffer->stride[1];
+ size_t srcVStride = buffer->stride[2];
+
+ if (buffer->image_format == libgav1::kImageFormatYuv444) {
+ libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+ dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
+ mWidth, mHeight);
+ } else if (buffer->image_format == libgav1::kImageFormatYuv422) {
+ libyuv::I422ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+ dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
+ mWidth, mHeight);
+ } else {
+ convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUStride, dstVStride, mWidth, mHeight,
+ isMonochrome);
+ }
}
finishWork(buffer->user_private_data, work, std::move(block));
block = nullptr;
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index f0e14d7..c3b27ea 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -19,6 +19,8 @@
#include <inttypes.h>
+#include <memory>
+
#include <media/stagefright/foundation/ColorUtils.h>
#include <SimpleC2Component.h>
@@ -60,6 +62,9 @@
uint32_t mHeight;
bool mSignalledOutputEos;
bool mSignalledError;
+ // Used during 10-bit I444/I422 to 10-bit P010 & 8-bit I420 conversions.
+ std::unique_ptr<uint16_t[]> mTmpFrameBuffer;
+ size_t mTmpFrameBufferSize = 0;
C2StreamHdrStaticMetadataInfo::output mHdrStaticMetadataInfo;
std::unique_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfo = nullptr;
@@ -97,6 +102,9 @@
void destroyDecoder();
void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
const std::shared_ptr<C2GraphicBlock>& block);
+ // Sets |work->result| and mSignalledError. Returns false.
+ void setError(const std::unique_ptr<C2Work> &work, c2_status_t error);
+ bool allocTmpFrameBuffer(size_t size);
bool outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
const std::unique_ptr<C2Work>& work);
c2_status_t drainInternal(uint32_t drainMode,
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 3bf9c48..2137964 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -603,7 +603,8 @@
C2PlanarLayout layout = wView.layout();
size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
- size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+ size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+ size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
size_t srcYStride = align(mWidth, 16);
size_t srcUStride = srcYStride / 2;
size_t srcVStride = srcYStride / 2;
@@ -613,8 +614,8 @@
const uint8_t *srcV = (const uint8_t *)srcY + vStride * srcYStride * 5 / 4;
convertYUV420Planar8ToYV12(outputBufferY, outputBufferU, outputBufferV, srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride, dstYStride, dstUVStride,
- mWidth, mHeight);
+ srcYStride, srcUStride, srcVStride, dstYStride, dstUStride,
+ dstVStride, mWidth, mHeight);
inPos += inSize - (size_t)tmpInSize;
finishWork(workIndex, work);
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 18cd1bf..dab7b89 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -766,7 +766,8 @@
size_t srcVStride = img->stride[VPX_PLANE_V];
C2PlanarLayout layout = wView.layout();
size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
- size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+ size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+ size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
if (img->fmt == VPX_IMG_FMT_I42016) {
const uint16_t *srcY = (const uint16_t *)img->planes[VPX_PLANE_Y];
@@ -804,10 +805,10 @@
} else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
srcYStride / 2, srcUStride / 2, srcVStride / 2,
- dstYStride / 2, dstUVStride / 2, mWidth, mHeight);
+ dstYStride / 2, dstUStride / 2, mWidth, mHeight);
} else {
convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
- srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
mWidth, mHeight);
}
} else {
@@ -816,7 +817,7 @@
const uint8_t *srcV = (const uint8_t *)img->planes[VPX_PLANE_V];
convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
- srcVStride, dstYStride, dstUVStride, mWidth, mHeight);
+ srcVStride, dstYStride, dstVStride, dstVStride, mWidth, mHeight);
}
finishWork(((c2_cntr64_t *)img->user_priv)->peekull(), work, std::move(block));
return OK;
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 4c1d749..13e430a 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -1724,7 +1724,7 @@
* There may be sample rate conversions in the Audio framework.
* The sample rate set in the stream builder may not be actual sample rate used in the hardware.
*
- * This returns the sample rate used by the hardware.
+ * This returns the sample rate used by the hardware in Hertz.
*
* If AAudioStreamBuilder_openStream() returned AAUDIO_OK, the result should always be valid.
*
@@ -1797,9 +1797,16 @@
* The data format set in the stream builder may not be actual format used in the hardware.
*
* This returns the audio format used by the hardware.
+ *
+ * If AAudioStreamBuilder_openStream() returned AAUDIO_OK, this should always return an
+ * aaudio_format_t.
+ *
* AUDIO_FORMAT_PCM_8_24_BIT is currently not supported in AAudio, but the hardware may use it.
* If AUDIO_FORMAT_PCM_8_24_BIT is used by the hardware, return AAUDIO_FORMAT_PCM_I24_PACKED.
*
+ * If any other format used by the hardware is not supported by AAudio, this will return
+ * AAUDIO_FORMAT_INVALID.
+ *
* Available since API level 34.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index f65ff18..b3c8643 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -66,125 +66,6 @@
using media::audio::common::Int;
using media::audio::common::PcmType;
-namespace {
-
-enum class Direction {
- INPUT, OUTPUT
-};
-
-ConversionResult<Direction> direction(media::AudioPortRole role, media::AudioPortType type) {
- switch (type) {
- case media::AudioPortType::NONE:
- case media::AudioPortType::SESSION:
- break; // must be listed -Werror,-Wswitch
- case media::AudioPortType::DEVICE:
- switch (role) {
- case media::AudioPortRole::NONE:
- break; // must be listed -Werror,-Wswitch
- case media::AudioPortRole::SOURCE:
- return Direction::INPUT;
- case media::AudioPortRole::SINK:
- return Direction::OUTPUT;
- }
- break;
- case media::AudioPortType::MIX:
- switch (role) {
- case media::AudioPortRole::NONE:
- break; // must be listed -Werror,-Wswitch
- case media::AudioPortRole::SOURCE:
- return Direction::OUTPUT;
- case media::AudioPortRole::SINK:
- return Direction::INPUT;
- }
- break;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<Direction> direction(audio_port_role_t role, audio_port_type_t type) {
- switch (type) {
- case AUDIO_PORT_TYPE_NONE:
- case AUDIO_PORT_TYPE_SESSION:
- break; // must be listed -Werror,-Wswitch
- case AUDIO_PORT_TYPE_DEVICE:
- switch (role) {
- case AUDIO_PORT_ROLE_NONE:
- break; // must be listed -Werror,-Wswitch
- case AUDIO_PORT_ROLE_SOURCE:
- return Direction::INPUT;
- case AUDIO_PORT_ROLE_SINK:
- return Direction::OUTPUT;
- }
- break;
- case AUDIO_PORT_TYPE_MIX:
- switch (role) {
- case AUDIO_PORT_ROLE_NONE:
- break; // must be listed -Werror,-Wswitch
- case AUDIO_PORT_ROLE_SOURCE:
- return Direction::OUTPUT;
- case AUDIO_PORT_ROLE_SINK:
- return Direction::INPUT;
- }
- break;
- }
- return unexpected(BAD_VALUE);
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Converters
-
-ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
- media::AudioIoConfigEvent aidl) {
- switch (aidl) {
- case media::AudioIoConfigEvent::OUTPUT_REGISTERED:
- return AUDIO_OUTPUT_REGISTERED;
- case media::AudioIoConfigEvent::OUTPUT_OPENED:
- return AUDIO_OUTPUT_OPENED;
- case media::AudioIoConfigEvent::OUTPUT_CLOSED:
- return AUDIO_OUTPUT_CLOSED;
- case media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED:
- return AUDIO_OUTPUT_CONFIG_CHANGED;
- case media::AudioIoConfigEvent::INPUT_REGISTERED:
- return AUDIO_INPUT_REGISTERED;
- case media::AudioIoConfigEvent::INPUT_OPENED:
- return AUDIO_INPUT_OPENED;
- case media::AudioIoConfigEvent::INPUT_CLOSED:
- return AUDIO_INPUT_CLOSED;
- case media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED:
- return AUDIO_INPUT_CONFIG_CHANGED;
- case media::AudioIoConfigEvent::CLIENT_STARTED:
- return AUDIO_CLIENT_STARTED;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
- audio_io_config_event_t legacy) {
- switch (legacy) {
- case AUDIO_OUTPUT_REGISTERED:
- return media::AudioIoConfigEvent::OUTPUT_REGISTERED;
- case AUDIO_OUTPUT_OPENED:
- return media::AudioIoConfigEvent::OUTPUT_OPENED;
- case AUDIO_OUTPUT_CLOSED:
- return media::AudioIoConfigEvent::OUTPUT_CLOSED;
- case AUDIO_OUTPUT_CONFIG_CHANGED:
- return media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED;
- case AUDIO_INPUT_REGISTERED:
- return media::AudioIoConfigEvent::INPUT_REGISTERED;
- case AUDIO_INPUT_OPENED:
- return media::AudioIoConfigEvent::INPUT_OPENED;
- case AUDIO_INPUT_CLOSED:
- return media::AudioIoConfigEvent::INPUT_CLOSED;
- case AUDIO_INPUT_CONFIG_CHANGED:
- return media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED;
- case AUDIO_CLIENT_STARTED:
- return media::AudioIoConfigEvent::CLIENT_STARTED;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<audio_port_role_t> aidl2legacy_AudioPortRole_audio_port_role_t(
media::AudioPortRole aidl) {
switch (aidl) {
@@ -241,52 +122,97 @@
return unexpected(BAD_VALUE);
}
-// This type is unnamed in the original definition, thus we name it here.
-using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
+ConversionResult<AudioPortDirection> portDirection(
+ media::AudioPortRole role, media::AudioPortType type) {
+ audio_port_role_t legacyRole = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortRole_audio_port_role_t(role));
+ audio_port_type_t legacyType = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortType_audio_port_type_t(type));
+ return portDirection(legacyRole, legacyType);
+}
+ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
+ media::AudioIoConfigEvent aidl) {
+ switch (aidl) {
+ case media::AudioIoConfigEvent::OUTPUT_REGISTERED:
+ return AUDIO_OUTPUT_REGISTERED;
+ case media::AudioIoConfigEvent::OUTPUT_OPENED:
+ return AUDIO_OUTPUT_OPENED;
+ case media::AudioIoConfigEvent::OUTPUT_CLOSED:
+ return AUDIO_OUTPUT_CLOSED;
+ case media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED:
+ return AUDIO_OUTPUT_CONFIG_CHANGED;
+ case media::AudioIoConfigEvent::INPUT_REGISTERED:
+ return AUDIO_INPUT_REGISTERED;
+ case media::AudioIoConfigEvent::INPUT_OPENED:
+ return AUDIO_INPUT_OPENED;
+ case media::AudioIoConfigEvent::INPUT_CLOSED:
+ return AUDIO_INPUT_CLOSED;
+ case media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED:
+ return AUDIO_INPUT_CONFIG_CHANGED;
+ case media::AudioIoConfigEvent::CLIENT_STARTED:
+ return AUDIO_CLIENT_STARTED;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
+ audio_io_config_event_t legacy) {
+ switch (legacy) {
+ case AUDIO_OUTPUT_REGISTERED:
+ return media::AudioIoConfigEvent::OUTPUT_REGISTERED;
+ case AUDIO_OUTPUT_OPENED:
+ return media::AudioIoConfigEvent::OUTPUT_OPENED;
+ case AUDIO_OUTPUT_CLOSED:
+ return media::AudioIoConfigEvent::OUTPUT_CLOSED;
+ case AUDIO_OUTPUT_CONFIG_CHANGED:
+ return media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED;
+ case AUDIO_INPUT_REGISTERED:
+ return media::AudioIoConfigEvent::INPUT_REGISTERED;
+ case AUDIO_INPUT_OPENED:
+ return media::AudioIoConfigEvent::INPUT_OPENED;
+ case AUDIO_INPUT_CLOSED:
+ return media::AudioIoConfigEvent::INPUT_CLOSED;
+ case AUDIO_INPUT_CONFIG_CHANGED:
+ return media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED;
+ case AUDIO_CLIENT_STARTED:
+ return media::AudioIoConfigEvent::CLIENT_STARTED;
+ }
+ return unexpected(BAD_VALUE);
+}
ConversionResult<audio_port_config_mix_ext_usecase> aidl2legacy_AudioPortMixExtUseCase(
const AudioPortMixExtUseCase& aidl, media::AudioPortRole role) {
- audio_port_config_mix_ext_usecase legacy;
-
switch (role) {
- case media::AudioPortRole::NONE:
+ case media::AudioPortRole::NONE: {
+ audio_port_config_mix_ext_usecase legacy;
// Just verify that the union is empty.
VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
return legacy;
-
+ }
case media::AudioPortRole::SOURCE:
- // This is not a bug. A SOURCE role corresponds to the stream field.
- legacy.stream = VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
- VALUE_OR_RETURN(UNION_GET(aidl, stream))));
- return legacy;
-
+ return aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ aidl, false /*isInput*/);
case media::AudioPortRole::SINK:
- // This is not a bug. A SINK role corresponds to the source field.
- legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
- VALUE_OR_RETURN(UNION_GET(aidl, source))));
- return legacy;
+ return aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+ aidl, true /*isInput*/);
}
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
ConversionResult<AudioPortMixExtUseCase> legacy2aidl_AudioPortMixExtUseCase(
const audio_port_config_mix_ext_usecase& legacy, audio_port_role_t role) {
- AudioPortMixExtUseCase aidl;
-
switch (role) {
- case AUDIO_PORT_ROLE_NONE:
+ case AUDIO_PORT_ROLE_NONE: {
+ AudioPortMixExtUseCase aidl;
UNION_SET(aidl, unspecified, false);
return aidl;
+ }
case AUDIO_PORT_ROLE_SOURCE:
- // This is not a bug. A SOURCE role corresponds to the stream field.
- UNION_SET(aidl, stream, VALUE_OR_RETURN(
- legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream)));
- return aidl;
+ return legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ legacy, false /*isInput*/);
case AUDIO_PORT_ROLE_SINK:
- // This is not a bug. A SINK role corresponds to the source field.
- UNION_SET(aidl, source,
- VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source)));
- return aidl;
+ return legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+ legacy, true /*isInput*/);
}
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
@@ -294,6 +220,8 @@
ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
const AudioPortMixExt& aidl, media::AudioPortRole role,
const media::AudioPortMixExtSys& aidlMixExt) {
+ // Not using HAL-level 'aidl2legacy_AudioPortMixExt' as it does not support
+ // 'media::AudioPortRole::NONE'.
audio_port_config_mix_ext legacy;
legacy.hw_module = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_module_handle_t(aidlMixExt.hwModule));
@@ -305,6 +233,8 @@
status_t legacy2aidl_AudioPortMixExt(
const audio_port_config_mix_ext& legacy, audio_port_role_t role,
AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
+ // Not using HAL-level 'legacy2aidl_AudioPortMixExt' as it does not support
+ // 'AUDIO_PORT_ROLE_NONE'.
aidlMixExt->hwModule = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
aidl->handle = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
@@ -329,21 +259,20 @@
ConversionResult<audio_port_config_device_ext>
aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
- audio_port_config_device_ext legacy;
+ audio_port_config_device_ext legacy = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(aidl));
legacy.hw_module = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
- RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
- aidl.device, &legacy.type, legacy.address));
return legacy;
}
status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
const audio_port_config_device_ext& legacy,
AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+ *aidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(legacy));
aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
- aidl->device = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
return OK;
}
@@ -353,6 +282,8 @@
ConversionResult<audio_port_config_ext> aidl2legacy_AudioPortExt_audio_port_config_ext(
const AudioPortExt& aidl, media::AudioPortType type,
media::AudioPortRole role, const media::AudioPortExtSys& aidlSys) {
+ // Not using HAL-level 'aidl2legacy_AudioPortExt_audio_port_config_ext' as it does not support
+ // 'media::AudioPortType::SESSION'.
audio_port_config_ext legacy;
switch (type) {
case media::AudioPortType::NONE:
@@ -384,6 +315,8 @@
status_t legacy2aidl_AudioPortExt(
const audio_port_config_ext& legacy, audio_port_type_t type, audio_port_role_t role,
AudioPortExt* aidl, media::AudioPortExtSys* aidlSys) {
+ // Not using HAL-level 'aidl2legacy_AudioPortExt_audio_port_config_ext' as it does not support
+ // 'AUDIO_PORT_TYPE_SESSION'.
switch (type) {
case AUDIO_PORT_TYPE_NONE:
UNION_SET(*aidl, unspecified, false);
@@ -417,40 +350,16 @@
}
ConversionResult<audio_port_config> aidl2legacy_AudioPortConfigFw_audio_port_config(
- const media::AudioPortConfigFw& aidl) {
- audio_port_config legacy{};
- legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.hal.id));
+ const media::AudioPortConfigFw& aidl, int32_t* aidlPortId) {
+ const bool isInput = VALUE_OR_RETURN(
+ portDirection(aidl.sys.role, aidl.sys.type)) == AudioPortDirection::INPUT;
+ audio_port_config legacy;
+ int32_t aidlPortIdHolder;
+ RETURN_IF_ERROR(aidl2legacy_AudioPortConfig_audio_port_config(
+ aidl.hal, isInput, &legacy, &aidlPortIdHolder));
+ if (aidlPortId != nullptr) *aidlPortId = aidlPortIdHolder;
legacy.role = VALUE_OR_RETURN(aidl2legacy_AudioPortRole_audio_port_role_t(aidl.sys.role));
legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioPortType_audio_port_type_t(aidl.sys.type));
- const bool isInput =
- VALUE_OR_RETURN(direction(aidl.sys.role, aidl.sys.type)) == Direction::INPUT;
- if (aidl.hal.sampleRate.has_value()) {
- legacy.sample_rate = VALUE_OR_RETURN(
- convertIntegral<unsigned int>(aidl.hal.sampleRate.value().value));
- legacy.config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
- }
- if (aidl.hal.channelMask.has_value()) {
- legacy.channel_mask =
- VALUE_OR_RETURN(
- aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
- aidl.hal.channelMask.value(), isInput));
- legacy.config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
- }
- if (aidl.hal.format.has_value()) {
- legacy.format = VALUE_OR_RETURN(
- aidl2legacy_AudioFormatDescription_audio_format_t(aidl.hal.format.value()));
- legacy.config_mask |= AUDIO_PORT_CONFIG_FORMAT;
- }
- if (aidl.hal.gain.has_value()) {
- legacy.gain = VALUE_OR_RETURN(aidl2legacy_AudioGainConfig_audio_gain_config(
- aidl.hal.gain.value(), isInput));
- legacy.config_mask |= AUDIO_PORT_CONFIG_GAIN;
- }
- if (aidl.hal.flags.has_value()) {
- legacy.flags = VALUE_OR_RETURN(
- aidl2legacy_AudioIoFlags_audio_io_flags(aidl.hal.flags.value(), isInput));
- legacy.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
- }
legacy.ext = VALUE_OR_RETURN(
aidl2legacy_AudioPortExt_audio_port_config_ext(
aidl.hal.ext, aidl.sys.type, aidl.sys.role, aidl.sys.ext));
@@ -458,34 +367,14 @@
}
ConversionResult<media::AudioPortConfigFw> legacy2aidl_audio_port_config_AudioPortConfigFw(
- const audio_port_config& legacy) {
+ const audio_port_config& legacy, int32_t portId) {
+ const bool isInput = VALUE_OR_RETURN(
+ portDirection(legacy.role, legacy.type)) == AudioPortDirection::INPUT;
media::AudioPortConfigFw aidl;
- aidl.hal.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ aidl.hal = VALUE_OR_RETURN(
+ legacy2aidl_audio_port_config_AudioPortConfig(legacy, isInput, portId));
aidl.sys.role = VALUE_OR_RETURN(legacy2aidl_audio_port_role_t_AudioPortRole(legacy.role));
aidl.sys.type = VALUE_OR_RETURN(legacy2aidl_audio_port_type_t_AudioPortType(legacy.type));
- const bool isInput = VALUE_OR_RETURN(
- direction(legacy.role, legacy.type)) == Direction::INPUT;
- if (legacy.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
- Int aidl_sampleRate;
- aidl_sampleRate.value = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
- aidl.hal.sampleRate = aidl_sampleRate;
- }
- if (legacy.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
- aidl.hal.channelMask = VALUE_OR_RETURN(
- legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
- }
- if (legacy.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
- aidl.hal.format = VALUE_OR_RETURN(
- legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
- }
- if (legacy.config_mask & AUDIO_PORT_CONFIG_GAIN) {
- aidl.hal.gain = VALUE_OR_RETURN(
- legacy2aidl_audio_gain_config_AudioGainConfig(legacy.gain, isInput));
- }
- if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
- aidl.hal.flags = VALUE_OR_RETURN(
- legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, isInput));
- }
RETURN_IF_ERROR(legacy2aidl_AudioPortExt(legacy.ext, legacy.type, legacy.role,
&aidl.hal.ext, &aidl.sys.ext));
return aidl;
@@ -801,18 +690,18 @@
ConversionResult<audio_port_mix_ext>
aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
const AudioPortMixExt& aidl, const media::AudioPortMixExtSys& aidlSys) {
- audio_port_mix_ext legacy{};
+ audio_port_mix_ext legacy = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortMixExt_audio_port_mix_ext(aidl));
legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
- legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
return legacy;
}
status_t
legacy2aidl_audio_port_mix_ext_AudioPortMixExt(const audio_port_mix_ext& legacy,
AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
+ *aidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_mix_ext_AudioPortMixExt(legacy));
aidlMixExt->hwModule = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
- aidl->handle = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
return OK;
}
@@ -831,11 +720,10 @@
ConversionResult<audio_port_device_ext>
aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
- audio_port_device_ext legacy;
+ audio_port_device_ext legacy = VALUE_OR_RETURN(
+ aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(aidl));
legacy.hw_module = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
- RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
- aidl.device, &legacy.type, legacy.address));
legacy.encapsulation_modes = VALUE_OR_RETURN(
aidl2legacy_AudioEncapsulationMode_mask(aidlSys.encapsulationModes));
legacy.encapsulation_metadata_types = VALUE_OR_RETURN(
@@ -847,10 +735,9 @@
status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
const audio_port_device_ext& legacy,
AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+ *aidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(legacy));
aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
- aidl->device = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
aidlDeviceExt->encapsulationModes = VALUE_OR_RETURN_STATUS(
legacy2aidl_AudioEncapsulationMode_mask(legacy.encapsulation_modes));
aidlDeviceExt->encapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
@@ -931,42 +818,11 @@
ConversionResult<audio_port_v7>
aidl2legacy_AudioPortFw_audio_port_v7(const media::AudioPortFw& aidl) {
- audio_port_v7 legacy;
- legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.hal.id));
+ const bool isInput = VALUE_OR_RETURN(
+ portDirection(aidl.sys.role, aidl.sys.type)) == AudioPortDirection::INPUT;
+ audio_port_v7 legacy = VALUE_OR_RETURN(aidl2legacy_AudioPort_audio_port_v7(aidl.hal, isInput));
legacy.role = VALUE_OR_RETURN(aidl2legacy_AudioPortRole_audio_port_role_t(aidl.sys.role));
legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioPortType_audio_port_type_t(aidl.sys.type));
- RETURN_IF_ERROR(aidl2legacy_string(aidl.hal.name, legacy.name, sizeof(legacy.name)));
-
- if (aidl.hal.profiles.size() > std::size(legacy.audio_profiles)) {
- return unexpected(BAD_VALUE);
- }
- const bool isInput =
- VALUE_OR_RETURN(direction(aidl.sys.role, aidl.sys.type)) == Direction::INPUT;
- RETURN_IF_ERROR(convertRange(
- aidl.hal.profiles.begin(), aidl.hal.profiles.end(), legacy.audio_profiles,
- [isInput](const AudioProfile& p) {
- return aidl2legacy_AudioProfile_audio_profile(p, isInput);
- }));
- legacy.num_audio_profiles = aidl.hal.profiles.size();
-
- if (aidl.hal.extraAudioDescriptors.size() > std::size(legacy.extra_audio_descriptors)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(
- aidl.hal.extraAudioDescriptors.begin(), aidl.hal.extraAudioDescriptors.end(),
- legacy.extra_audio_descriptors,
- aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor));
- legacy.num_extra_audio_descriptors = aidl.hal.extraAudioDescriptors.size();
-
- if (aidl.hal.gains.size() > std::size(legacy.gains)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(convertRange(aidl.hal.gains.begin(), aidl.hal.gains.end(), legacy.gains,
- [isInput](const AudioGain& g) {
- return aidl2legacy_AudioGain_audio_gain(g, isInput);
- }));
- legacy.num_gains = aidl.hal.gains.size();
legacy.active_config = VALUE_OR_RETURN(
aidl2legacy_AudioPortConfigFw_audio_port_config(aidl.sys.activeConfig));
@@ -977,46 +833,17 @@
ConversionResult<media::AudioPortFw>
legacy2aidl_audio_port_v7_AudioPortFw(const audio_port_v7& legacy) {
+ const bool isInput = VALUE_OR_RETURN(
+ portDirection(legacy.role, legacy.type)) == AudioPortDirection::INPUT;
media::AudioPortFw aidl;
- aidl.hal.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ aidl.hal = VALUE_OR_RETURN(legacy2aidl_audio_port_v7_AudioPort(legacy, isInput));
aidl.sys.role = VALUE_OR_RETURN(legacy2aidl_audio_port_role_t_AudioPortRole(legacy.role));
aidl.sys.type = VALUE_OR_RETURN(legacy2aidl_audio_port_type_t_AudioPortType(legacy.type));
- aidl.hal.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
-
- if (legacy.num_audio_profiles > std::size(legacy.audio_profiles)) {
- return unexpected(BAD_VALUE);
- }
- const bool isInput = VALUE_OR_RETURN(direction(legacy.role, legacy.type)) == Direction::INPUT;
- RETURN_IF_ERROR(
- convertRange(legacy.audio_profiles, legacy.audio_profiles + legacy.num_audio_profiles,
- std::back_inserter(aidl.hal.profiles),
- [isInput](const audio_profile& p) {
- return legacy2aidl_audio_profile_AudioProfile(p, isInput);
- }));
-
- if (legacy.num_extra_audio_descriptors > std::size(legacy.extra_audio_descriptors)) {
- return unexpected(BAD_VALUE);
- }
+ // These get filled by the call to 'legacy2aidl_AudioPortExt' below.
aidl.sys.profiles.resize(legacy.num_audio_profiles);
- RETURN_IF_ERROR(
- convertRange(legacy.extra_audio_descriptors,
- legacy.extra_audio_descriptors + legacy.num_extra_audio_descriptors,
- std::back_inserter(aidl.hal.extraAudioDescriptors),
- legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor));
-
- if (legacy.num_gains > std::size(legacy.gains)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(legacy.gains, legacy.gains + legacy.num_gains,
- std::back_inserter(aidl.hal.gains),
- [isInput](const audio_gain& g) {
- return legacy2aidl_audio_gain_AudioGain(g, isInput);
- }));
aidl.sys.gains.resize(legacy.num_gains);
-
aidl.sys.activeConfig = VALUE_OR_RETURN(
- legacy2aidl_audio_port_config_AudioPortConfigFw(legacy.active_config));
+ legacy2aidl_audio_port_config_AudioPortConfigFw(legacy.active_config, legacy.id));
aidl.sys.activeConfig.hal.portId = aidl.hal.id;
RETURN_IF_ERROR(
legacy2aidl_AudioPortExt(legacy.ext, legacy.type, &aidl.hal.ext, &aidl.sys.ext));
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 6bb0cbe..1b9936f 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -203,9 +203,10 @@
return false;
}
-bool AudioMix::hasMatchUserIdRule() const {
+bool AudioMix::hasUserIdRule(bool match) const {
+ const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID;
for (size_t i = 0; i < mCriteria.size(); i++) {
- if (mCriteria[i].mRule == RULE_MATCH_USERID) {
+ if (mCriteria[i].mRule == rule) {
return true;
}
}
@@ -214,7 +215,7 @@
bool AudioMix::isDeviceAffinityCompatible() const {
return ((mMixType == MIX_TYPE_PLAYERS)
- && (mRouteFlags == MIX_ROUTE_FLAG_RENDER));
+ && ((mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER));
}
} // namespace android
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 9a88f76..f0e58ae 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -88,10 +88,11 @@
ConversionResult<int32_t> legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
const audio_port_config_session_ext& legacy);
+// portId needs to be set when dealing with the HAL.
ConversionResult<audio_port_config> aidl2legacy_AudioPortConfigFw_audio_port_config(
- const media::AudioPortConfigFw& aidl);
+ const media::AudioPortConfigFw& aidl, int32_t* aidlPortId = nullptr);
ConversionResult<media::AudioPortConfigFw> legacy2aidl_audio_port_config_AudioPortConfigFw(
- const audio_port_config& legacy);
+ const audio_port_config& legacy, int32_t portId = 0);
ConversionResult<struct audio_patch> aidl2legacy_AudioPatchFw_audio_patch(
const media::AudioPatchFw& aidl);
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 61f2069..3fd438e 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -61,7 +61,10 @@
#define MIX_ROUTE_FLAG_LOOP_BACK (0x1 << 1)
/** Loop back some audio while it is rendered */
#define MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK)
-#define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK)
+/** Control if audio routing disallows preferred device routing **/
+#define MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE (0x1 << 2)
+#define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK | \
+ MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE)
#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20
@@ -112,9 +115,9 @@
void setMatchUserId(int userId);
/** returns true if this mix has a rule to match or exclude the given userId */
bool hasUserIdRule(bool match, int userId) const;
- /** returns true if this mix has a rule for userId match (any userId) */
- bool hasMatchUserIdRule() const;
- /** returns true if this mix can be used for uid-device affinity routing */
+ /** returns true if this mix has a rule to match or exclude (any userId) */
+ bool hasUserIdRule(bool match) const;
+ /** returns true if this mix has a rule for userId exclude (any userId) */
bool isDeviceAffinityCompatible() const;
std::vector<AudioMixMatchCriterion> mCriteria;
@@ -147,6 +150,11 @@
== MIX_ROUTE_FLAG_LOOP_BACK;
}
+static inline bool is_mix_disallows_preferred_device(uint32_t routeFlags) {
+ return (routeFlags & MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE)
+ == MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE;
+}
+
}; // namespace android
#endif // ANDROID_AUDIO_POLICY_H
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 75d576e..5cd17e1 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <iostream>
+
#include <gtest/gtest.h>
#include <media/AidlConversion.h>
@@ -22,19 +24,52 @@
using namespace android;
using namespace android::aidl_utils;
-using android::media::AudioDirectMode;
+using media::AudioDirectMode;
+using media::AudioPortConfigFw;
+using media::AudioPortDeviceExtSys;
+using media::AudioPortFw;
+using media::AudioPortRole;
+using media::AudioPortType;
using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioDevice;
using media::audio::common::AudioDeviceDescription;
using media::audio::common::AudioDeviceType;
using media::audio::common::AudioEncapsulationMetadataType;
using media::audio::common::AudioEncapsulationType;
using media::audio::common::AudioFormatDescription;
using media::audio::common::AudioFormatType;
+using media::audio::common::AudioGain;
+using media::audio::common::AudioGainConfig;
using media::audio::common::AudioGainMode;
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioProfile;
using media::audio::common::AudioStandard;
using media::audio::common::ExtraAudioDescriptor;
+using media::audio::common::Int;
using media::audio::common::PcmType;
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace android::media {
+#define DEFINE_PRINTING_TEMPLATES() \
+ template <typename P> \
+ std::enable_if_t<std::is_base_of_v<::android::Parcelable, P>, std::ostream&> operator<<( \
+ std::ostream& os, const P& p) { \
+ return os << p.toString(); \
+ } \
+ template <typename E> \
+ std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) { \
+ return os << toString(e); \
+ }
+DEFINE_PRINTING_TEMPLATES();
+
+namespace audio::common {
+DEFINE_PRINTING_TEMPLATES();
+} // namespace audio::common
+#undef DEFINE_PRINTING_TEMPLATES
+} // namespace android::media
+
namespace {
template <typename T>
@@ -367,6 +402,134 @@
testing::Values(make_AFD_Invalid(), AudioFormatDescription{},
make_AFD_Pcm16Bit()));
+AudioPortConfigFw createAudioPortConfigFw(const AudioChannelLayout& layout,
+ const AudioFormatDescription& format,
+ const AudioDeviceDescription& device) {
+ const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+ AudioPortConfigFw result;
+ result.hal.id = 43;
+ result.hal.portId = 42;
+ Int sr44100;
+ sr44100.value = 44100;
+ result.hal.sampleRate = sr44100;
+ result.hal.channelMask = layout;
+ result.hal.format = format;
+ AudioGainConfig gain;
+ gain.mode = 1 << static_cast<int>(AudioGainMode::JOINT);
+ gain.values = std::vector<int32_t>({100});
+ result.hal.gain = gain;
+ AudioPortDeviceExt ext;
+ AudioDevice audioDevice;
+ audioDevice.type = device;
+ ext.device = audioDevice;
+ result.hal.ext = ext;
+ result.sys.role = isInput ? AudioPortRole::SOURCE : AudioPortRole::SINK;
+ result.sys.type = AudioPortType::DEVICE;
+ AudioPortDeviceExtSys sysDevice;
+ sysDevice.hwModule = 1;
+ result.sys.ext = sysDevice;
+ return result;
+}
+
+using AudioPortConfigParam =
+ std::tuple<AudioChannelLayout, AudioFormatDescription, AudioDeviceDescription>;
+class AudioPortConfigRoundTripTest : public testing::TestWithParam<AudioPortConfigParam> {};
+TEST_P(AudioPortConfigRoundTripTest, Aidl2Legacy2Aidl) {
+ const AudioChannelLayout layout = std::get<0>(GetParam());
+ const AudioFormatDescription format = std::get<1>(GetParam());
+ const AudioDeviceDescription device = std::get<2>(GetParam());
+ const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+ AudioPortConfigFw initial = createAudioPortConfigFw(layout, format, device);
+ {
+ audio_port_config conv{};
+ int32_t portId = -1;
+ status_t status =
+ aidl2legacy_AudioPortConfig_audio_port_config(initial.hal, isInput, &conv, &portId);
+ ASSERT_EQ(OK, status);
+ EXPECT_NE(-1, portId);
+ auto convBack = legacy2aidl_audio_port_config_AudioPortConfig(conv, isInput, portId);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial.hal, convBack.value());
+ }
+ {
+ int32_t portId = -1;
+ auto conv = aidl2legacy_AudioPortConfigFw_audio_port_config(initial, &portId);
+ ASSERT_TRUE(conv.ok());
+ EXPECT_NE(-1, portId);
+ auto convBack = legacy2aidl_audio_port_config_AudioPortConfigFw(conv.value(), portId);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+ }
+}
+INSTANTIATE_TEST_SUITE_P(
+ AudioPortConfig, AudioPortConfigRoundTripTest,
+ testing::Combine(testing::Values(make_ACL_Stereo(), make_ACL_ChannelIndex2()),
+ testing::Values(make_AFD_Pcm16Bit()),
+ testing::Values(make_ADD_DefaultIn(), make_ADD_DefaultOut(),
+ make_ADD_WiredHeadset())));
+
+class AudioPortFwRoundTripTest : public testing::TestWithParam<AudioDeviceDescription> {
+ public:
+ AudioProfile createProfile(const AudioFormatDescription& format,
+ const std::vector<AudioChannelLayout>& channelMasks,
+ const std::vector<int32_t>& sampleRates) {
+ AudioProfile profile;
+ profile.format = format;
+ profile.channelMasks = channelMasks;
+ profile.sampleRates = sampleRates;
+ return profile;
+ }
+};
+TEST_P(AudioPortFwRoundTripTest, Aidl2Legacy2Aidl) {
+ const AudioDeviceDescription device = GetParam();
+ const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+ AudioPortFw initial;
+ initial.hal.id = 42;
+ initial.hal.profiles.push_back(createProfile(
+ make_AFD_Pcm16Bit(), {make_ACL_Stereo(), make_ACL_ChannelIndex2()}, {44100, 48000}));
+ if (isInput) {
+ initial.hal.flags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
+ } else {
+ initial.hal.flags = AudioIoFlags::make<AudioIoFlags::Tag::output>(0);
+ }
+ AudioGain initialGain;
+ initialGain.mode = 1 << static_cast<int>(AudioGainMode::JOINT);
+ initialGain.channelMask = make_ACL_Stereo();
+ initial.hal.gains.push_back(initialGain);
+ AudioPortDeviceExt initialExt;
+ AudioDevice initialDevice;
+ initialDevice.type = device;
+ initialExt.device = initialDevice;
+ initial.hal.ext = initialExt;
+ {
+ auto conv = aidl2legacy_AudioPort_audio_port_v7(initial.hal, isInput);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_port_v7_AudioPort(conv.value(), isInput);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial.hal, convBack.value());
+ }
+ initial.sys.role = isInput ? AudioPortRole::SOURCE : AudioPortRole::SINK;
+ initial.sys.type = AudioPortType::DEVICE;
+ initial.sys.profiles.resize(initial.hal.profiles.size());
+ initial.sys.gains.resize(initial.hal.gains.size());
+ initial.sys.activeConfig =
+ createAudioPortConfigFw(make_ACL_Stereo(), make_AFD_Pcm16Bit(), device);
+ initial.sys.activeConfig.hal.flags = initial.hal.flags;
+ AudioPortDeviceExtSys initialSysDevice;
+ initialSysDevice.hwModule = 1;
+ initial.sys.ext = initialSysDevice;
+ {
+ auto conv = aidl2legacy_AudioPortFw_audio_port_v7(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_port_v7_AudioPortFw(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+ }
+}
+INSTANTIATE_TEST_SUITE_P(AudioPortFw, AudioPortFwRoundTripTest,
+ testing::Values(make_ADD_DefaultIn(), make_ADD_DefaultOut(),
+ make_ADD_WiredHeadset()));
+
class AudioDirectModeRoundTripTest : public testing::TestWithParam<AudioDirectMode> {};
TEST_P(AudioDirectModeRoundTripTest, Aidl2Legacy2Aidl) {
const auto initial = GetParam();
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index b6602ec..fd2f126 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -257,6 +257,11 @@
"EffectConversionHelperAidl.cpp",
"EffectBufferHalAidl.cpp",
"EffectHalAidl.cpp",
+ "effectsAidlConversion/AidlConversionAec.cpp",
+ "effectsAidlConversion/AidlConversionAgc2.cpp",
+ "effectsAidlConversion/AidlConversionBassBoost.cpp",
+ "effectsAidlConversion/AidlConversionDownmix.cpp",
+ "effectsAidlConversion/AidlConversionDynamicsProcessing.cpp",
"EffectsFactoryHalAidl.cpp",
"EffectsFactoryHalEntry.cpp",
"StreamHalAidl.cpp",
@@ -268,6 +273,7 @@
shared_libs: [
"libbinder_ndk",
"libaudio_aidl_conversion_common_ndk",
+ "libaudio_aidl_conversion_effect_ndk",
],
header_libs: [
"libaudio_aidl_conversion_common_util_ndk",
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 280306d..1445e49 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -17,6 +17,9 @@
#define LOG_TAG "DeviceHalAidl"
// #define LOG_NDEBUG 0
+#include <algorithm>
+#include <forward_list>
+
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
@@ -28,8 +31,19 @@
#include "StreamHalAidl.h"
using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::media::audio::common::AudioConfig;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioMode;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::Float;
+using aidl::android::hardware::audio::common::RecordTrackMetadata;
+using aidl::android::hardware::audio::core::AudioPatch;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::ITelephony;
using aidl::android::hardware::audio::core::StreamDescriptor;
@@ -37,14 +51,55 @@
namespace android {
+namespace {
+
+bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
+ return portConfig.sampleRate.value().value == config.base.sampleRate &&
+ portConfig.channelMask.value() == config.base.channelMask &&
+ portConfig.format.value() == config.base.format;
+}
+
+void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
+ config->base.sampleRate = portConfig.sampleRate.value().value;
+ config->base.channelMask = portConfig.channelMask.value();
+ config->base.format = portConfig.format.value();
+}
+
+void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
+ portConfig->sampleRate = Int{ .value = config.base.sampleRate };
+ portConfig->channelMask = config.base.channelMask;
+ portConfig->format = config.base.format;
+}
+
+} // namespace
+
status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
// Obsolete.
return INVALID_OPERATION;
}
status_t DeviceHalAidl::initCheck() {
+ TIME_CHECK();
if (mModule == nullptr) return NO_INIT;
- // HAL modules are already initialized by the time they are published to the SM.
+ std::vector<AudioPort> ports;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
+ ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
+ __func__, mInstance.c_str());
+ std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
+ [](const auto& p) { return std::make_pair(p.id, p); });
+ std::vector<AudioPortConfig> portConfigs;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
+ std::transform(portConfigs.begin(), portConfigs.end(),
+ std::inserter(mPortConfigs, mPortConfigs.end()),
+ [](const auto& p) { return std::make_pair(p.id, p); });
+ std::vector<AudioPatch> patches;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
+ std::transform(patches.begin(), patches.end(),
+ std::inserter(mPatches, mPatches.end()),
+ [](const auto& p) { return std::make_pair(p.id, p); });
return OK;
}
@@ -135,47 +190,152 @@
return OK;
}
+namespace {
+
+class Cleanup {
+ public:
+ typedef void (DeviceHalAidl::*Cleaner)(int32_t);
+
+ Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
+ mDevice(device), mCleaner(cleaner), mId(id) {}
+ ~Cleanup() { clean(); }
+ void clean() {
+ if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
+ disarm();
+ }
+ void disarm() { mDevice = nullptr; }
+
+ private:
+ DeviceHalAidl* mDevice;
+ const Cleaner mCleaner;
+ const int32_t mId;
+};
+
+} // namespace
+
+// Since the order of container elements destruction is unspecified,
+// ensure that cleanups are performed from the most recent one and upwards.
+// This is the same as if there were individual Cleanup instances on the stack,
+// however the bonus is that we can disarm all of them with just one statement.
+class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
+ public:
+ ~Cleanups() { for (auto& c : *this) c.clean(); }
+ void disarmAll() { for (auto& c : *this) c.disarm(); }
+};
+
+status_t DeviceHalAidl::prepareToOpenStream(
+ int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
+ struct audio_config* config,
+ Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig) {
+ const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
+ // Find / create AudioPortConfigs for the device port and the mix port,
+ // then find / create a patch between them, and open a stream on the mix port.
+ AudioPortConfig devicePortConfig;
+ bool created = false;
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
+ if (created) {
+ cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
+ }
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle,
+ mixPortConfig, &created));
+ if (created) {
+ cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
+ }
+ setConfigFromPortConfig(aidlConfig, *mixPortConfig);
+ AudioPatch patch;
+ if (isInput) {
+ RETURN_STATUS_IF_ERROR(findOrCreatePatch(
+ {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
+ } else {
+ RETURN_STATUS_IF_ERROR(findOrCreatePatch(
+ {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
+ }
+ if (created) {
+ cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
+ }
+ if (aidlConfig->frameCount <= 0) {
+ aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
+ }
+ *config = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
+ return OK;
+}
+
status_t DeviceHalAidl::openOutputStream(
- audio_io_handle_t handle __unused, audio_devices_t devices __unused,
- audio_output_flags_t flags __unused, struct audio_config* config,
- const char* address __unused,
+ audio_io_handle_t handle, audio_devices_t devices,
+ audio_output_flags_t flags, struct audio_config* config,
+ const char* address,
sp<StreamOutHalInterface>* outStream) {
if (!outStream || !config) {
return BAD_VALUE;
}
TIME_CHECK();
if (!mModule) return NO_INIT;
- config->sample_rate = 48000;
- config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
- config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
- StreamDescriptor descriptor;
- descriptor.frameSizeBytes = audio_bytes_per_sample(config->format) *
- audio_channel_count_from_out_mask(config->channel_mask);
- descriptor.bufferSizeFrames = 600;
- *outStream = sp<StreamOutHalAidl>::make(descriptor, nullptr);
+ int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
+ AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
+ AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
+ int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
+ AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
+ AudioPortConfig mixPortConfig;
+ Cleanups cleanups;
+ RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
+ &cleanups, &aidlConfig, &mixPortConfig));
+ ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
+ args.portConfigId = mixPortConfig.id;
+ args.offloadInfo = aidlConfig.offloadInfo;
+ args.bufferSizeFrames = aidlConfig.frameCount;
+ ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
+ *outStream = sp<StreamOutHalAidl>::make(*config, std::move(ret.desc), std::move(ret.stream));
+ cleanups.disarmAll();
return OK;
}
status_t DeviceHalAidl::openInputStream(
- audio_io_handle_t handle __unused, audio_devices_t devices __unused,
- struct audio_config* config, audio_input_flags_t flags __unused,
- const char* address __unused, audio_source_t source __unused,
- audio_devices_t outputDevice __unused,
- const char* outputDeviceAddress __unused,
+ audio_io_handle_t handle, audio_devices_t devices,
+ struct audio_config* config, audio_input_flags_t flags,
+ const char* address, audio_source_t source,
+ audio_devices_t outputDevice, const char* outputDeviceAddress,
sp<StreamInHalInterface>* inStream) {
if (!inStream || !config) {
return BAD_VALUE;
}
TIME_CHECK();
if (!mModule) return NO_INIT;
- config->sample_rate = 48000;
- config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
- config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
- StreamDescriptor descriptor;
- descriptor.frameSizeBytes = audio_bytes_per_sample(config->format) *
- audio_channel_count_from_out_mask(config->channel_mask);
- descriptor.bufferSizeFrames = 600;
- *inStream = sp<StreamInHalAidl>::make(descriptor, nullptr);
+ int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
+ AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
+ AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
+ int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
+ AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
+ AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
+ AudioPortConfig mixPortConfig;
+ Cleanups cleanups;
+ RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
+ &cleanups, &aidlConfig, &mixPortConfig));
+ ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
+ args.portConfigId = mixPortConfig.id;
+ RecordTrackMetadata aidlTrackMetadata{
+ .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
+ if (outputDevice != AUDIO_DEVICE_NONE) {
+ aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_device_AudioDevice(
+ outputDevice, outputDeviceAddress));
+ }
+ args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
+ args.bufferSizeFrames = aidlConfig.frameCount;
+ ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
+ *inStream = sp<StreamInHalAidl>::make(*config, std::move(ret.desc), std::move(ret.stream));
+ cleanups.disarmAll();
return OK;
}
@@ -184,21 +344,104 @@
return OK;
}
-status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources __unused,
- const struct audio_port_config* sources __unused,
- unsigned int num_sinks __unused,
- const struct audio_port_config* sinks __unused,
- audio_patch_handle_t* patch __unused) {
+status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
+ const struct audio_port_config* sources,
+ unsigned int num_sinks,
+ const struct audio_port_config* sinks,
+ audio_patch_handle_t* patch) {
TIME_CHECK();
if (!mModule) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
+ sources == nullptr || sinks == nullptr || patch == nullptr) {
+ return BAD_VALUE;
+ }
+ // Note that the patch handle (*patch) is provided by the framework.
+ // In tests it's possible that its value is AUDIO_PATCH_HANDLE_NONE.
+
+ // Upon conversion, mix port configs contain audio configuration, while
+ // device port configs contain device address. This data is used to find
+ // or create HAL configs.
+ std::vector<AudioPortConfig> aidlSources, aidlSinks;
+ for (unsigned int i = 0; i < num_sources; ++i) {
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+ sources[i].role, sources[i].type)) ==
+ ::aidl::android::AudioPortDirection::INPUT;
+ aidlSources.push_back(VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+ sources[i], isInput, 0)));
+ }
+ for (unsigned int i = 0; i < num_sinks; ++i) {
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+ sinks[i].role, sinks[i].type)) ==
+ ::aidl::android::AudioPortDirection::INPUT;
+ aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+ sinks[i], isInput, 0)));
+ }
+ Cleanups cleanups;
+ auto existingPatchIt = mPatches.end();
+ auto fwkHandlesIt = *patch != AUDIO_PATCH_HANDLE_NONE ?
+ mFwkHandles.find(*patch) : mFwkHandles.end();
+ AudioPatch aidlPatch;
+ if (fwkHandlesIt != mFwkHandles.end()) {
+ existingPatchIt = mPatches.find(fwkHandlesIt->second);
+ if (existingPatchIt != mPatches.end()) {
+ aidlPatch = existingPatchIt->second;
+ aidlPatch.sourcePortConfigIds.clear();
+ aidlPatch.sinkPortConfigIds.clear();
+ }
+ }
+ auto fillPortConfigs = [&](
+ const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
+ for (const auto& s : configs) {
+ AudioPortConfig portConfig;
+ bool created = false;
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
+ if (created) {
+ cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
+ }
+ ids->push_back(portConfig.id);
+ }
+ return OK;
+ };
+ RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
+ RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
+ if (existingPatchIt != mPatches.end()) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mModule->setAudioPatch(aidlPatch, &aidlPatch)));
+ existingPatchIt->second = aidlPatch;
+ } else {
+ bool created = false;
+ RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
+ // Since no cleanup of the patch is needed, 'created' is ignored.
+ if (fwkHandlesIt != mFwkHandles.end()) {
+ fwkHandlesIt->second = aidlPatch.id;
+ // Patch handle (*patch) stays the same.
+ } else {
+ if (*patch == AUDIO_PATCH_HANDLE_NONE) {
+ // This isn't good as the module can't provide a handle which is really unique.
+ // However, this situation should only happen in tests.
+ *patch = aidlPatch.id;
+ LOG_ALWAYS_FATAL_IF(mFwkHandles.count(*patch) > 0,
+ "%s: patch id %d clashes with another framework patch handle",
+ __func__, *patch);
+ }
+ mFwkHandles.emplace(*patch, aidlPatch.id);
+ }
+ }
+ cleanups.disarmAll();
return OK;
}
-status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch __unused) {
+status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
TIME_CHECK();
if (!mModule) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ auto idMapIt = mFwkHandles.find(patch);
+ if (idMapIt == mFwkHandles.end()) {
+ return BAD_VALUE;
+ }
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(idMapIt->second)));
+ mFwkHandles.erase(idMapIt);
return OK;
}
@@ -308,4 +551,253 @@
return OK;
}
+status_t DeviceHalAidl::createPortConfig(const AudioPortConfig& requestedPortConfig,
+ AudioPortConfig* appliedPortConfig) {
+ TIME_CHECK();
+ bool applied = false;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
+ requestedPortConfig, appliedPortConfig, &applied)));
+ if (!applied) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
+ *appliedPortConfig, appliedPortConfig, &applied)));
+ if (!applied) {
+ ALOGE("%s: module %s did not apply suggested config %s",
+ __func__, mInstance.c_str(), appliedPortConfig->toString().c_str());
+ return NO_INIT;
+ }
+ }
+ mPortConfigs.emplace(appliedPortConfig->id, *appliedPortConfig);
+ return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePatch(
+ const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
+ std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
+ requestedPatch.sourcePortConfigIds.end());
+ std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
+ requestedPatch.sinkPortConfigIds.end());
+ return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
+}
+
+status_t DeviceHalAidl::findOrCreatePatch(
+ const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
+ AudioPatch* patch, bool* created) {
+ auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
+ if (patchIt == mPatches.end()) {
+ TIME_CHECK();
+ AudioPatch requestedPatch, appliedPatch;
+ requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
+ sourcePortConfigIds.begin(), sourcePortConfigIds.end());
+ requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
+ sinkPortConfigIds.begin(), sinkPortConfigIds.end());
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
+ requestedPatch, &appliedPatch)));
+ patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
+ *created = true;
+ } else {
+ *created = false;
+ }
+ *patch = patchIt->second;
+ return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
+ AudioPortConfig* portConfig, bool* created) {
+ auto portConfigIt = findPortConfig(device);
+ if (portConfigIt == mPortConfigs.end()) {
+ auto portsIt = findPort(device);
+ if (portsIt == mPorts.end()) {
+ ALOGE("%s: device port for device %s is not found in the module %s",
+ __func__, device.toString().c_str(), mInstance.c_str());
+ return BAD_VALUE;
+ }
+ AudioPortConfig requestedPortConfig;
+ requestedPortConfig.portId = portsIt->first;
+ AudioPortConfig appliedPortConfig;
+ RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
+ portConfigIt = mPortConfigs.insert(
+ mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
+ *created = true;
+ } else {
+ *created = false;
+ }
+ *portConfig = portConfigIt->second;
+ return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(
+ const AudioConfig& config, const AudioIoFlags& flags, int32_t ioHandle,
+ AudioPortConfig* portConfig, bool* created) {
+ auto portConfigIt = findPortConfig(config, flags, ioHandle);
+ if (portConfigIt == mPortConfigs.end()) {
+ auto portsIt = findPort(config, flags);
+ if (portsIt == mPorts.end()) {
+ ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
+ __func__, config.toString().c_str(), flags.toString().c_str(),
+ mInstance.c_str());
+ return BAD_VALUE;
+ }
+ AudioPortConfig requestedPortConfig;
+ requestedPortConfig.portId = portsIt->first;
+ setPortConfigFromConfig(&requestedPortConfig, config);
+ AudioPortConfig appliedPortConfig;
+ RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
+ appliedPortConfig.ext.get<AudioPortExt::Tag::mix>().handle = ioHandle;
+ portConfigIt = mPortConfigs.insert(
+ mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
+ *created = true;
+ } else {
+ *created = false;
+ }
+ *portConfig = portConfigIt->second;
+ return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(
+ const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
+ using Tag = AudioPortExt::Tag;
+ if (requestedPortConfig.ext.getTag() == Tag::mix) {
+ if (const auto& p = requestedPortConfig;
+ !p.sampleRate.has_value() || !p.channelMask.has_value() ||
+ !p.format.has_value() || !p.flags.has_value()) {
+ ALOGW("%s: provided mix port config is not fully specified: %s",
+ __func__, p.toString().c_str());
+ return BAD_VALUE;
+ }
+ AudioConfig config;
+ setConfigFromPortConfig(&config, requestedPortConfig);
+ return findOrCreatePortConfig(config, requestedPortConfig.flags.value(),
+ requestedPortConfig.ext.get<Tag::mix>().handle, portConfig, created);
+ } else if (requestedPortConfig.ext.getTag() == Tag::device) {
+ return findOrCreatePortConfig(
+ requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
+ }
+ ALOGW("%s: unsupported audio port config: %s",
+ __func__, requestedPortConfig.toString().c_str());
+ return BAD_VALUE;
+}
+
+DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
+ const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
+ return std::find_if(mPatches.begin(), mPatches.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ std::set<int32_t> patchSrcs(
+ p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
+ std::set<int32_t> patchSinks(
+ p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
+ return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
+}
+
+DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
+ using Tag = AudioPortExt::Tag;
+ return std::find_if(mPorts.begin(), mPorts.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ return p.ext.getTag() == Tag::device &&
+ p.ext.template get<Tag::device>().device == device; });
+}
+
+DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
+ const AudioConfig& config, const AudioIoFlags& flags) {
+ using Tag = AudioPortExt::Tag;
+ return std::find_if(mPorts.begin(), mPorts.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ return p.ext.getTag() == Tag::mix &&
+ p.flags == flags &&
+ std::find_if(p.profiles.begin(), p.profiles.end(),
+ [&](const auto& prof) {
+ return prof.format == config.base.format &&
+ std::find(prof.channelMasks.begin(),
+ prof.channelMasks.end(),
+ config.base.channelMask) !=
+ prof.channelMasks.end() &&
+ std::find(prof.sampleRates.begin(),
+ prof.sampleRates.end(),
+ config.base.sampleRate) !=
+ prof.sampleRates.end();
+ }) != p.profiles.end(); });
+}
+
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
+ using Tag = AudioPortExt::Tag;
+ return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ return p.ext.getTag() == Tag::device &&
+ p.ext.template get<Tag::device>().device == device; });
+}
+
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
+ const AudioConfig& config, const AudioIoFlags& flags, int32_t ioHandle) {
+ using Tag = AudioPortExt::Tag;
+ return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
+ !p.sampleRate.has_value() || !p.channelMask.has_value() ||
+ !p.format.has_value() || !p.flags.has_value(),
+ "%s: stored mix port config is not fully specified: %s",
+ __func__, p.toString().c_str());
+ return p.ext.getTag() == Tag::mix &&
+ isConfigEqualToPortConfig(config, p) &&
+ p.flags.value() == flags &&
+ p.ext.template get<Tag::mix>().handle == ioHandle; });
+}
+/*
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
+ const AudioPortConfig& portConfig) {
+ using Tag = AudioPortExt::Tag;
+ if (portConfig.ext.getTag() == Tag::mix) {
+ return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+ [&](const auto& pair) {
+ const auto& p = pair.second;
+ LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
+ !p.sampleRate.has_value() || !p.channelMask.has_value() ||
+ !p.format.has_value() || !p.flags.has_value(),
+ "%s: stored mix port config is not fully specified: %s",
+ __func__, p.toString().c_str());
+ return p.ext.getTag() == Tag::mix &&
+ (!portConfig.sampleRate.has_value() ||
+ p.sampleRate == portConfig.sampleRate) &&
+ (!portConfig.channelMask.has_value() ||
+ p.channelMask == portConfig.channelMask) &&
+ (!portConfig.format.has_value() || p.format == portConfig.format) &&
+ (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
+ p.ext.template get<Tag::mix>().handle ==
+ portConfig.ext.template get<Tag::mix>().handle; });
+ } else if (portConfig.ext.getTag() == Tag::device) {
+ return findPortConfig(portConfig.ext.get<Tag::device>().device);
+ }
+ return mPortConfigs.end();
+}
+*/
+void DeviceHalAidl::resetPatch(int32_t patchId) {
+ if (auto it = mPatches.find(patchId); it != mPatches.end()) {
+ mPatches.erase(it);
+ TIME_CHECK();
+ if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
+ ALOGE("%s: error while resetting patch %d: %s",
+ __func__, patchId, status.getDescription().c_str());
+ }
+ return;
+ }
+ ALOGE("%s: patch id %d not found", __func__, patchId);
+}
+
+void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
+ if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
+ mPortConfigs.erase(it);
+ TIME_CHECK();
+ if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
+ !status.isOk()) {
+ ALOGE("%s: error while resetting port config %d: %s",
+ __func__, portConfigId, status.getDescription().c_str());
+ }
+ return;
+ }
+ ALOGE("%s: port config id %d not found", __func__, portConfigId);
+}
+
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index b1aa351..0662cf2 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -16,8 +16,12 @@
#pragma once
-#include <aidl/android/hardware/audio/core/sounddose/BpSoundDose.h>
+#include <map>
+#include <set>
+#include <vector>
+
#include <aidl/android/hardware/audio/core/BpModule.h>
+#include <aidl/android/hardware/audio/core/sounddose/BpSoundDose.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
@@ -123,17 +127,77 @@
private:
friend class sp<DeviceHalAidl>;
+ using Patches = std::map<int32_t /*patch ID*/,
+ ::aidl::android::hardware::audio::core::AudioPatch>;
+ using PortConfigs = std::map<int32_t /*port config ID*/,
+ ::aidl::android::media::audio::common::AudioPortConfig>;
+ using Ports = std::map<int32_t /*port ID*/, ::aidl::android::media::audio::common::AudioPort>;
+ class Cleanups;
+ // Must not be constructed directly by clients.
+ DeviceHalAidl(
+ const std::string& instance,
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module)
+ : ConversionHelperAidl("DeviceHalAidl"), mInstance(instance), mModule(module) {}
+
+ ~DeviceHalAidl() override = default;
+
+ status_t createPortConfig(
+ const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+ ::aidl::android::media::audio::common::AudioPortConfig* appliedPortConfig);
+ status_t findOrCreatePatch(
+ const std::set<int32_t>& sourcePortConfigIds,
+ const std::set<int32_t>& sinkPortConfigIds,
+ ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
+ status_t findOrCreatePatch(
+ const ::aidl::android::hardware::audio::core::AudioPatch& requestedPatch,
+ ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
+ status_t findOrCreatePortConfig(
+ const ::aidl::android::media::audio::common::AudioDevice& device,
+ ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
+ bool* created);
+ status_t findOrCreatePortConfig(
+ const ::aidl::android::media::audio::common::AudioConfig& config,
+ const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+ int32_t ioHandle,
+ ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
+ status_t findOrCreatePortConfig(
+ const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+ ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
+ Patches::iterator findPatch(const std::set<int32_t>& sourcePortConfigIds,
+ const std::set<int32_t>& sinkPortConfigIds);
+ Ports::iterator findPort(const ::aidl::android::media::audio::common::AudioDevice& device);
+ Ports::iterator findPort(
+ const ::aidl::android::media::audio::common::AudioConfig& config,
+ const ::aidl::android::media::audio::common::AudioIoFlags& flags);
+ PortConfigs::iterator findPortConfig(
+ const ::aidl::android::media::audio::common::AudioDevice& device);
+ PortConfigs::iterator findPortConfig(
+ const ::aidl::android::media::audio::common::AudioConfig& config,
+ const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+ int32_t ioHandle);
+ // Currently unused but may be useful for implementing setAudioPortConfig
+ // PortConfigs::iterator findPortConfig(
+ // const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
+ status_t prepareToOpenStream(
+ int32_t aidlHandle,
+ const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
+ const ::aidl::android::media::audio::common::AudioIoFlags& aidlFlags,
+ struct audio_config* config,
+ Cleanups* cleanups,
+ ::aidl::android::media::audio::common::AudioConfig* aidlConfig,
+ ::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig);
+ void resetPatch(int32_t patchId);
+ void resetPortConfig(int32_t portConfigId);
+
+ const std::string mInstance;
const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>
mSoundDose = nullptr;
-
- // Can not be constructed directly by clients.
- explicit DeviceHalAidl(
- const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module)
- : ConversionHelperAidl("DeviceHalAidl"), mModule(module) {}
-
- ~DeviceHalAidl() override = default;
+ Ports mPorts;
+ PortConfigs mPortConfigs;
+ Patches mPatches;
+ std::map<audio_patch_handle_t, int32_t /* patch ID */> mFwkHandles;
};
} // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index 78d03e7..b452fa3 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -57,7 +57,7 @@
}
// If the service is a nullptr, the device will not be really functional,
// but will not crash either.
- *device = sp<DeviceHalAidl>::make(service);
+ *device = sp<DeviceHalAidl>::make(name, service);
return OK;
}
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index ec8abd7..da89e20 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -21,21 +21,8 @@
//#define LOG_NDEBUG 0
#include <error/expected_utils.h>
-#include <media/audiohal/AudioEffectUuid.h>
-#include <system/audio_effects/effect_aec.h>
-#include <system/audio_effects/effect_agc2.h>
-#include <system/audio_effects/effect_bassboost.h>
-#include <system/audio_effects/effect_downmix.h>
-#include <system/audio_effects/effect_dynamicsprocessing.h>
-#include <system/audio_effects/effect_environmentalreverb.h>
-#include <system/audio_effects/effect_equalizer.h>
-#include <system/audio_effects/effect_hapticgenerator.h>
-#include <system/audio_effects/effect_loudnessenhancer.h>
-#include <system/audio_effects/effect_ns.h>
-#include <system/audio_effects/effect_presetreverb.h>
-#include <system/audio_effects/effect_spatializer.h>
-#include <system/audio_effects/effect_virtualizer.h>
-#include <system/audio_effects/effect_visualizer.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
#include <utils/Log.h>
@@ -45,15 +32,10 @@
namespace effect {
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
-using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
-using ::aidl::android::hardware::audio::effect::AutomaticGainControl;
-using ::aidl::android::hardware::audio::effect::BassBoost;
using ::aidl::android::hardware::audio::effect::CommandId;
using ::aidl::android::hardware::audio::effect::Descriptor;
-using ::aidl::android::hardware::audio::effect::Downmix;
using ::aidl::android::hardware::audio::effect::Parameter;
using ::aidl::android::media::audio::common::AudioDeviceDescription;
-using ::aidl::android::media::audio::common::AudioUuid;
using android::effect::utils::EffectParamReader;
using android::effect::utils::EffectParamWriter;
@@ -75,26 +57,9 @@
{EFFECT_CMD_OFFLOAD, &EffectConversionHelperAidl::handleSetOffload},
{EFFECT_CMD_FIRST_PROPRIETARY, &EffectConversionHelperAidl::handleFirstPriority}};
-const std::map<AudioUuid /* TypeUUID */, std::pair<EffectConversionHelperAidl::SetParameter,
- EffectConversionHelperAidl::GetParameter>>
- EffectConversionHelperAidl::mParameterHandlerMap = {
- {kAcousticEchoCancelerTypeUUID,
- {&EffectConversionHelperAidl::setAecParameter,
- &EffectConversionHelperAidl::getAecParameter}},
- {kAutomaticGainControlTypeUUID,
- {&EffectConversionHelperAidl::setAgcParameter,
- &EffectConversionHelperAidl::getAgcParameter}},
- {kBassBoostTypeUUID,
- {&EffectConversionHelperAidl::setBassBoostParameter,
- &EffectConversionHelperAidl::getBassBoostParameter}},
- {kDownmixTypeUUID,
- {&EffectConversionHelperAidl::setDownmixParameter,
- &EffectConversionHelperAidl::getDownmixParameter}}};
-
EffectConversionHelperAidl::EffectConversionHelperAidl(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
- int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ int32_t sessionId, int32_t ioId, const Descriptor& desc)
: mSessionId(sessionId), mIoId(ioId), mDesc(desc), mEffect(std::move(effect)) {
mCommon.session = sessionId;
mCommon.ioHandle = ioId;
@@ -136,14 +101,7 @@
return BAD_VALUE;
}
- const auto& handler = mParameterHandlerMap.find(mDesc.common.id.type);
- if (handler == mParameterHandlerMap.end() || !handler->second.first) {
- ALOGE("%s handler for uuid %s not found", __func__,
- mDesc.common.id.type.toString().c_str());
- return BAD_VALUE;
- }
- const SetParameter& functor = handler->second.first;
- return *(status_t*)pReplyData = (this->*functor)(reader);
+ return *(status_t*)pReplyData = setParameter(reader);
}
status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
@@ -153,24 +111,20 @@
}
const auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
- if (!reader.validateCmdSize(cmdSize)) {
- ALOGE("%s illegal param %s, replysize %u", __func__, reader.toString().c_str(),
+ if (!reader.validateCmdSize(cmdSize) ||
+ *replySize < sizeof(effect_param_t) + reader.getParameterSize()) {
+ ALOGE("%s illegal param %s, replySize %u", __func__, reader.toString().c_str(),
*replySize);
return BAD_VALUE;
}
- const auto& handler = mParameterHandlerMap.find(mDesc.common.id.type);
- if (handler == mParameterHandlerMap.end() || !handler->second.second) {
- ALOGE("%s handler for uuid %s not found", __func__,
- mDesc.common.id.type.toString().c_str());
- return BAD_VALUE;
- }
- const GetParameter& functor = handler->second.second;
+ // copy effect_param_t and parameters
memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + reader.getParameterSize());
- auto writer = EffectParamWriter(*(effect_param_t *)pReplyData);
- (this->*functor)(writer);
+ auto writer = EffectParamWriter(*(effect_param_t*)pReplyData);
+ status_t ret = getParameter(writer);
+ writer.finishValueWrite();
*replySize = writer.getTotalSize();
- return writer.getStatus();
+ return ret;
}
status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const void* pCmdData,
@@ -182,17 +136,19 @@
const auto& legacyConfig = static_cast<const effect_config_t*>(pCmdData);
// already open, apply latest settings
- mCommon.input.base =
+ Parameter::Common common;
+ common.input.base =
VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
legacyConfig->inputCfg, true /* isInput */));
- mCommon.output.base =
+ common.output.base =
VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
legacyConfig->outputCfg, false /* isInput */));
- mCommon.session = mSessionId;
- mCommon.ioHandle = mIoId;
+ common.session = mSessionId;
+ common.ioHandle = mIoId;
// TODO: add access mode support
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mEffect->setParameter(Parameter::make<Parameter::common>(mCommon))));
+ mEffect->setParameter(Parameter::make<Parameter::common>(common))));
+ mCommon = common;
return *static_cast<int32_t*>(pReplyData) = OK;
}
@@ -215,6 +171,7 @@
pConfig->outputCfg =
VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(
common.output.base, false));
+ mCommon = common;
return OK;
}
@@ -306,262 +263,5 @@
return OK;
}
-status_t EffectConversionHelperAidl::setAecParameter(EffectParamReader& param) {
- uint32_t type, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type) ||
- OK != param.readFromValue(&value)) {
- ALOGW("%s invalid param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
-
- Parameter aidlParam;
- switch (type) {
- case AEC_PARAM_ECHO_DELAY:
- FALLTHROUGH_INTENDED;
- case AEC_PARAM_PROPERTIES: {
- aidlParam = VALUE_OR_RETURN_STATUS(
- aidl::android::legacy2aidl_uint32_echoDelay_Parameter_aec(value));
- break;
- }
- case AEC_PARAM_MOBILE_MODE: {
- aidlParam = VALUE_OR_RETURN_STATUS(
- aidl::android::legacy2aidl_uint32_mobileMode_Parameter_aec(value));
- break;
- }
- default: {
- ALOGW("%s unknown param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- }
-
- return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
-}
-
-status_t EffectConversionHelperAidl::getAecParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
- param.setStatus(BAD_VALUE);
- ALOGW("%s invalid param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- Parameter aidlParam;
- switch (type) {
- case AEC_PARAM_ECHO_DELAY:
- FALLTHROUGH_INTENDED;
- case AEC_PARAM_PROPERTIES: {
- Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AcousticEchoCanceler,
- acousticEchoCancelerTag, echoDelayUs);
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- value = VALUE_OR_RETURN_STATUS(
- aidl::android::aidl2legacy_Parameter_aec_uint32_echoDelay(aidlParam));
- break;
- }
- case AEC_PARAM_MOBILE_MODE: {
- Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AcousticEchoCanceler,
- acousticEchoCancelerTag, mobileMode);
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- value = VALUE_OR_RETURN_STATUS(
- aidl::android::aidl2legacy_Parameter_aec_uint32_mobileMode(aidlParam));
- break;
- }
- default:
- ALOGW("%s unknown param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- param.writeToValue(&value);
- return OK;
-}
-
-status_t EffectConversionHelperAidl::setAgcParameter(EffectParamReader& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
- ALOGW("%s invalid param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- Parameter aidlParam;
- switch (type) {
- case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
- aidlParam = VALUE_OR_RETURN_STATUS(
- aidl::android::legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(value));
- break;
- }
- case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
- aidlParam = VALUE_OR_RETURN_STATUS(
- aidl::android::legacy2aidl_uint32_levelEstimator_Parameter_agc(value));
- break;
- }
- case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
- aidlParam = VALUE_OR_RETURN_STATUS(
- aidl::android::legacy2aidl_uint32_saturationMargin_Parameter_agc(value));
- break;
- }
- default: {
- ALOGW("%s unknown param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- }
-
- return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
-}
-
-status_t EffectConversionHelperAidl::getAgcParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
- ALOGW("%s invalid param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- Parameter aidlParam;
- switch (type) {
- case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
- Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(
- AutomaticGainControl, automaticGainControlTag, fixedDigitalGainMb);
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- value = VALUE_OR_RETURN_STATUS(
- aidl::android::aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(aidlParam));
- break;
- }
- case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
- Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControl,
- automaticGainControlTag, levelEstimator);
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- value = VALUE_OR_RETURN_STATUS(
- aidl::android::aidl2legacy_Parameter_agc_uint32_levelEstimator(aidlParam));
- break;
- }
- case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
- Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(
- AutomaticGainControl, automaticGainControlTag, saturationMarginMb);
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- value = VALUE_OR_RETURN_STATUS(
- aidl::android::aidl2legacy_Parameter_agc_uint32_saturationMargin(aidlParam));
- break;
- }
- default: {
- ALOGW("%s unknown param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- }
-
- param.writeToValue(&value);
- return OK;
-}
-
-status_t EffectConversionHelperAidl::setBassBoostParameter(EffectParamReader& param) {
- uint32_t type = 0;
- uint16_t value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
- ALOGW("%s invalid param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- Parameter aidlParam;
- switch (type) {
- case BASSBOOST_PARAM_STRENGTH: {
- aidlParam = VALUE_OR_RETURN_STATUS(
- aidl::android::legacy2aidl_uint16_strengthPm_Parameter_BassBoost(value));
- break;
- }
- case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
- ALOGW("%s set BASSBOOST_PARAM_STRENGTH_SUPPORTED not supported", __func__);
- return BAD_VALUE;
- }
- default: {
- ALOGW("%s unknown param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- }
-
- return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
-}
-
-status_t EffectConversionHelperAidl::getBassBoostParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
- ALOGW("%s invalid param %s", __func__, param.toString().c_str());
- param.setStatus(BAD_VALUE);
- return BAD_VALUE;
- }
- Parameter aidlParam;
- switch (type) {
- case BASSBOOST_PARAM_STRENGTH: {
- Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(BassBoost, bassBoostTag, strengthPm);
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- value = VALUE_OR_RETURN_STATUS(
- aidl::android::aidl2legacy_Parameter_BassBoost_uint16_strengthPm(aidlParam));
- break;
- }
- case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
- const auto& cap =
- VALUE_OR_RETURN_STATUS(aidl::android::UNION_GET(mDesc.capability, bassBoost));
- value = VALUE_OR_RETURN_STATUS(
- aidl::android::convertIntegral<uint32_t>(cap.strengthSupported));
- break;
- }
- default: {
- ALOGW("%s unknown param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- }
-
- param.writeToValue(&value);
- return OK;
-}
-
-status_t EffectConversionHelperAidl::setDownmixParameter(EffectParamReader& param) {
- uint32_t type = 0;
- int16_t value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int16_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
- ALOGW("%s invalid param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- Parameter aidlParam;
- switch (type) {
- case DOWNMIX_PARAM_TYPE: {
- aidlParam = VALUE_OR_RETURN_STATUS(
- aidl::android::legacy2aidl_int16_type_Parameter_Downmix(value));
- break;
- }
- default: {
- ALOGW("%s unknown param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- }
-
- return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
-}
-
-status_t EffectConversionHelperAidl::getDownmixParameter(EffectParamWriter& param) {
- int16_t value = 0;
- uint32_t type = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
- param.setStatus(BAD_VALUE);
- return BAD_VALUE;
- }
- Parameter aidlParam;
- switch (type) {
- case DOWNMIX_PARAM_TYPE: {
- Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Downmix, downmixTag, type);
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- value = VALUE_OR_RETURN_STATUS(
- aidl::android::aidl2legacy_Parameter_Downmix_int16_type(aidlParam));
- break;
- }
- default: {
- ALOGW("%s unknown param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- }
-
- param.writeToValue(&value);
- return OK;
-}
-
-} // namespace effect
-} // namespace android
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 35249f5..490a1dc 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -16,14 +16,9 @@
#pragma once
-#include <cstddef>
-#include <map>
-#include <memory>
#include <utils/Errors.h>
-#include <aidl/android/hardware/audio/effect/IEffect.h>
-
-#include <media/AidlConversionNdk.h>
+#include <aidl/android/hardware/audio/effect/BpEffect.h>
#include <system/audio_effect.h>
#include <system/audio_effects/audio_effects_utils.h>
@@ -31,24 +26,30 @@
namespace effect {
class EffectConversionHelperAidl {
+ public:
+ status_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ virtual ~EffectConversionHelperAidl() {}
+
protected:
+ const int32_t mSessionId;
+ const int32_t mIoId;
+ const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
+ ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn mOpenReturn;
+ ::aidl::android::hardware::audio::effect::Parameter::Common mCommon;
+
EffectConversionHelperAidl(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
const ::aidl::android::hardware::audio::effect::Descriptor& desc);
- status_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
- void* pReplyData);
+ status_t handleSetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleGetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
private:
- const int32_t mSessionId;
- const int32_t mIoId;
- const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
- ::aidl::android::media::audio::common::AudioUuid mTypeUuid;
- const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
- ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn mOpenReturn;
- ::aidl::android::hardware::audio::effect::Parameter::Common mCommon;
-
const aidl::android::media::audio::common::AudioFormatDescription kDefaultFormatDescription = {
.type = aidl::android::media::audio::common::AudioFormatType::PCM,
.pcm = aidl::android::media::audio::common::PcmType::FLOAT_32_BIT};
@@ -69,21 +70,8 @@
void* /* pReplyData */);
static const std::map<uint32_t /* effect_command_e */, CommandHandler> mCommandHandlerMap;
- // parameter set/get handler map
- typedef status_t (EffectConversionHelperAidl::*SetParameter)(
- android::effect::utils::EffectParamReader& param);
- typedef status_t (EffectConversionHelperAidl::*GetParameter)(
- android::effect::utils::EffectParamWriter& param);
- static const std::map<::aidl::android::media::audio::common::AudioUuid /* TypeUUID */,
- std::pair<SetParameter, GetParameter>>
- mParameterHandlerMap;
-
status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
- status_t handleSetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
- void* pReplyData);
- status_t handleGetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
- void* pReplyData);
status_t handleSetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
status_t handleGetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
@@ -103,15 +91,9 @@
status_t handleFirstPriority(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
- // set/get parameter handler
- status_t setAecParameter(android::effect::utils::EffectParamReader& param);
- status_t getAecParameter(android::effect::utils::EffectParamWriter& param);
- status_t setAgcParameter(android::effect::utils::EffectParamReader& param);
- status_t getAgcParameter(android::effect::utils::EffectParamWriter& param);
- status_t setBassBoostParameter(android::effect::utils::EffectParamReader& param);
- status_t getBassBoostParameter(android::effect::utils::EffectParamWriter& param);
- status_t setDownmixParameter(android::effect::utils::EffectParamReader& param);
- status_t getDownmixParameter(android::effect::utils::EffectParamWriter& param);
+ // implemented by conversion of each effect
+ virtual status_t setParameter(utils::EffectParamReader& param) = 0;
+ virtual status_t getParameter(utils::EffectParamWriter& param) = 0;
};
} // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 0c37552..08040f3 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -14,13 +14,15 @@
* limitations under the License.
*/
+#include <memory>
#define LOG_TAG "EffectHalAidl"
//#define LOG_NDEBUG 0
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
-#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
#include <media/AidlConversionUtil.h>
+#include <media/audiohal/AudioEffectUuid.h>
#include <media/EffectsFactoryApi.h>
#include <mediautils/TimeCheck.h>
#include <utils/Log.h>
@@ -38,6 +40,12 @@
#include <system/audio.h>
#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "effectsAidlConversion/AidlConversionAec.h"
+#include "effectsAidlConversion/AidlConversionAgc2.h"
+#include "effectsAidlConversion/AidlConversionBassBoost.h"
+#include "effectsAidlConversion/AidlConversionDownmix.h"
+#include "effectsAidlConversion/AidlConversionDynamicsProcessing.h"
+
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
using ::aidl::android::hardware::audio::effect::CommandId;
using ::aidl::android::hardware::audio::effect::Descriptor;
@@ -53,13 +61,14 @@
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& effect,
uint64_t effectId, int32_t sessionId, int32_t ioId,
const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc),
- mFactory(factory),
+ : mFactory(factory),
mEffect(effect),
mEffectId(effectId),
mSessionId(sessionId),
mIoId(ioId),
- mDesc(desc) {}
+ mDesc(desc) {
+ createAidlConversion(effect, sessionId, ioId, desc);
+}
EffectHalAidl::~EffectHalAidl() {
if (mFactory) {
@@ -67,6 +76,34 @@
}
}
+status_t EffectHalAidl::createAidlConversion(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc) {
+ const auto& typeUuid = desc.common.id.type;
+ if (typeUuid == kAcousticEchoCancelerTypeUUID) {
+ mConversion =
+ std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId, desc);
+ } else if (typeUuid == kAutomaticGainControlTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
+ desc);
+ } else if (typeUuid == kBassBoostTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(effect, sessionId,
+ ioId, desc);
+ } else if (typeUuid == kDownmixTypeUUID) {
+ mConversion = std::make_unique<android::effect::AidlConversionDownmix>(effect, sessionId,
+ ioId, desc);
+ } else if (typeUuid == kDynamicsProcessingTypeUUID) {
+ mConversion =
+ std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId, desc);
+ } else {
+ ALOGE("%s effect not implemented yet, UUID type: %s", __func__,
+ typeUuid.toString().c_str());
+ return BAD_VALUE;
+ }
+ return OK;
+}
+
status_t EffectHalAidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
if (buffer == nullptr) {
return BAD_VALUE;
@@ -97,7 +134,9 @@
status_t EffectHalAidl::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
uint32_t* replySize, void* pReplyData) {
- return handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+ return mConversion
+ ? mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData)
+ : INVALID_OPERATION;
}
status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 6a1ec1c..83b644b 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -20,13 +20,14 @@
#include <aidl/android/hardware/audio/effect/IFactory.h>
#include <media/audiohal/EffectHalInterface.h>
#include <system/audio_effect.h>
+#include <memory>
#include "EffectConversionHelperAidl.h"
namespace android {
namespace effect {
-class EffectHalAidl : public EffectHalInterface, public EffectConversionHelperAidl {
+class EffectHalAidl : public EffectHalInterface {
public:
// Set the input buffer.
status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) override;
@@ -71,10 +72,15 @@
const int32_t mSessionId;
const int32_t mIoId;
const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
+ std::unique_ptr<EffectConversionHelperAidl> mConversion;
sp<EffectBufferHalInterface> mInBuffer, mOutBuffer;
effect_config_t mConfig;
+ status_t createAidlConversion(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc);
// Can not be constructed directly by clients.
EffectHalAidl(
const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory,
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index 878c19e..0aae87b 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -24,7 +24,7 @@
#include <error/expected_utils.h>
#include <android/binder_manager.h>
#include <media/AidlConversionCppNdk.h>
-#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
#include <system/audio.h>
#include <utils/Log.h>
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 1c6a014..2b7856b 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -46,10 +46,11 @@
}
StreamHalAidl::StreamHalAidl(
- std::string_view className, bool isInput, const StreamDescriptor& descriptor,
- const std::shared_ptr<IStreamCommon>& stream)
+ std::string_view className, bool isInput, const audio_config& config,
+ const StreamDescriptor& descriptor, const std::shared_ptr<IStreamCommon>& stream)
: ConversionHelperAidl(className),
mIsInput(isInput),
+ mConfig(configToBase(config)),
mFrameSizeBytes(descriptor.frameSizeBytes),
mBufferSizeFrames(descriptor.bufferSizeFrames),
mCommandMQ(new CommandMQ(descriptor.command)),
@@ -76,7 +77,7 @@
if (size == nullptr) {
return BAD_VALUE;
}
- if (mFrameSizeBytes == 0 || mBufferSizeFrames == 0) {
+ if (mFrameSizeBytes == 0 || mBufferSizeFrames == 0 || !mStream) {
return NO_INIT;
}
*size = mFrameSizeBytes * mBufferSizeFrames;
@@ -87,13 +88,8 @@
if (configBase == nullptr) {
return BAD_VALUE;
}
- TIME_CHECK();
- *configBase = AUDIO_CONFIG_BASE_INITIALIZER;
- configBase->sample_rate = 48000;
- configBase->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
- configBase->channel_mask = mIsInput ? AUDIO_CHANNEL_IN_STEREO : AUDIO_CHANNEL_OUT_STEREO;
- // if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (!mStream) return NO_INIT;
+ *configBase = mConfig;
return OK;
}
@@ -116,7 +112,7 @@
if (size == nullptr) {
return BAD_VALUE;
}
- if (mFrameSizeBytes == 0) {
+ if (mFrameSizeBytes == 0 || !mStream) {
return NO_INIT;
}
*size = mFrameSizeBytes;
@@ -140,6 +136,9 @@
status_t StreamHalAidl::standby() {
TIME_CHECK();
if (!mStream) return NO_INIT;
+ if (mState == StreamDescriptor::State::STANDBY) {
+ return OK;
+ }
ALOGE("%s not implemented yet", __func__);
return OK;
}
@@ -180,7 +179,7 @@
}
status_t StreamHalAidl::setHalThreadPriority(int priority __unused) {
- mHalThreadPriority = priority;
+ // Obsolete, must be done by the HAL module.
return OK;
}
@@ -192,12 +191,8 @@
}
bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
- if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
- return true;
- }
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ // Obsolete, must be done by the HAL module.
+ return true;
}
status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
@@ -244,8 +239,10 @@
} // namespace
StreamOutHalAidl::StreamOutHalAidl(
+ const audio_config& config,
const StreamDescriptor& descriptor, const std::shared_ptr<IStreamOut>& stream)
- : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, descriptor, getStreamCommon(stream)),
+ : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config,
+ descriptor, getStreamCommon(stream)),
mStream(stream) {}
status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
@@ -360,34 +357,55 @@
}
status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamOutHalAidl::getPlaybackRateParameters(
audio_playback_rate_t* playbackRate __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamOutHalAidl::setPlaybackRateParameters(
const audio_playback_rate_t& playbackRate __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamOutHalAidl::setEventCallback(
const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
namespace {
@@ -401,17 +419,26 @@
} // namespace
status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
};
status_t StreamOutHalAidl::getRecommendedLatencyModes(
std::vector<audio_latency_mode_t> *modes __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
};
status_t StreamOutHalAidl::setLatencyModeCallback(
const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
};
void StreamOutHalAidl::onWriteReady() {
@@ -458,8 +485,10 @@
}
StreamInHalAidl::StreamInHalAidl(
+ const audio_config& config,
const StreamDescriptor& descriptor, const std::shared_ptr<IStreamIn>& stream)
- : StreamHalAidl("StreamInHalAidl", true /*isInput*/, descriptor, getStreamCommon(stream)),
+ : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config,
+ descriptor, getStreamCommon(stream)),
mStream(stream) {}
status_t StreamInHalAidl::setGain(float gain __unused) {
@@ -494,24 +523,33 @@
status_t StreamInHalAidl::getActiveMicrophones(
std::vector<media::MicrophoneInfo> *microphones __unused) {
- if (mStream == 0) return NO_INIT;
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamInHalAidl::updateSinkMetadata(
const StreamInHalInterface::SinkMetadata& sinkMetadata __unused) {
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamInHalAidl::setPreferredMicrophoneDirection(
audio_microphone_direction_t direction __unused) {
- if (mStream == 0) return NO_INIT;
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
- if (mStream == 0) return NO_INIT;
- return INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ ALOGE("%s not implemented yet", __func__);
+ return OK;
}
} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index c56d5e3..e55c413 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -101,6 +101,7 @@
// Subclasses can not be constructed directly by clients.
StreamHalAidl(std::string_view className,
bool isInput,
+ const audio_config& config,
const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream);
@@ -111,6 +112,7 @@
bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
const bool mIsInput;
+ const audio_config_base_t mConfig;
const size_t mFrameSizeBytes;
const size_t mBufferSizeFrames;
const std::unique_ptr<CommandMQ> mCommandMQ;
@@ -118,8 +120,17 @@
const std::unique_ptr<DataMQ> mDataMQ;
// mStreamPowerLog is used for audio signal power logging.
StreamPowerLog mStreamPowerLog;
+ ::aidl::android::hardware::audio::core::StreamDescriptor::State mState =
+ ::aidl::android::hardware::audio::core::StreamDescriptor::State::STANDBY;
private:
+ static audio_config_base_t configToBase(const audio_config& config) {
+ audio_config_base_t result = AUDIO_CONFIG_BASE_INITIALIZER;
+ result.sample_rate = config.sample_rate;
+ result.channel_mask = config.channel_mask;
+ result.format = config.format;
+ return result;
+ }
static std::unique_ptr<DataMQ> maybeCreateDataMQ(
const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
@@ -129,9 +140,7 @@
return nullptr;
}
- const int HAL_THREAD_PRIORITY_DEFAULT = -1;
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
- int mHalThreadPriority = HAL_THREAD_PRIORITY_DEFAULT;
};
class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {
@@ -230,6 +239,7 @@
// Can not be constructed directly by clients.
StreamOutHalAidl(
+ const audio_config& config,
const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream);
@@ -271,6 +281,7 @@
// Can not be constructed directly by clients.
StreamInHalAidl(
+ const audio_config& config,
const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream);
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
new file mode 100644
index 0000000..901566e
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
@@ -0,0 +1,113 @@
+/*
+ * 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionAec"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_aec.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionAec.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionAec::setParameter(EffectParamReader& param) {
+ uint32_t type, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type) ||
+ OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ switch (type) {
+ case AEC_PARAM_ECHO_DELAY:
+ FALLTHROUGH_INTENDED;
+ case AEC_PARAM_PROPERTIES: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_echoDelay_Parameter_aec(value));
+ break;
+ }
+ case AEC_PARAM_MOBILE_MODE: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_mobileMode_Parameter_aec(value));
+ break;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAec::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ param.setStatus(BAD_VALUE);
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case AEC_PARAM_ECHO_DELAY:
+ FALLTHROUGH_INTENDED;
+ case AEC_PARAM_PROPERTIES: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AcousticEchoCanceler, acousticEchoCancelerTag,
+ AcousticEchoCanceler::echoDelayUs);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_aec_uint32_echoDelay(aidlParam));
+ break;
+ }
+ case AEC_PARAM_MOBILE_MODE: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AcousticEchoCanceler, acousticEchoCancelerTag,
+ AcousticEchoCanceler::mobileMode);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_aec_uint32_mobileMode(aidlParam));
+ break;
+ }
+ default:
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
new file mode 100644
index 0000000..3ee419a
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
@@ -0,0 +1,39 @@
+/*
+ * 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/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionAec : public EffectConversionHelperAidl {
+ public:
+ AidlConversionAec(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionAec() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
new file mode 100644
index 0000000..80df2b8
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionAgc2"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_agc2.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionAgc2.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControl;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionAgc2::setParameter(EffectParamReader& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(value));
+ break;
+ }
+ case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_levelEstimator_Parameter_agc(value));
+ break;
+ }
+ case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint32_saturationMargin_Parameter_agc(value));
+ break;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc2::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControl, automaticGainControlTag,
+ AutomaticGainControl::fixedDigitalGainMb);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(aidlParam));
+ break;
+ }
+ case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControl, automaticGainControlTag,
+ AutomaticGainControl::levelEstimator);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_agc_uint32_levelEstimator(aidlParam));
+ break;
+ }
+ case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControl, automaticGainControlTag,
+ AutomaticGainControl::saturationMarginMb);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_agc_uint32_saturationMargin(aidlParam));
+ break;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
new file mode 100644
index 0000000..8f7eac7
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
@@ -0,0 +1,39 @@
+/*
+ * 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/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionAgc2 : public EffectConversionHelperAidl {
+ public:
+ AidlConversionAgc2(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionAgc2() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
new file mode 100644
index 0000000..ba8148f
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionBassBoost"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_bassboost.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionBassBoost.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::BassBoost;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionBassBoost::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ uint16_t value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case BASSBOOST_PARAM_STRENGTH: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_uint16_strengthPm_Parameter_BassBoost(value));
+ break;
+ }
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
+ ALOGW("%s set BASSBOOST_PARAM_STRENGTH_SUPPORTED not supported", __func__);
+ return BAD_VALUE;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionBassBoost::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case BASSBOOST_PARAM_STRENGTH: {
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(BassBoost, bassBoostTag, BassBoost::strengthPm);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_BassBoost_uint16_strengthPm(aidlParam));
+ break;
+ }
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
+ const auto& cap =
+ VALUE_OR_RETURN_STATUS(aidl::android::UNION_GET(mDesc.capability, bassBoost));
+ value = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(cap.strengthSupported));
+ break;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
new file mode 100644
index 0000000..9664aa1
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
@@ -0,0 +1,40 @@
+/*
+ * 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/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionBassBoost : public EffectConversionHelperAidl {
+ public:
+ AidlConversionBassBoost(
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionBassBoost() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp
new file mode 100644
index 0000000..17cedf7
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionDownmix"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/effect_downmix.h>
+
+#include <system/audio_effect.h>
+#include <utils/Log.h>
+
+#include "AidlConversionDownmix.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Downmix;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionDownmix::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ int16_t value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int16_t)) ||
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case DOWNMIX_PARAM_TYPE: {
+ aidlParam = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_int16_type_Parameter_Downmix(value));
+ break;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionDownmix::getParameter(EffectParamWriter& param) {
+ int16_t value = 0;
+ uint32_t type = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ OK != param.readFromParameter(&type)) {
+ param.setStatus(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case DOWNMIX_PARAM_TYPE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Downmix, downmixTag, Downmix::type);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_Downmix_int16_type(aidlParam));
+ break;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
new file mode 100644
index 0000000..8b28ca3
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
@@ -0,0 +1,39 @@
+/*
+ * 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/audio/effect/BpEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionDownmix : public EffectConversionHelperAidl {
+ public:
+ AidlConversionDownmix(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionDownmix() {}
+
+ private:
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
new file mode 100644
index 0000000..4ecaa07
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -0,0 +1,522 @@
+/*
+ * 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 <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionDp"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effect.h>
+#include <system/audio_effects/effect_dynamicsprocessing.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionDynamicsProcessing.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Capability;
+using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::toString;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionDp::setParameter(EffectParamReader& param) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case DP_PARAM_INPUT_GAIN: {
+ DynamicsProcessing::InputGain inputGainAidl;
+ if (OK != param.readFromParameter(&inputGainAidl.channel) ||
+ OK != param.readFromValue(&inputGainAidl.gainDb)) {
+ ALOGE("%s invalid inputGain %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, inputGain,
+ {inputGainAidl});
+ break;
+ }
+ case DP_PARAM_ENGINE_ARCHITECTURE: {
+ DynamicsProcessing::EngineArchitecture engine =
+ VALUE_OR_RETURN_STATUS(readEngineArchitectureFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing,
+ engineArchitecture, engine);
+ mEngine = engine;
+ break;
+ }
+ case DP_PARAM_PRE_EQ: {
+ DynamicsProcessing::ChannelConfig chConfig =
+ VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, preEq,
+ {chConfig});
+ break;
+ }
+ case DP_PARAM_POST_EQ: {
+ DynamicsProcessing::ChannelConfig chConfig =
+ VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, postEq,
+ {chConfig});
+ break;
+ }
+ case DP_PARAM_MBC: {
+ DynamicsProcessing::ChannelConfig chConfig =
+ VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, mbc,
+ {chConfig});
+ break;
+ }
+ case DP_PARAM_PRE_EQ_BAND: {
+ DynamicsProcessing::EqBandConfig bandConfig =
+ VALUE_OR_RETURN_STATUS(readEqBandConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, preEqBand,
+ {bandConfig});
+ break;
+ }
+ case DP_PARAM_POST_EQ_BAND: {
+ DynamicsProcessing::EqBandConfig bandConfig =
+ VALUE_OR_RETURN_STATUS(readEqBandConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, postEqBand,
+ {bandConfig});
+ break;
+ }
+ case DP_PARAM_MBC_BAND: {
+ DynamicsProcessing::MbcBandConfig bandConfig =
+ VALUE_OR_RETURN_STATUS(readMbcBandConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, mbcBand,
+ {bandConfig});
+ break;
+ }
+ case DP_PARAM_LIMITER: {
+ DynamicsProcessing::LimiterConfig config =
+ VALUE_OR_RETURN_STATUS(readLimiterConfigFromParam(param));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, limiter,
+ {config});
+ break;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionDp::getParameter(EffectParamWriter& param) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ }
+ Parameter aidlParam;
+ switch (type) {
+ case DP_PARAM_INPUT_GAIN: {
+ int32_t channel;
+ if (OK != param.readFromParameter(&channel)) {
+ ALOGE("%s invalid inputGain %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+ DynamicsProcessing::inputGain);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ DynamicsProcessing::Capability cap =
+ mDesc.capability.get<Capability::dynamicsProcessing>();
+ std::vector<DynamicsProcessing::InputGain> gains =
+ VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing,
+ DynamicsProcessing::inputGain,
+ std::vector<DynamicsProcessing::InputGain>));
+ for (const auto& gain : gains) {
+ if (gain.channel == channel) {
+ return param.writeToValue(&gain.gainDb);
+ }
+ }
+ ALOGE("%s not able to find channel %d", __func__, channel);
+ return BAD_VALUE;
+ }
+ case DP_PARAM_ENGINE_ARCHITECTURE: {
+ int32_t channel;
+ if (OK != param.readFromParameter(&channel)) {
+ ALOGE("%s invalid inputGain %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+ DynamicsProcessing::engineArchitecture);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ DynamicsProcessing::EngineArchitecture engine =
+ VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing,
+ DynamicsProcessing::engineArchitecture,
+ DynamicsProcessing::EngineArchitecture));
+ int32_t resolution = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+ engine.resolutionPreference));
+ int32_t preEqInUse =
+ VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.preEqStage.inUse));
+ int32_t mbcInUse =
+ VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.mbcStage.inUse));
+ int32_t postEqInUse =
+ VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.postEqStage.inUse));
+ int32_t limiterInUse =
+ VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.limiterInUse));
+ if (OK != param.writeToValue(&resolution) ||
+ OK != param.writeToValue(&engine.preferredProcessingDurationMs) ||
+ OK != param.writeToValue(&preEqInUse) ||
+ OK != param.writeToValue(&engine.preEqStage.bandCount) ||
+ OK != param.writeToValue(&mbcInUse) ||
+ OK != param.writeToValue(&engine.mbcStage.bandCount) ||
+ OK != param.writeToValue(&postEqInUse) ||
+ OK != param.writeToValue(&engine.postEqStage.bandCount) ||
+ OK != param.writeToValue(&limiterInUse)) {
+ ALOGE("%s invalid engineArchitecture %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ mEngine = engine;
+ return OK;
+ }
+ case DP_PARAM_PRE_EQ: {
+ return getChannelConfig(DynamicsProcessing::preEq, param);
+ }
+ case DP_PARAM_POST_EQ: {
+ return getChannelConfig(DynamicsProcessing::postEq, param);
+ }
+ case DP_PARAM_MBC: {
+ return getChannelConfig(DynamicsProcessing::mbc, param);
+ }
+ case DP_PARAM_PRE_EQ_BAND: {
+ return getEqBandConfig(DynamicsProcessing::preEqBand, param);
+ }
+ case DP_PARAM_POST_EQ_BAND: {
+ return getEqBandConfig(DynamicsProcessing::postEqBand, param);
+ }
+ case DP_PARAM_MBC_BAND: {
+ return getMbcBandConfig(param);
+ }
+ case DP_PARAM_LIMITER: {
+ return getLimiterConfig(param);
+ }
+ case DP_PARAM_GET_CHANNEL_COUNT: {
+ uint32_t channel = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ mCommon.input.base.channelMask, true /* input */));
+ if (OK != param.writeToValue(&channel)) {
+ ALOGE("%s write channel number %d to param failed %s", __func__, channel,
+ param.toString().c_str());
+ return BAD_VALUE;
+ }
+ return OK;
+ }
+ default: {
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+}
+
+aidl::ConversionResult<DynamicsProcessing::ChannelConfig>
+AidlConversionDp::readChannelConfigFromParam(EffectParamReader& param) {
+ int32_t enable, channel;
+ if (OK != param.readFromParameter(&channel) || OK != param.readFromValue(&enable)) {
+ ALOGE("%s invalid channel config param %s", __func__, param.toString().c_str());
+ return ::android::base::unexpected(::android::BAD_VALUE);
+ }
+ return DynamicsProcessing::ChannelConfig(
+ {.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable)), .channel = channel});
+}
+
+aidl::ConversionResult<DynamicsProcessing::EqBandConfig>
+AidlConversionDp::readEqBandConfigFromParam(EffectParamReader& param) {
+ DynamicsProcessing::EqBandConfig config;
+ int32_t enable;
+ if (OK != param.readFromParameter(&config.channel) ||
+ OK != param.readFromParameter(&config.band) ||
+ OK != param.readFromValue(&enable) ||
+ OK != param.readFromValue(&config.cutoffFrequencyHz) ||
+ OK != param.readFromValue(&config.gainDb)) {
+ ALOGE("%s invalid eq band param %s", __func__, param.toString().c_str());
+ return ::android::base::unexpected(::android::BAD_VALUE);
+ }
+ config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+ return config;
+}
+
+aidl::ConversionResult<DynamicsProcessing::MbcBandConfig>
+AidlConversionDp::readMbcBandConfigFromParam(EffectParamReader& param) {
+ DynamicsProcessing::MbcBandConfig config;
+ int32_t enable;
+ if (OK != param.readFromParameter(&config.channel) ||
+ OK != param.readFromParameter(&config.band) ||
+ OK != param.readFromValue(&enable) ||
+ OK != param.readFromValue(&config.cutoffFrequencyHz) ||
+ OK != param.readFromValue(&config.attackTimeMs) ||
+ OK != param.readFromValue(&config.releaseTimeMs) ||
+ OK != param.readFromValue(&config.ratio) ||
+ OK != param.readFromValue(&config.thresholdDb) ||
+ OK != param.readFromValue(&config.kneeWidthDb) ||
+ OK != param.readFromValue(&config.noiseGateThresholdDb) ||
+ OK != param.readFromValue(&config.expanderRatio) ||
+ OK != param.readFromValue(&config.preGainDb) ||
+ OK != param.readFromValue(&config.postGainDb)) {
+ ALOGE("%s invalid mbc band config param %s", __func__, param.toString().c_str());
+ return ::android::base::unexpected(::android::BAD_VALUE);
+ }
+ config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+ return config;
+}
+
+aidl::ConversionResult<DynamicsProcessing::LimiterConfig>
+AidlConversionDp::readLimiterConfigFromParam(EffectParamReader& param) {
+ DynamicsProcessing::LimiterConfig config;
+ int32_t enable, inUse;
+ if (OK != param.readFromParameter(&config.channel) ||
+ OK != param.readFromValue(&inUse) ||
+ OK != param.readFromValue(&enable) ||
+ OK != param.readFromValue(&config.linkGroup) ||
+ OK != param.readFromValue(&config.attackTimeMs) ||
+ OK != param.readFromValue(&config.releaseTimeMs) ||
+ OK != param.readFromValue(&config.ratio) ||
+ OK != param.readFromValue(&config.thresholdDb) ||
+ OK != param.readFromValue(&config.postGainDb)) {
+ ALOGE("%s invalid limiter config param %s", __func__, param.toString().c_str());
+ return ::android::base::unexpected(::android::BAD_VALUE);
+ }
+ config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+ return config;
+}
+
+aidl::ConversionResult<DynamicsProcessing::EngineArchitecture>
+AidlConversionDp::readEngineArchitectureFromParam(EffectParamReader& param) {
+ DynamicsProcessing::EngineArchitecture engine;
+ int32_t variant, preEqInUse, mbcInUse, postEqInUse, limiterInUse;
+ if (OK != param.readFromValue(&variant) &&
+ OK != param.readFromValue(&engine.preferredProcessingDurationMs) &&
+ OK != param.readFromValue(&preEqInUse) &&
+ OK != param.readFromValue(&engine.preEqStage.bandCount) &&
+ OK != param.readFromValue(&mbcInUse) &&
+ OK != param.readFromValue(&engine.mbcStage.bandCount) &&
+ OK != param.readFromValue(&postEqInUse) &&
+ OK != param.readFromValue(&engine.postEqStage.bandCount) &&
+ OK != param.readFromValue(&limiterInUse)) {
+ ALOGE("%s invalid engineArchitecture %s", __func__, param.toString().c_str());
+ return ::android::base::unexpected(::android::BAD_VALUE);
+ }
+
+ engine.resolutionPreference = VALUE_OR_RETURN(
+ aidl::android::legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(variant));
+ engine.preEqStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(preEqInUse));
+ engine.mbcStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(mbcInUse));
+ engine.postEqStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(postEqInUse));
+ engine.limiterInUse = VALUE_OR_RETURN(convertIntegral<bool>(limiterInUse));
+ return engine;
+}
+
+status_t AidlConversionDp::getChannelConfig(DynamicsProcessing::Tag tag, EffectParamWriter& param) {
+ int32_t channel;
+ if (OK != param.readFromParameter(&channel)) {
+ ALOGE("%s invalid parameter %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag, tag);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::ChannelConfig> channels;
+ int32_t inUse, bandCount;
+ switch (tag) {
+ case DynamicsProcessing::preEq: {
+ inUse = mEngine.preEqStage.inUse;
+ bandCount = mEngine.preEqStage.bandCount;
+ channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::preEq,
+ std::vector<DynamicsProcessing::ChannelConfig>));
+ break;
+ }
+ case DynamicsProcessing::postEq: {
+ inUse = mEngine.postEqStage.inUse;
+ bandCount = mEngine.postEqStage.bandCount;
+ channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::postEq,
+ std::vector<DynamicsProcessing::ChannelConfig>));
+ break;
+ }
+ case DynamicsProcessing::mbc: {
+ inUse = mEngine.mbcStage.inUse;
+ bandCount = mEngine.mbcStage.bandCount;
+ channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::mbc,
+ std::vector<DynamicsProcessing::ChannelConfig>));
+ break;
+ }
+ default: {
+ ALOGE("%s unsupported tag %s", __func__, toString(tag).c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ for (const auto& ch : channels) {
+ if (ch.channel == channel) {
+ int32_t enable = ch.enable;
+ if (OK != param.writeToValue(&inUse) ||
+ OK != param.writeToValue(&enable) ||
+ OK != param.writeToValue(&bandCount)) {
+ ALOGE("%s failed to write into param value %s", __func__,
+ param.toString().c_str());
+ return BAD_VALUE;
+ }
+ return OK;
+ }
+ }
+ ALOGE("%s not able to find channel %d", __func__, channel);
+ return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getEqBandConfig(DynamicsProcessing::Tag tag, EffectParamWriter& param) {
+ int32_t channel, band;
+ if (OK != param.readFromParameter(&channel) || OK != param.readFromParameter(&band)) {
+ ALOGE("%s invalid parameter %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag, tag);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::EqBandConfig> bands;
+ if (tag == DynamicsProcessing::preEqBand) {
+ bands = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, preEqBand,
+ std::vector<DynamicsProcessing::EqBandConfig>));
+ } else if (tag == DynamicsProcessing::postEqBand) {
+ bands = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, postEqBand,
+ std::vector<DynamicsProcessing::EqBandConfig>));
+ } else {
+ return BAD_VALUE;
+ }
+
+ for (const auto& bandIt : bands) {
+ if (bandIt.channel == channel && bandIt.band == band) {
+ int32_t enable = bandIt.enable;
+ if (OK != param.writeToValue(&enable) ||
+ OK != param.writeToValue(&bandIt.cutoffFrequencyHz) ||
+ OK != param.writeToValue(&bandIt.gainDb)) {
+ ALOGE("%s failed to write into param value %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ return OK;
+ }
+ }
+ ALOGE("%s not able to find channel %d band %d", __func__, channel, band);
+ return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getMbcBandConfig(EffectParamWriter& param) {
+ int32_t channel, band;
+ if (OK != param.readFromParameter(&channel) || OK != param.readFromParameter(&band)) {
+ ALOGE("%s invalid parameter %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+ DynamicsProcessing::mbcBand);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::MbcBandConfig> bands =
+ VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, mbcBand,
+ std::vector<DynamicsProcessing::MbcBandConfig>));
+
+ for (const auto& bandIt : bands) {
+ if (bandIt.channel == channel && bandIt.band == band) {
+ int32_t enable = bandIt.enable;
+ if (OK != param.writeToValue(&enable) ||
+ OK != param.writeToValue(&bandIt.cutoffFrequencyHz) ||
+ OK != param.writeToValue(&bandIt.attackTimeMs) ||
+ OK != param.writeToValue(&bandIt.releaseTimeMs) ||
+ OK != param.writeToValue(&bandIt.ratio) ||
+ OK != param.writeToValue(&bandIt.thresholdDb) ||
+ OK != param.writeToValue(&bandIt.kneeWidthDb) ||
+ OK != param.writeToValue(&bandIt.noiseGateThresholdDb) ||
+ OK != param.writeToValue(&bandIt.expanderRatio) ||
+ OK != param.writeToValue(&bandIt.preGainDb) ||
+ OK != param.writeToValue(&bandIt.postGainDb)) {
+ ALOGE("%s failed to write into param value %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ return OK;
+ }
+ }
+ ALOGE("%s not able to find channel %d band %d", __func__, channel, band);
+ return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getLimiterConfig(EffectParamWriter& param) {
+ int32_t channel;
+ if (OK != param.readFromParameter(&channel)) {
+ ALOGE("%s invalid parameter %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+ DynamicsProcessing::limiter);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+ std::vector<DynamicsProcessing::LimiterConfig> configs =
+ VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, DynamicsProcessing, dynamicsProcessing, limiter,
+ std::vector<DynamicsProcessing::LimiterConfig>));
+
+ for (const auto& config : configs) {
+ if (config.channel == channel) {
+ int32_t inUse = mEngine.limiterInUse;
+ int32_t enable = config.enable;
+ if (OK != param.writeToValue(&inUse) ||
+ OK != param.writeToValue(&enable) ||
+ OK != param.writeToValue(&config.linkGroup) ||
+ OK != param.writeToValue(&config.attackTimeMs) ||
+ OK != param.writeToValue(&config.releaseTimeMs) ||
+ OK != param.writeToValue(&config.ratio) ||
+ OK != param.writeToValue(&config.thresholdDb) ||
+ OK != param.writeToValue(&config.postGainDb)) {
+ ALOGE("%s failed to write into param value %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ return OK;
+ }
+ }
+ ALOGE("%s not able to find channel %d", __func__, channel);
+ return BAD_VALUE;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
new file mode 100644
index 0000000..6bab18d
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
@@ -0,0 +1,64 @@
+/*
+ * 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/audio/effect/BpEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionDp : public EffectConversionHelperAidl {
+ public:
+ AidlConversionDp(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ ~AidlConversionDp() {}
+
+ private:
+ aidl::android::hardware::audio::effect::DynamicsProcessing::EngineArchitecture mEngine;
+
+ status_t setParameter(utils::EffectParamReader& param) override;
+ status_t getParameter(utils::EffectParamWriter& param) override;
+
+ aidl::ConversionResult<
+ aidl::android::hardware::audio::effect::DynamicsProcessing::ChannelConfig>
+ readChannelConfigFromParam(utils::EffectParamReader& param);
+ aidl::ConversionResult<aidl::android::hardware::audio::effect::DynamicsProcessing::EqBandConfig>
+ readEqBandConfigFromParam(utils::EffectParamReader& param);
+ aidl::ConversionResult<
+ aidl::android::hardware::audio::effect::DynamicsProcessing::MbcBandConfig>
+ readMbcBandConfigFromParam(utils::EffectParamReader& param);
+ aidl::ConversionResult<
+ aidl::android::hardware::audio::effect::DynamicsProcessing::LimiterConfig>
+ readLimiterConfigFromParam(utils::EffectParamReader& param);
+ aidl::ConversionResult<
+ aidl::android::hardware::audio::effect::DynamicsProcessing::EngineArchitecture>
+ readEngineArchitectureFromParam(utils::EffectParamReader& param);
+
+ status_t getChannelConfig(aidl::android::hardware::audio::effect::DynamicsProcessing::Tag tag,
+ utils::EffectParamWriter& writer);
+ status_t getEqBandConfig(aidl::android::hardware::audio::effect::DynamicsProcessing::Tag tag,
+ utils::EffectParamWriter& param);
+ status_t getMbcBandConfig(utils::EffectParamWriter& param);
+ status_t getLimiterConfig(utils::EffectParamWriter& param);
+
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h b/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
index 20a10f6..77563e8 100644
--- a/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
+++ b/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
@@ -47,18 +47,18 @@
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
-// 0bed4300-ddd6-11db-8f34-0002a5d5c51b.
-static const AudioUuid kEqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
- 0xddd6,
- 0x11db,
- 0x8f34,
- {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// 7261676f-6d75-7369-6364-28e2fd3ac39e
static const AudioUuid kDynamicsProcessingTypeUUID = {static_cast<int32_t>(0x7261676f),
0x6d75,
0x7369,
0x6364,
{0x28, 0xe2, 0xfd, 0x3a, 0xc3, 0x9e}};
+// 0bed4300-ddd6-11db-8f34-0002a5d5c51b.
+static const AudioUuid kEqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
+ 0xddd6,
+ 0x11db,
+ 0x8f34,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// 1411e6d6-aecd-4021-a1cf-a6aceb0d71e5
static const AudioUuid kHapticGeneratorTypeUUID = {static_cast<int32_t>(0x1411e6d6),
0xaecd,
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index c2e2ba7..9b2d0e2 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -22,6 +22,7 @@
#include <system/audio_effects/audio_effects_utils.h>
#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_dynamicsprocessing.h>
#include <system/audio_effect.h>
#include <gtest/gtest.h>
@@ -29,6 +30,7 @@
namespace android {
+using effect::utils::EffectParamReader;
using effect::utils::EffectParamWriter;
// EffectsFactoryHalInterface
@@ -124,7 +126,7 @@
EXPECT_EQ(OK, factory->getDescriptors(&FX_IID_AEC_, &descs));
static constexpr uint32_t delayValue = 0x20;
for (const auto& desc : descs) {
- ASSERT_EQ(0, std::memcmp(&desc.type, &FX_IID_AEC_, sizeof(FX_IID_AEC_)));
+ ASSERT_EQ(0, std::memcmp(&desc.type, &FX_IID_AEC_, sizeof(effect_uuid_t)));
sp<EffectHalInterface> interface;
EXPECT_EQ(OK, factory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
1 /* deviceId */, &interface));
@@ -133,7 +135,6 @@
uint32_t type = AEC_PARAM_ECHO_DELAY, value = delayValue;
param->psize = sizeof(type);
param->vsize = sizeof(value);
- //EXPECT_EQ(1, 0) << param->psize << " " << param->vsize;
EffectParamWriter writer(*param);
EXPECT_EQ(OK, writer.writeToParameter(&type)) << writer.toString();
EXPECT_EQ(OK, writer.writeToValue(&value)) << writer.toString();
@@ -141,24 +142,24 @@
uint32_t replySize = sizeof(reply);
EXPECT_EQ(OK, interface->command(EFFECT_CMD_INIT, 0, nullptr, &replySize, &reply));
EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_PARAM, (uint32_t)writer.getTotalSize(),
- param, &replySize, &reply));
+ param, &replySize, &reply)) << writer.toString();
EXPECT_EQ(replySize, sizeof(reply));
EXPECT_EQ(OK, reply);
effect_param_t* responseParam = (effect_param_t*)testResponseBuffer;
param->psize = sizeof(type);
param->vsize = sizeof(value);
- EffectParamWriter response(*param);
- EXPECT_EQ(OK, response.writeToParameter(&type)) << response.toString();
- replySize = response.getTotalSize();
+ EffectParamWriter request(*param);
+ EXPECT_EQ(OK, request.writeToParameter(&type)) << request.toString();
+ replySize = request.getTotalSize();
EXPECT_EQ(OK, interface->command(EFFECT_CMD_GET_PARAM, (uint32_t)writer.getTotalSize(),
param, &replySize, responseParam));
- EXPECT_EQ(replySize, response.getTotalSize());
- EXPECT_EQ(OK, response.readFromValue(&value));
- EXPECT_EQ(delayValue, value);
+ EffectParamReader response(*responseParam);
+ EXPECT_EQ(replySize, response.getTotalSize()) << response.toString();
+ EXPECT_EQ(OK, response.readFromValue(&value)) << response.toString();
+ EXPECT_EQ(delayValue, value) << response.toString();
}
}
-
// TODO: b/263986405 Add multi-thread testing
} // namespace android
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
index 64f51c3..8ed579b 100644
--- a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
@@ -67,7 +67,7 @@
}
RetCode HapticGeneratorContext::setHgHapticScales(
- const std::vector<HapticGenerator::HapticScale> hapticScales) {
+ const std::vector<HapticGenerator::HapticScale>& hapticScales) {
std::lock_guard lg(mMutex);
for (auto hapticScale : hapticScales) {
mParams.mHapticScales.insert_or_assign(hapticScale.id, hapticScale.scale);
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
index dc43feb..a0a0a4c 100644
--- a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
@@ -69,7 +69,7 @@
RetCode disable();
void reset();
- RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale> hapticScales);
+ RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale>& hapticScales);
std::vector<HapticGenerator::HapticScale> getHgHapticScales();
RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo);
diff --git a/media/libheadtracking/HeadTrackingProcessor.cpp b/media/libheadtracking/HeadTrackingProcessor.cpp
index 101b825..6b62004 100644
--- a/media/libheadtracking/HeadTrackingProcessor.cpp
+++ b/media/libheadtracking/HeadTrackingProcessor.cpp
@@ -97,7 +97,7 @@
mModeSelector.setScreenStable(mWorldToScreenTimestamp.value(), screenStable);
// Whenever the screen is unstable, recenter the head pose.
if (!screenStable) {
- recenter(true, false);
+ recenter(true, false, "calculate: screen movement");
}
mScreenHeadFusion.setWorldToScreenPose(mWorldToScreenTimestamp.value(),
worldToLogicalScreen);
@@ -109,7 +109,7 @@
// Auto-recenter.
bool headStable = mHeadStillnessDetector.calculate(timestamp);
if (headStable || !screenStable) {
- recenter(true, false);
+ recenter(true, false, "calculate: head movement");
worldToHead = mHeadPoseBias.getOutput();
}
@@ -139,16 +139,16 @@
HeadTrackingMode getActualMode() const override { return mModeSelector.getActualMode(); }
- void recenter(bool recenterHead, bool recenterScreen) override {
+ void recenter(bool recenterHead, bool recenterScreen, std::string source) override {
if (recenterHead) {
mHeadPoseBias.recenter();
mHeadStillnessDetector.reset();
- mLocalLog.log("recenter Head");
+ mLocalLog.log("recenter Head from %s", source.c_str());
}
if (recenterScreen) {
mScreenPoseBias.recenter();
mScreenStillnessDetector.reset();
- mLocalLog.log("recenter Screen");
+ mLocalLog.log("recenter Screen from %s", source.c_str());
}
// If a sensor being recentered is included in the current mode, apply rate limiting to
diff --git a/media/libheadtracking/include/media/HeadTrackingProcessor.h b/media/libheadtracking/include/media/HeadTrackingProcessor.h
index 8ef8ab0..b4c78a0 100644
--- a/media/libheadtracking/include/media/HeadTrackingProcessor.h
+++ b/media/libheadtracking/include/media/HeadTrackingProcessor.h
@@ -95,7 +95,8 @@
/**
* This causes the current poses for both the head and/or screen to be considered "center".
*/
- virtual void recenter(bool recenterHead = true, bool recenterScreen = true) = 0;
+ virtual void recenter(
+ bool recenterHead = true, bool recenterScreen = true, std::string source = "") = 0;
/**
* Dump HeadTrackingProcessor parameters under caller lock.
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index ab1cf69..590a7b7 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -384,7 +384,6 @@
export_shared_lib_headers: [
"libaudioclient",
"libbinder",
- "libandroidicu",
//"libsonivox",
"libmedia_omx",
"framework-permission-aidl-cpp",
diff --git a/media/libmedia/include/media/CharacterEncodingDetector.h b/media/libmedia/include/media/CharacterEncodingDetector.h
index 62564b1..2acc868 100644
--- a/media/libmedia/include/media/CharacterEncodingDetector.h
+++ b/media/libmedia/include/media/CharacterEncodingDetector.h
@@ -21,9 +21,12 @@
#include "StringArray.h"
-#include "unicode/ucnv.h"
-#include "unicode/ucsdet.h"
-#include "unicode/ustring.h"
+/** Declare opaque structures from ICU4C. */
+struct UConverter;
+typedef struct UConverter UConverter;
+
+struct UCharsetMatch;
+typedef struct UCharsetMatch UCharsetMatch;
namespace android {
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index ccd3a54..32e40c3 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -301,7 +301,6 @@
"libstagefright_codecbase",
"libstagefright_foundation",
"libstagefright_omx_utils",
- "libRScpp",
"libhidlallocatorutils",
"libhidlbase",
"libhidlmemory",
@@ -318,7 +317,6 @@
"libstagefright_esds",
"libstagefright_color_conversion",
"libyuv_static",
- "libstagefright_mediafilter",
"libstagefright_webm",
"libstagefright_timedtext",
"libogg",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index a1ada4f..7237bb2 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -75,7 +75,6 @@
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaFilter.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/SurfaceUtils.h>
@@ -1580,8 +1579,6 @@
} else if (name.startsWithIgnoreCase("omx.")) {
// at this time only ACodec specifies a mime type.
return new ACodec;
- } else if (name.startsWithIgnoreCase("android.filter.")) {
- return new MediaFilter;
} else {
return NULL;
}
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
deleted file mode 100644
index e6d59ad..0000000
--- a/media/libstagefright/filters/Android.bp
+++ /dev/null
@@ -1,52 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
-}
-
-cc_library_static {
- name: "libstagefright_mediafilter",
-
- srcs: [
- "ColorConvert.cpp",
- "GraphicBufferListener.cpp",
- "IntrinsicBlurFilter.cpp",
- "MediaFilter.cpp",
- "RSFilter.cpp",
- "SaturationFilter.cpp",
- "saturationARGB.rscript",
- "SimpleFilter.cpp",
- "ZeroFilter.cpp",
- ],
-
- export_include_dirs: [
- "include",
- ],
-
- local_include_dirs: [
- "include/filters",
- ],
-
- cflags: [
- "-Wno-multichar",
- "-Werror",
- "-Wall",
- ],
-
- header_libs: [
- "libmediadrm_headers",
- ],
-
- shared_libs: [
- "libgui",
- "libmedia",
- "libhidlmemory",
- ],
-
- sanitize: {
- cfi: true,
- },
-}
diff --git a/media/libstagefright/filters/ColorConvert.cpp b/media/libstagefright/filters/ColorConvert.cpp
deleted file mode 100644
index a8d5dd2..0000000
--- a/media/libstagefright/filters/ColorConvert.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2014 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 "ColorConvert.h"
-
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-namespace android {
-
-void YUVToRGB(
- int32_t y, int32_t u, int32_t v,
- int32_t* r, int32_t* g, int32_t* b) {
- y -= 16;
- u -= 128;
- v -= 128;
-
- *b = 1192 * y + 2066 * u;
- *g = 1192 * y - 833 * v - 400 * u;
- *r = 1192 * y + 1634 * v;
-
- *r = min(262143, max(0, *r));
- *g = min(262143, max(0, *g));
- *b = min(262143, max(0, *b));
-
- *r >>= 10;
- *g >>= 10;
- *b >>= 10;
-}
-
-void convertYUV420spToARGB(
- uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
- uint8_t *dest) {
- const int32_t bytes_per_pixel = 2;
-
- for (int32_t i = 0; i < height; i++) {
- for (int32_t j = 0; j < width; j++) {
- int32_t y = *(pY + i * width + j);
- int32_t u = *(pUV + (i/2) * width + bytes_per_pixel * (j/2));
- int32_t v = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1);
-
- int32_t r, g, b;
- YUVToRGB(y, u, v, &r, &g, &b);
-
- *dest++ = 0xFF;
- *dest++ = r;
- *dest++ = g;
- *dest++ = b;
- }
- }
-}
-
-void convertYUV420spToRGB888(
- uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
- uint8_t *dest) {
- const int32_t bytes_per_pixel = 2;
-
- for (int32_t i = 0; i < height; i++) {
- for (int32_t j = 0; j < width; j++) {
- int32_t y = *(pY + i * width + j);
- int32_t u = *(pUV + (i/2) * width + bytes_per_pixel * (j/2));
- int32_t v = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1);
-
- int32_t r, g, b;
- YUVToRGB(y, u, v, &r, &g, &b);
-
- *dest++ = r;
- *dest++ = g;
- *dest++ = b;
- }
- }
-}
-
-// HACK - not even slightly optimized
-// TODO: remove when RGBA support is added to SoftwareRenderer
-void convertRGBAToARGB(
- uint8_t *src, int32_t width, int32_t height, uint32_t stride,
- uint8_t *dest) {
- for (int32_t i = 0; i < height; ++i) {
- for (int32_t j = 0; j < width; ++j) {
- uint8_t r = *src++;
- uint8_t g = *src++;
- uint8_t b = *src++;
- uint8_t a = *src++;
- *dest++ = a;
- *dest++ = r;
- *dest++ = g;
- *dest++ = b;
- }
- src += (stride - width) * 4;
- }
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/GraphicBufferListener.cpp b/media/libstagefright/filters/GraphicBufferListener.cpp
deleted file mode 100644
index db061c1..0000000
--- a/media/libstagefright/filters/GraphicBufferListener.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2014 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 "GraphicBufferListener"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-
-#include <gui/BufferItem.h>
-#include <utils/String8.h>
-
-#include "GraphicBufferListener.h"
-
-namespace android {
-
-status_t GraphicBufferListener::init(
- const sp<AMessage> ¬ify,
- size_t bufferWidth, size_t bufferHeight, size_t bufferCount) {
- mNotify = notify;
-
- String8 name("GraphicBufferListener");
- BufferQueue::createBufferQueue(&mProducer, &mConsumer);
- mConsumer->setConsumerName(name);
- mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
- mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
-
- status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
- if (err != NO_ERROR) {
- ALOGE("Unable to set BQ max acquired buffer count to %zu: %d",
- bufferCount, err);
- return err;
- }
-
- wp<BufferQueue::ConsumerListener> listener =
- static_cast<BufferQueue::ConsumerListener*>(this);
- sp<BufferQueue::ProxyConsumerListener> proxy =
- new BufferQueue::ProxyConsumerListener(listener);
-
- err = mConsumer->consumerConnect(proxy, false);
- if (err != NO_ERROR) {
- ALOGE("Error connecting to BufferQueue: %s (%d)",
- strerror(-err), err);
- return err;
- }
-
- ALOGV("init() successful.");
-
- return OK;
-}
-
-void GraphicBufferListener::onFrameAvailable(const BufferItem& /* item */) {
- ALOGV("onFrameAvailable() called");
-
- {
- Mutex::Autolock autoLock(mMutex);
- mNumFramesAvailable++;
- }
-
- sp<AMessage> notify = mNotify->dup();
- mNotify->setWhat(kWhatFrameAvailable);
- mNotify->post();
-}
-
-void GraphicBufferListener::onBuffersReleased() {
- ALOGV("onBuffersReleased() called");
- // nothing to do
-}
-
-void GraphicBufferListener::onSidebandStreamChanged() {
- ALOGW("GraphicBufferListener cannot consume sideband streams.");
- // nothing to do
-}
-
-BufferItem GraphicBufferListener::getBufferItem() {
- BufferItem item;
-
- {
- Mutex::Autolock autoLock(mMutex);
- if (mNumFramesAvailable <= 0) {
- ALOGE("getBuffer() called with no frames available");
- return item;
- }
- mNumFramesAvailable--;
- }
-
- status_t err = mConsumer->acquireBuffer(&item, 0);
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- // shouldn't happen, since we track num frames available
- ALOGE("frame was not available");
- item.mSlot = -1;
- return item;
- } else if (err != OK) {
- ALOGE("acquireBuffer returned err=%d", err);
- item.mSlot = -1;
- return item;
- }
-
- // Wait for it to become available.
- err = item.mFence->waitForever("GraphicBufferListener::getBufferItem");
- if (err != OK) {
- ALOGW("failed to wait for buffer fence: %d", err);
- // keep going
- }
-
- // If this is the first time we're seeing this buffer, add it to our
- // slot table.
- if (item.mGraphicBuffer != NULL) {
- ALOGV("setting mBufferSlot %d", item.mSlot);
- mBufferSlot[item.mSlot] = item.mGraphicBuffer;
- }
-
- return item;
-}
-
-sp<GraphicBuffer> GraphicBufferListener::getBuffer(BufferItem item) {
- sp<GraphicBuffer> buf;
- if (item.mSlot < 0 || item.mSlot >= BufferQueue::NUM_BUFFER_SLOTS) {
- ALOGE("getBuffer() received invalid BufferItem: mSlot==%d", item.mSlot);
- return buf;
- }
-
- buf = mBufferSlot[item.mSlot];
- CHECK(buf.get() != NULL);
-
- return buf;
-}
-
-status_t GraphicBufferListener::releaseBuffer(BufferItem item) {
- if (item.mSlot < 0 || item.mSlot >= BufferQueue::NUM_BUFFER_SLOTS) {
- ALOGE("getBuffer() received invalid BufferItem: mSlot==%d", item.mSlot);
- return ERROR_OUT_OF_RANGE;
- }
-
- mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/IntrinsicBlurFilter.cpp b/media/libstagefright/filters/IntrinsicBlurFilter.cpp
deleted file mode 100644
index e00afd9..0000000
--- a/media/libstagefright/filters/IntrinsicBlurFilter.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2014 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 "IntrinsicBlurFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "IntrinsicBlurFilter.h"
-
-namespace android {
-
-status_t IntrinsicBlurFilter::configure(const sp<AMessage> &msg) {
- status_t err = SimpleFilter::configure(msg);
- if (err != OK) {
- return err;
- }
-
- if (!msg->findString("cacheDir", &mCacheDir)) {
- ALOGE("Failed to find cache directory in config message.");
- return NAME_NOT_FOUND;
- }
-
- return OK;
-}
-
-status_t IntrinsicBlurFilter::start() {
- // TODO: use a single RS context object for entire application
- mRS = new RSC::RS();
-
- if (!mRS->init(mCacheDir.c_str())) {
- ALOGE("Failed to initialize RenderScript context.");
- return NO_INIT;
- }
-
- // 32-bit elements for ARGB8888
- RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
- RSC::Type::Builder tb(mRS, e);
- tb.setX(mWidth);
- tb.setY(mHeight);
- RSC::sp<const RSC::Type> t = tb.create();
-
- mAllocIn = RSC::Allocation::createTyped(mRS, t);
- mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
- mBlur = RSC::ScriptIntrinsicBlur::create(mRS, e);
- mBlur->setRadius(mBlurRadius);
- mBlur->setInput(mAllocIn);
-
- return OK;
-}
-
-void IntrinsicBlurFilter::reset() {
- mBlur.clear();
- mAllocOut.clear();
- mAllocIn.clear();
- mRS.clear();
-}
-
-status_t IntrinsicBlurFilter::setParameters(const sp<AMessage> &msg) {
- sp<AMessage> params;
- CHECK(msg->findMessage("params", ¶ms));
-
- float blurRadius;
- if (params->findFloat("blur-radius", &blurRadius)) {
- mBlurRadius = blurRadius;
- }
-
- return OK;
-}
-
-status_t IntrinsicBlurFilter::processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
- mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
- mBlur->forEach(mAllocOut);
- mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
deleted file mode 100644
index c7baa73..0000000
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Copyright (C) 2014 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 "MediaFilter"
-
-#include <inttypes.h>
-#include <utils/Trace.h>
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <media/stagefright/BufferProducerWrapper.h>
-#include <media/stagefright/MediaCodecConstants.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaFilter.h>
-
-#include <media/MediaCodecBuffer.h>
-
-#include <gui/BufferItem.h>
-
-#include "ColorConvert.h"
-#include "GraphicBufferListener.h"
-#include "IntrinsicBlurFilter.h"
-#include "RSFilter.h"
-#include "SaturationFilter.h"
-#include "ZeroFilter.h"
-
-namespace android {
-
-class MediaFilter::BufferChannel : public BufferChannelBase {
-public:
- BufferChannel(const sp<AMessage> &in, const sp<AMessage> &out)
- : mInputBufferFilled(in), mOutputBufferDrained(out) {
- }
-
- ~BufferChannel() override = default;
-
- // BufferChannelBase
-
- status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override {
- sp<AMessage> msg = mInputBufferFilled->dup();
- msg->setObject("buffer", buffer);
- msg->post();
- return OK;
- }
-
- status_t queueSecureInputBuffer(
- const sp<MediaCodecBuffer> &,
- bool,
- const uint8_t *,
- const uint8_t *,
- CryptoPlugin::Mode,
- CryptoPlugin::Pattern,
- const CryptoPlugin::SubSample *,
- size_t,
- AString *) override {
- return INVALID_OPERATION;
- }
-
- status_t renderOutputBuffer(
- const sp<MediaCodecBuffer> &buffer, int64_t /* timestampNs */) override {
- sp<AMessage> msg = mOutputBufferDrained->dup();
- msg->setObject("buffer", buffer);
- msg->post();
- return OK;
- }
-
- status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override {
- if (FindBufferIndex(&mInputBuffers, buffer) >= 0) {
- sp<AMessage> msg = mInputBufferFilled->dup();
- msg->setObject("buffer", buffer);
- msg->post();
- return OK;
- }
- sp<AMessage> msg = mOutputBufferDrained->dup();
- msg->setObject("buffer", buffer);
- msg->post();
- return OK;
- }
-
- void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
- if (!array) {
- return;
- }
- array->clear();
- array->appendVector(mInputBuffers);
- }
-
- void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
- if (!array) {
- return;
- }
- array->clear();
- array->appendVector(mOutputBuffers);
- }
-
- // For MediaFilter
-
- void fillThisBuffer(const sp<MediaCodecBuffer> &buffer) {
- ssize_t index = FindBufferIndex(&mInputBuffers, buffer);
- mCallback->onInputBufferAvailable(index, buffer);
- }
-
- void drainThisBuffer(const sp<MediaCodecBuffer> &buffer, int flags) {
- ssize_t index = FindBufferIndex(&mOutputBuffers, buffer);
- buffer->meta()->setInt32("flags", flags);
- mCallback->onOutputBufferAvailable(index, buffer);
- }
-
- template <class T>
- void setInputBuffers(T begin, T end) {
- mInputBuffers.clear();
- for (T it = begin; it != end; ++it) {
- mInputBuffers.push_back(it->mData);
- }
- }
-
- template <class T>
- void setOutputBuffers(T begin, T end) {
- mOutputBuffers.clear();
- for (T it = begin; it != end; ++it) {
- mOutputBuffers.push_back(it->mData);
- }
- }
-
-private:
- sp<AMessage> mInputBufferFilled;
- sp<AMessage> mOutputBufferDrained;
- Vector<sp<MediaCodecBuffer>> mInputBuffers;
- Vector<sp<MediaCodecBuffer>> mOutputBuffers;
-
- static ssize_t FindBufferIndex(
- Vector<sp<MediaCodecBuffer>> *array, const sp<MediaCodecBuffer> &buffer) {
- for (size_t i = 0; i < array->size(); ++i) {
- if (array->itemAt(i) == buffer) {
- return i;
- }
- }
- return -1;
- }
-};
-
-// parameter: number of input and output buffers
-static const size_t kBufferCountActual = 4;
-
-MediaFilter::MediaFilter()
- : mState(UNINITIALIZED),
- mGeneration(0),
- mGraphicBufferListener(NULL) {
-}
-
-MediaFilter::~MediaFilter() {
-}
-
-//////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////
-
-std::shared_ptr<BufferChannelBase> MediaFilter::getBufferChannel() {
- if (!mBufferChannel) {
- mBufferChannel = std::make_shared<BufferChannel>(
- new AMessage(kWhatInputBufferFilled, this),
- new AMessage(kWhatOutputBufferDrained, this));
- }
- return mBufferChannel;
-}
-
-void MediaFilter::initiateAllocateComponent(const sp<AMessage> &msg) {
- msg->setWhat(kWhatAllocateComponent);
- msg->setTarget(this);
- msg->post();
-}
-
-void MediaFilter::initiateConfigureComponent(const sp<AMessage> &msg) {
- msg->setWhat(kWhatConfigureComponent);
- msg->setTarget(this);
- msg->post();
-}
-
-void MediaFilter::initiateCreateInputSurface() {
- (new AMessage(kWhatCreateInputSurface, this))->post();
-}
-
-void MediaFilter::initiateSetInputSurface(
- const sp<PersistentSurface> & /* surface */) {
- ALOGW("initiateSetInputSurface() unsupported");
-}
-
-void MediaFilter::initiateStart() {
- (new AMessage(kWhatStart, this))->post();
-}
-
-void MediaFilter::initiateShutdown(bool keepComponentAllocated) {
- sp<AMessage> msg = new AMessage(kWhatShutdown, this);
- msg->setInt32("keepComponentAllocated", keepComponentAllocated);
- msg->post();
-}
-
-void MediaFilter::signalFlush() {
- (new AMessage(kWhatFlush, this))->post();
-}
-
-void MediaFilter::signalResume() {
- (new AMessage(kWhatResume, this))->post();
-}
-
-// nothing to do
-void MediaFilter::signalRequestIDRFrame() {
- return;
-}
-
-void MediaFilter::signalSetParameters(const sp<AMessage> ¶ms) {
- sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
- msg->setMessage("params", params);
- msg->post();
-}
-
-void MediaFilter::signalEndOfInputStream() {
- (new AMessage(kWhatSignalEndOfInputStream, this))->post();
-}
-
-void MediaFilter::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatAllocateComponent:
- {
- onAllocateComponent(msg);
- break;
- }
- case kWhatConfigureComponent:
- {
- onConfigureComponent(msg);
- break;
- }
- case kWhatStart:
- {
- onStart();
- break;
- }
- case kWhatProcessBuffers:
- {
- processBuffers();
- break;
- }
- case kWhatInputBufferFilled:
- {
- onInputBufferFilled(msg);
- break;
- }
- case kWhatOutputBufferDrained:
- {
- onOutputBufferDrained(msg);
- break;
- }
- case kWhatShutdown:
- {
- onShutdown(msg);
- break;
- }
- case kWhatFlush:
- {
- onFlush();
- break;
- }
- case kWhatResume:
- {
- // nothing to do
- break;
- }
- case kWhatSetParameters:
- {
- onSetParameters(msg);
- break;
- }
- case kWhatCreateInputSurface:
- {
- onCreateInputSurface();
- break;
- }
- case GraphicBufferListener::kWhatFrameAvailable:
- {
- onInputFrameAvailable();
- break;
- }
- case kWhatSignalEndOfInputStream:
- {
- onSignalEndOfInputStream();
- break;
- }
- default:
- {
- ALOGE("Message not handled:\n%s", msg->debugString().c_str());
- break;
- }
- }
-}
-
-//////////////////// HELPER FUNCTIONS //////////////////////////////////////////
-
-void MediaFilter::signalProcessBuffers() {
- (new AMessage(kWhatProcessBuffers, this))->post();
-}
-
-void MediaFilter::signalError(status_t error) {
- mCallback->onError(error, ACTION_CODE_FATAL);
-}
-
-status_t MediaFilter::allocateBuffersOnPort(OMX_U32 portIndex) {
- CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
- const bool isInput = portIndex == kPortIndexInput;
- const size_t bufferSize = isInput ? mMaxInputSize : mMaxOutputSize;
-
- CHECK(mBuffers[portIndex].isEmpty());
-
- ALOGV("Allocating %zu buffers of size %zu on %s port",
- kBufferCountActual, bufferSize,
- isInput ? "input" : "output");
-
- // trigger output format change
- sp<AMessage> outputFormat = mOutputFormat->dup();
- for (size_t i = 0; i < kBufferCountActual; ++i) {
- BufferInfo info;
- info.mStatus = BufferInfo::OWNED_BY_US;
- info.mBufferID = i;
- info.mGeneration = mGeneration;
- info.mOutputFlags = 0;
- info.mData = new MediaCodecBuffer(
- isInput ? mInputFormat : outputFormat,
- new ABuffer(bufferSize));
- info.mData->meta()->setInt64("timeUs", 0);
-
- mBuffers[portIndex].push_back(info);
-
- if (!isInput) {
- mAvailableOutputBuffers.push(
- &mBuffers[portIndex].editItemAt(i));
- }
- }
- if (isInput) {
- mBufferChannel->setInputBuffers(
- mBuffers[portIndex].begin(), mBuffers[portIndex].end());
- } else {
- mBufferChannel->setOutputBuffers(
- mBuffers[portIndex].begin(), mBuffers[portIndex].end());
- }
-
- return OK;
-}
-
-MediaFilter::BufferInfo* MediaFilter::findBuffer(
- uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
- ssize_t *index) {
- for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
- BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
-
- if (info->mData == buffer) {
- if (index != NULL) {
- *index = i;
- }
- return info;
- }
- }
-
- TRESPASS();
-
- return NULL;
-}
-
-void MediaFilter::postFillThisBuffer(BufferInfo *info) {
- ALOGV("postFillThisBuffer on buffer %d", info->mBufferID);
- if (mPortEOS[kPortIndexInput]) {
- return;
- }
-
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
-
- info->mGeneration = mGeneration;
-
- info->mData->meta()->clear();
-
- sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, this);
- reply->setInt32("buffer-id", info->mBufferID);
-
- info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
-
- mBufferChannel->fillThisBuffer(info->mData);
-}
-
-void MediaFilter::postDrainThisBuffer(BufferInfo *info) {
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
-
- info->mGeneration = mGeneration;
-
- sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
- reply->setInt32("buffer-id", info->mBufferID);
-
- mBufferChannel->drainThisBuffer(info->mData, info->mOutputFlags);
-
- info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
-}
-
-void MediaFilter::postEOS() {
- mCallback->onEos(ERROR_END_OF_STREAM);
-
- ALOGV("Sent kWhatEOS.");
-}
-
-void MediaFilter::requestFillEmptyInput() {
- if (mPortEOS[kPortIndexInput]) {
- return;
- }
-
- for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) {
- BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i);
-
- if (info->mStatus == BufferInfo::OWNED_BY_US) {
- postFillThisBuffer(info);
- }
- }
-}
-
-void MediaFilter::processBuffers() {
- if (mAvailableInputBuffers.empty() || mAvailableOutputBuffers.empty()) {
- ALOGV("Skipping process (buffers unavailable)");
- return;
- }
-
- if (mPortEOS[kPortIndexOutput]) {
- // TODO notify caller of queueInput error when it is supported
- // in MediaCodec
- ALOGW("Tried to process a buffer after EOS.");
- return;
- }
-
- BufferInfo *inputInfo = mAvailableInputBuffers[0];
- mAvailableInputBuffers.removeAt(0);
- BufferInfo *outputInfo = mAvailableOutputBuffers[0];
- mAvailableOutputBuffers.removeAt(0);
-
- status_t err;
- err = mFilter->processBuffers(inputInfo->mData, outputInfo->mData);
- if (err != (status_t)OK) {
- outputInfo->mData->meta()->setInt32("err", err);
- }
-
- int64_t timeUs;
- CHECK(inputInfo->mData->meta()->findInt64("timeUs", &timeUs));
- outputInfo->mData->meta()->setInt64("timeUs", timeUs);
- outputInfo->mOutputFlags = 0;
- int32_t eos = 0;
- if (inputInfo->mData->meta()->findInt32("eos", &eos) && eos != 0) {
- outputInfo->mOutputFlags |= BUFFER_FLAG_END_OF_STREAM;
- mPortEOS[kPortIndexOutput] = true;
- outputInfo->mData->meta()->setInt32("eos", eos);
- postEOS();
- ALOGV("Output stream saw EOS.");
- }
-
- ALOGV("Processed input buffer %u [%zu], output buffer %u [%zu]",
- inputInfo->mBufferID, inputInfo->mData->size(),
- outputInfo->mBufferID, outputInfo->mData->size());
-
- if (mGraphicBufferListener != NULL) {
- delete inputInfo;
- } else {
- postFillThisBuffer(inputInfo);
- }
- postDrainThisBuffer(outputInfo);
-
- // prevent any corner case where buffers could get stuck in queue
- signalProcessBuffers();
-}
-
-void MediaFilter::onAllocateComponent(const sp<AMessage> &msg) {
- CHECK_EQ(mState, UNINITIALIZED);
-
- CHECK(msg->findString("componentName", &mComponentName));
- const char* name = mComponentName.c_str();
- if (!strcasecmp(name, "android.filter.zerofilter")) {
- mFilter = new ZeroFilter;
- } else if (!strcasecmp(name, "android.filter.saturation")) {
- mFilter = new SaturationFilter;
- } else if (!strcasecmp(name, "android.filter.intrinsicblur")) {
- mFilter = new IntrinsicBlurFilter;
- } else if (!strcasecmp(name, "android.filter.RenderScript")) {
- mFilter = new RSFilter;
- } else {
- ALOGE("Unrecognized filter name: %s", name);
- signalError(NAME_NOT_FOUND);
- return;
- }
-
- mCallback->onComponentAllocated(mComponentName.c_str());
- mState = INITIALIZED;
- ALOGV("Handled kWhatAllocateComponent.");
-}
-
-void MediaFilter::onConfigureComponent(const sp<AMessage> &msg) {
- // TODO: generalize to allow audio filters as well as video
-
- CHECK_EQ(mState, INITIALIZED);
-
- // get params - at least mime, width & height
- AString mime;
- CHECK(msg->findString("mime", &mime));
- if (strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) {
- ALOGE("Bad mime: %s", mime.c_str());
- signalError(BAD_VALUE);
- return;
- }
-
- CHECK(msg->findInt32("width", &mWidth));
- CHECK(msg->findInt32("height", &mHeight));
- if (!msg->findInt32("stride", &mStride)) {
- mStride = mWidth;
- }
- if (!msg->findInt32("slice-height", &mSliceHeight)) {
- mSliceHeight = mHeight;
- }
-
- mMaxInputSize = mWidth * mHeight * 4; // room for ARGB8888
- int32_t maxInputSize;
- if (msg->findInt32("max-input-size", &maxInputSize)
- && (size_t)maxInputSize > mMaxInputSize) {
- mMaxInputSize = maxInputSize;
- }
-
- if (!msg->findInt32("color-format", &mColorFormatIn)) {
- // default to OMX_COLOR_Format32bitARGB8888
- mColorFormatIn = OMX_COLOR_Format32bitARGB8888;
- msg->setInt32("color-format", mColorFormatIn);
- }
- mColorFormatOut = mColorFormatIn;
-
- mMaxOutputSize = mWidth * mHeight * 4; // room for ARGB8888
-
- AString cacheDir;
- if (!msg->findString("cacheDir", &cacheDir)) {
- ALOGE("Failed to find cache directory in config message.");
- signalError(NAME_NOT_FOUND);
- return;
- }
-
- status_t err;
- err = mFilter->configure(msg);
- if (err != (status_t)OK) {
- ALOGE("Failed to configure filter component, err %d", err);
- signalError(err);
- return;
- }
-
- mInputFormat = new AMessage();
- mInputFormat->setString("mime", mime.c_str());
- mInputFormat->setInt32("stride", mStride);
- mInputFormat->setInt32("slice-height", mSliceHeight);
- mInputFormat->setInt32("color-format", mColorFormatIn);
- mInputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
- mInputFormat->setInt32("width", mWidth);
- mInputFormat->setInt32("height", mHeight);
-
- mOutputFormat = new AMessage();
- mOutputFormat->setString("mime", mime.c_str());
- mOutputFormat->setInt32("stride", mStride);
- mOutputFormat->setInt32("slice-height", mSliceHeight);
- mOutputFormat->setInt32("color-format", mColorFormatOut);
- mOutputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
- mOutputFormat->setInt32("width", mWidth);
- mOutputFormat->setInt32("height", mHeight);
- mOutputFormat->setInt32("using-sw-renderer", 1);
-
- mCallback->onComponentConfigured(mInputFormat, mOutputFormat);
- mState = CONFIGURED;
- ALOGV("Handled kWhatConfigureComponent.");
-}
-
-void MediaFilter::onStart() {
- CHECK_EQ(mState, CONFIGURED);
-
- allocateBuffersOnPort(kPortIndexInput);
-
- allocateBuffersOnPort(kPortIndexOutput);
-
- mCallback->onStartCompleted();
-
- status_t err = mFilter->start();
- if (err != (status_t)OK) {
- ALOGE("Failed to start filter component, err %d", err);
- signalError(err);
- return;
- }
-
- mPortEOS[kPortIndexInput] = false;
- mPortEOS[kPortIndexOutput] = false;
- mInputEOSResult = OK;
- mState = STARTED;
-
- requestFillEmptyInput();
- ALOGV("Handled kWhatStart.");
-}
-
-void MediaFilter::onInputBufferFilled(const sp<AMessage> &msg) {
- sp<RefBase> obj;
- CHECK(msg->findObject("buffer", &obj));
- sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
- ssize_t index = -1;
- BufferInfo *info = findBuffer(kPortIndexInput, buffer, &index);
-
- if (mState != STARTED) {
- // we're not running, so we'll just keep that buffer...
- info->mStatus = BufferInfo::OWNED_BY_US;
- return;
- }
-
- if (info->mGeneration != mGeneration) {
- ALOGV("Caught a stale input buffer [index %zd]", index);
- // buffer is stale (taken before a flush/shutdown) - repost it
- CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
- postFillThisBuffer(info);
- return;
- }
-
- CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
- info->mStatus = BufferInfo::OWNED_BY_US;
-
- int32_t err = OK;
- bool eos = false;
-
- int32_t isCSD;
- if (buffer != NULL && buffer->meta()->findInt32("csd", &isCSD)
- && isCSD != 0) {
- // ignore codec-specific data buffers
- ALOGW("MediaFilter received a codec-specific data buffer");
- postFillThisBuffer(info);
- return;
- }
-
- int32_t tmp;
- if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
- eos = true;
- err = ERROR_END_OF_STREAM;
- }
-
- mAvailableInputBuffers.push_back(info);
- processBuffers();
-
- if (eos) {
- mPortEOS[kPortIndexInput] = true;
- mInputEOSResult = err;
- }
-
- ALOGV("Handled kWhatInputBufferFilled. [index %zd]", index);
-}
-
-void MediaFilter::onOutputBufferDrained(const sp<AMessage> &msg) {
- sp<RefBase> obj;
- CHECK(msg->findObject("buffer", &obj));
- sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
- ssize_t index = -1;
- BufferInfo *info = findBuffer(kPortIndexOutput, buffer, &index);
-
- if (mState != STARTED) {
- // we're not running, so we'll just keep that buffer...
- info->mStatus = BufferInfo::OWNED_BY_US;
- return;
- }
-
- if (info->mGeneration != mGeneration) {
- ALOGV("Caught a stale output buffer [index %zd]", index);
- // buffer is stale (taken before a flush/shutdown) - keep it
- CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
- return;
- }
-
- CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
- info->mStatus = BufferInfo::OWNED_BY_US;
-
- mAvailableOutputBuffers.push_back(info);
-
- processBuffers();
-
- ALOGV("Handled kWhatOutputBufferDrained. [index %zd]", index);
-}
-
-void MediaFilter::onShutdown(const sp<AMessage> &msg) {
- mGeneration++;
-
- if (mState != UNINITIALIZED) {
- mFilter->reset();
- }
-
- int32_t keepComponentAllocated;
- CHECK(msg->findInt32("keepComponentAllocated", &keepComponentAllocated));
- if (!keepComponentAllocated || mState == UNINITIALIZED) {
- mState = UNINITIALIZED;
- } else {
- mState = INITIALIZED;
- }
-
- if (keepComponentAllocated) {
- mCallback->onStopCompleted();
- } else {
- mCallback->onReleaseCompleted();
- }
-}
-
-void MediaFilter::onFlush() {
- mGeneration++;
-
- mAvailableInputBuffers.clear();
- for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) {
- BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i);
- info->mStatus = BufferInfo::OWNED_BY_US;
- }
- mAvailableOutputBuffers.clear();
- for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
- BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
- info->mStatus = BufferInfo::OWNED_BY_US;
- mAvailableOutputBuffers.push_back(info);
- }
-
- mPortEOS[kPortIndexInput] = false;
- mPortEOS[kPortIndexOutput] = false;
- mInputEOSResult = OK;
-
- mCallback->onFlushCompleted();
- ALOGV("Posted kWhatFlushCompleted");
-
- // MediaCodec returns all input buffers after flush, so in
- // onInputBufferFilled we call postFillThisBuffer on them
-}
-
-void MediaFilter::onSetParameters(const sp<AMessage> &msg) {
- CHECK(mState != STARTED);
-
- status_t err = mFilter->setParameters(msg);
- if (err != (status_t)OK) {
- ALOGE("setParameters returned err %d", err);
- }
-}
-
-void MediaFilter::onCreateInputSurface() {
- CHECK(mState == CONFIGURED);
-
- mGraphicBufferListener = new GraphicBufferListener;
-
- sp<AMessage> notify = new AMessage();
- notify->setTarget(this);
- status_t err = mGraphicBufferListener->init(
- notify, mStride, mSliceHeight, kBufferCountActual);
-
- if (err != OK) {
- ALOGE("Failed to init mGraphicBufferListener: %d", err);
- signalError(err);
- return;
- }
-
- mCallback->onInputSurfaceCreated(
- nullptr, nullptr,
- new BufferProducerWrapper(
- mGraphicBufferListener->getIGraphicBufferProducer()));
-}
-
-void MediaFilter::onInputFrameAvailable() {
- BufferItem item = mGraphicBufferListener->getBufferItem();
- sp<GraphicBuffer> buf = mGraphicBufferListener->getBuffer(item);
-
- // get pointer to graphic buffer
- void* bufPtr;
- buf->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &bufPtr);
-
- // HACK - there is no OMX_COLOR_FORMATTYPE value for RGBA, so the format
- // conversion is hardcoded until we add this.
- // TODO: check input format and convert only if necessary
- // copy RGBA graphic buffer into temporary ARGB input buffer
- BufferInfo *inputInfo = new BufferInfo;
- inputInfo->mData = new MediaCodecBuffer(
- mInputFormat, new ABuffer(buf->getWidth() * buf->getHeight() * 4));
- ALOGV("Copying surface data into temp buffer.");
- convertRGBAToARGB(
- (uint8_t*)bufPtr, buf->getWidth(), buf->getHeight(),
- buf->getStride(), inputInfo->mData->data());
- inputInfo->mBufferID = item.mSlot;
- inputInfo->mGeneration = mGeneration;
- inputInfo->mOutputFlags = 0;
- inputInfo->mStatus = BufferInfo::OWNED_BY_US;
- inputInfo->mData->meta()->setInt64("timeUs", item.mTimestamp / 1000);
-
- mAvailableInputBuffers.push_back(inputInfo);
-
- mGraphicBufferListener->releaseBuffer(item);
-
- signalProcessBuffers();
-}
-
-void MediaFilter::onSignalEndOfInputStream() {
- // if using input surface, need to send an EOS output buffer
- if (mGraphicBufferListener != NULL) {
- Vector<BufferInfo> *outputBufs = &mBuffers[kPortIndexOutput];
- BufferInfo* eosBuf;
- bool foundBuf = false;
- for (size_t i = 0; i < kBufferCountActual; i++) {
- eosBuf = &outputBufs->editItemAt(i);
- if (eosBuf->mStatus == BufferInfo::OWNED_BY_US) {
- foundBuf = true;
- break;
- }
- }
-
- if (!foundBuf) {
- ALOGE("onSignalEndOfInputStream failed to find an output buffer");
- return;
- }
-
- eosBuf->mOutputFlags = BUFFER_FLAG_END_OF_STREAM;
- eosBuf->mGeneration = mGeneration;
- eosBuf->mData->setRange(0, 0);
- postDrainThisBuffer(eosBuf);
- ALOGV("Posted EOS on output buffer %u", eosBuf->mBufferID);
- }
-
- mPortEOS[kPortIndexOutput] = true;
- mCallback->onSignaledInputEOS(OK);
-
- ALOGV("Output stream saw EOS.");
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/RSFilter.cpp b/media/libstagefright/filters/RSFilter.cpp
deleted file mode 100644
index 225a375..0000000
--- a/media/libstagefright/filters/RSFilter.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2014 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 "RSFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "RSFilter.h"
-
-namespace android {
-
-RSFilter::RSFilter() {
-
-}
-
-RSFilter::~RSFilter() {
-
-}
-
-status_t RSFilter::configure(const sp<AMessage> &msg) {
- status_t err = SimpleFilter::configure(msg);
- if (err != OK) {
- return err;
- }
-
- if (!msg->findString("cacheDir", &mCacheDir)) {
- ALOGE("Failed to find cache directory in config message.");
- return NAME_NOT_FOUND;
- }
-
- sp<RenderScriptWrapper> wrapper;
- if (!msg->findObject("rs-wrapper", (sp<RefBase>*)&wrapper)) {
- ALOGE("Failed to find RenderScriptWrapper in config message.");
- return NAME_NOT_FOUND;
- }
-
- mRS = wrapper->mContext;
- mCallback = wrapper->mCallback;
-
- return OK;
-}
-
-status_t RSFilter::start() {
- // 32-bit elements for ARGB8888
- RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
- RSC::Type::Builder tb(mRS, e);
- tb.setX(mWidth);
- tb.setY(mHeight);
- RSC::sp<const RSC::Type> t = tb.create();
-
- mAllocIn = RSC::Allocation::createTyped(mRS, t);
- mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
- return OK;
-}
-
-void RSFilter::reset() {
- mCallback.clear();
- mAllocOut.clear();
- mAllocIn.clear();
- mRS.clear();
-}
-
-status_t RSFilter::setParameters(const sp<AMessage> &msg) {
- return mCallback->handleSetParameters(msg);
-}
-
-status_t RSFilter::processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
- mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
- mCallback->processBuffers(mAllocIn.get(), mAllocOut.get());
- mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/SaturationFilter.cpp b/media/libstagefright/filters/SaturationFilter.cpp
deleted file mode 100644
index 0a1df05..0000000
--- a/media/libstagefright/filters/SaturationFilter.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2014 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 "SaturationFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "SaturationFilter.h"
-
-namespace android {
-
-status_t SaturationFilter::configure(const sp<AMessage> &msg) {
- status_t err = SimpleFilter::configure(msg);
- if (err != OK) {
- return err;
- }
-
- if (!msg->findString("cacheDir", &mCacheDir)) {
- ALOGE("Failed to find cache directory in config message.");
- return NAME_NOT_FOUND;
- }
-
- return OK;
-}
-
-status_t SaturationFilter::start() {
- // TODO: use a single RS context object for entire application
- mRS = new RSC::RS();
-
- if (!mRS->init(mCacheDir.c_str())) {
- ALOGE("Failed to initialize RenderScript context.");
- return NO_INIT;
- }
-
- // 32-bit elements for ARGB8888
- RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
- RSC::Type::Builder tb(mRS, e);
- tb.setX(mWidth);
- tb.setY(mHeight);
- RSC::sp<const RSC::Type> t = tb.create();
-
- mAllocIn = RSC::Allocation::createTyped(mRS, t);
- mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
- mScript = new ScriptC_saturationARGB(mRS);
-
- mScript->set_gSaturation(mSaturation);
-
- return OK;
-}
-
-void SaturationFilter::reset() {
- mScript.clear();
- mAllocOut.clear();
- mAllocIn.clear();
- mRS.clear();
-}
-
-status_t SaturationFilter::setParameters(const sp<AMessage> &msg) {
- sp<AMessage> params;
- CHECK(msg->findMessage("params", ¶ms));
-
- float saturation;
- if (params->findFloat("saturation", &saturation)) {
- mSaturation = saturation;
- }
-
- return OK;
-}
-
-status_t SaturationFilter::processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
- mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
- mScript->forEach_root(mAllocIn, mAllocOut);
- mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/SimpleFilter.cpp b/media/libstagefright/filters/SimpleFilter.cpp
deleted file mode 100644
index 6c1ca2c..0000000
--- a/media/libstagefright/filters/SimpleFilter.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 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 <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-status_t SimpleFilter::configure(const sp<AMessage> &msg) {
- CHECK(msg->findInt32("width", &mWidth));
- CHECK(msg->findInt32("height", &mHeight));
- if (!msg->findInt32("stride", &mStride)) {
- mStride = mWidth;
- }
- if (!msg->findInt32("slice-height", &mSliceHeight)) {
- mSliceHeight = mHeight;
- }
- CHECK(msg->findInt32("color-format", &mColorFormatIn));
- mColorFormatOut = mColorFormatIn;
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/ZeroFilter.cpp b/media/libstagefright/filters/ZeroFilter.cpp
deleted file mode 100644
index 74b94b7..0000000
--- a/media/libstagefright/filters/ZeroFilter.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2014 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 "ZeroFilter"
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "ZeroFilter.h"
-
-namespace android {
-
-status_t ZeroFilter::setParameters(const sp<AMessage> &msg) {
- sp<AMessage> params;
- CHECK(msg->findMessage("params", ¶ms));
-
- int32_t invert;
- if (params->findInt32("invert", &invert)) {
- mInvertData = (invert != 0);
- }
-
- return OK;
-}
-
-status_t ZeroFilter::processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
- // assuming identical input & output buffers, since we're a copy filter
- if (mInvertData) {
- uint32_t* src = (uint32_t*)srcBuffer->data();
- uint32_t* dest = (uint32_t*)outBuffer->data();
- for (size_t i = 0; i < srcBuffer->size() / 4; ++i) {
- *(dest++) = *(src++) ^ 0xFFFFFFFF;
- }
- } else {
- memcpy(outBuffer->data(), srcBuffer->data(), srcBuffer->size());
- }
- outBuffer->setRange(0, srcBuffer->size());
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/filters/include/filters/ColorConvert.h b/media/libstagefright/filters/include/filters/ColorConvert.h
deleted file mode 100644
index 13faa02..0000000
--- a/media/libstagefright/filters/include/filters/ColorConvert.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 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 COLOR_CONVERT_H_
-#define COLOR_CONVERT_H_
-
-#include <inttypes.h>
-
-namespace android {
-
-void YUVToRGB(
- int32_t y, int32_t u, int32_t v,
- int32_t* r, int32_t* g, int32_t* b);
-
-void convertYUV420spToARGB(
- uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
- uint8_t *dest);
-
-void convertYUV420spToRGB888(
- uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
- uint8_t *dest);
-
-// TODO: remove when RGBA support is added to SoftwareRenderer
-void convertRGBAToARGB(
- uint8_t *src, int32_t width, int32_t height, uint32_t stride,
- uint8_t *dest);
-
-} // namespace android
-
-#endif // COLOR_CONVERT_H_
diff --git a/media/libstagefright/filters/include/filters/GraphicBufferListener.h b/media/libstagefright/filters/include/filters/GraphicBufferListener.h
deleted file mode 100644
index 586bf65..0000000
--- a/media/libstagefright/filters/include/filters/GraphicBufferListener.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 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 GRAPHIC_BUFFER_LISTENER_H_
-#define GRAPHIC_BUFFER_LISTENER_H_
-
-#include <gui/BufferQueue.h>
-
-namespace android {
-
-struct AMessage;
-
-struct GraphicBufferListener : public BufferQueue::ConsumerListener {
-public:
- GraphicBufferListener() {};
-
- status_t init(
- const sp<AMessage> ¬ify,
- size_t bufferWidth, size_t bufferHeight, size_t bufferCount);
-
- virtual void onFrameAvailable(const BufferItem& item);
- virtual void onBuffersReleased();
- virtual void onSidebandStreamChanged();
-
- // Returns the handle to the producer side of the BufferQueue. Buffers
- // queued on this will be received by GraphicBufferListener.
- sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
- return mProducer;
- }
-
- BufferItem getBufferItem();
- sp<GraphicBuffer> getBuffer(BufferItem item);
- status_t releaseBuffer(BufferItem item);
-
- enum {
- kWhatFrameAvailable = 'frav',
- };
-
-private:
- sp<AMessage> mNotify;
- size_t mNumFramesAvailable;
-
- mutable Mutex mMutex;
-
- // Our BufferQueue interfaces. mProducer is passed to the producer through
- // getIGraphicBufferProducer, and mConsumer is used internally to retrieve
- // the buffers queued by the producer.
- sp<IGraphicBufferProducer> mProducer;
- sp<IGraphicBufferConsumer> mConsumer;
-
- // Cache of GraphicBuffers from the buffer queue.
- sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS];
-};
-
-} // namespace android
-
-#endif // GRAPHIC_BUFFER_LISTENER_H
diff --git a/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h b/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h
deleted file mode 100644
index a2aabfa..0000000
--- a/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2014 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 INTRINSIC_BLUR_FILTER_H_
-#define INTRINSIC_BLUR_FILTER_H_
-
-#include "RenderScript.h"
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct IntrinsicBlurFilter : public SimpleFilter {
-public:
- IntrinsicBlurFilter() : mBlurRadius(1.f) {};
-
- virtual status_t configure(const sp<AMessage> &msg);
- virtual status_t start();
- virtual void reset();
- virtual status_t setParameters(const sp<AMessage> &msg);
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
- virtual ~IntrinsicBlurFilter() {};
-
-private:
- AString mCacheDir;
- RSC::sp<RSC::RS> mRS;
- RSC::sp<RSC::Allocation> mAllocIn;
- RSC::sp<RSC::Allocation> mAllocOut;
- RSC::sp<RSC::ScriptIntrinsicBlur> mBlur;
- float mBlurRadius;
-};
-
-} // namespace android
-
-#endif // INTRINSIC_BLUR_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/RSFilter.h b/media/libstagefright/filters/include/filters/RSFilter.h
deleted file mode 100644
index 3326284..0000000
--- a/media/libstagefright/filters/include/filters/RSFilter.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 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 RS_FILTER_H_
-#define RS_FILTER_H_
-
-#include <media/stagefright/RenderScriptWrapper.h>
-#include <RenderScript.h>
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct AString;
-
-struct RSFilter : public SimpleFilter {
-public:
- RSFilter();
-
- virtual status_t configure(const sp<AMessage> &msg);
- virtual status_t start();
- virtual void reset();
- virtual status_t setParameters(const sp<AMessage> &msg);
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
- virtual ~RSFilter();
-
-private:
- AString mCacheDir;
- sp<RenderScriptWrapper::RSFilterCallback> mCallback;
- RSC::sp<RSC::RS> mRS;
- RSC::sp<RSC::Allocation> mAllocIn;
- RSC::sp<RSC::Allocation> mAllocOut;
-};
-
-} // namespace android
-
-#endif // RS_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/SaturationFilter.h b/media/libstagefright/filters/include/filters/SaturationFilter.h
deleted file mode 100644
index 317e469..0000000
--- a/media/libstagefright/filters/include/filters/SaturationFilter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 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 SATURATION_FILTER_H_
-#define SATURATION_FILTER_H_
-
-#include <RenderScript.h>
-
-#include "ScriptC_saturationARGB.h"
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct SaturationFilter : public SimpleFilter {
-public:
- SaturationFilter() : mSaturation(1.f) {};
-
- virtual status_t configure(const sp<AMessage> &msg);
- virtual status_t start();
- virtual void reset();
- virtual status_t setParameters(const sp<AMessage> &msg);
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
- virtual ~SaturationFilter() {};
-
-private:
- AString mCacheDir;
- RSC::sp<RSC::RS> mRS;
- RSC::sp<RSC::Allocation> mAllocIn;
- RSC::sp<RSC::Allocation> mAllocOut;
- RSC::sp<ScriptC_saturationARGB> mScript;
- float mSaturation;
-};
-
-} // namespace android
-
-#endif // SATURATION_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/SimpleFilter.h b/media/libstagefright/filters/include/filters/SimpleFilter.h
deleted file mode 100644
index a3c2d76..0000000
--- a/media/libstagefright/filters/include/filters/SimpleFilter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 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 SIMPLE_FILTER_H_
-#define SIMPLE_FILTER_H_
-
-#include <stdint.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-struct AMessage;
-class MediaCodecBuffer;
-
-struct SimpleFilter : public RefBase {
-public:
- SimpleFilter() : mWidth(0), mHeight(0), mStride(0), mSliceHeight(0),
- mColorFormatIn(0), mColorFormatOut(0) {};
-
- virtual status_t configure(const sp<AMessage> &msg);
-
- virtual status_t start() = 0;
- virtual void reset() = 0;
- virtual status_t setParameters(const sp<AMessage> &msg) = 0;
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) = 0;
-
-protected:
- int32_t mWidth, mHeight;
- int32_t mStride, mSliceHeight;
- int32_t mColorFormatIn, mColorFormatOut;
-
- virtual ~SimpleFilter() {};
-};
-
-} // namespace android
-
-#endif // SIMPLE_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/ZeroFilter.h b/media/libstagefright/filters/include/filters/ZeroFilter.h
deleted file mode 100644
index f941cc8..0000000
--- a/media/libstagefright/filters/include/filters/ZeroFilter.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 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 ZERO_FILTER_H_
-#define ZERO_FILTER_H_
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct ZeroFilter : public SimpleFilter {
-public:
- ZeroFilter() : mInvertData(false) {};
-
- virtual status_t start() { return OK; };
- virtual void reset() {};
- virtual status_t setParameters(const sp<AMessage> &msg);
- virtual status_t processBuffers(
- const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
- virtual ~ZeroFilter() {};
-
-private:
- bool mInvertData;
-};
-
-} // namespace android
-
-#endif // ZERO_FILTER_H_
diff --git a/media/libstagefright/filters/saturation.rscript b/media/libstagefright/filters/saturation.rscript
deleted file mode 100644
index 2c867ac..0000000
--- a/media/libstagefright/filters/saturation.rscript
+++ /dev/null
@@ -1,40 +0,0 @@
-// Sample script for RGB888 support (compare to saturationARGB.rs)
-/*
- * Copyright (C) 2014 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 version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-// global variables (parameters accessible to application code)
-float gSaturation = 1.0f;
-
-void root(const uchar3 *v_in, uchar3 *v_out) {
- // scale 0-255 uchar to 0-1.0 float
- float3 in = {v_in->r * 0.003921569f, v_in->g * 0.003921569f,
- v_in->b * 0.003921569f};
-
- // apply saturation filter
- float3 result = dot(in, gMonoMult);
- result = mix(result, in, gSaturation);
-
- // convert to uchar, copied from rsPackColorTo8888
- v_out->x = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
- v_out->y = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
- v_out->z = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/media/libstagefright/filters/saturationARGB.rscript b/media/libstagefright/filters/saturationARGB.rscript
deleted file mode 100644
index 1de9dd8..0000000
--- a/media/libstagefright/filters/saturationARGB.rscript
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 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 version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-// global variables (parameters accessible to application code)
-float gSaturation = 1.0f;
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
- v_out->x = v_in->x; // don't modify A
-
- // get RGB, scale 0-255 uchar to 0-1.0 float
- float3 rgb = {v_in->y * 0.003921569f, v_in->z * 0.003921569f,
- v_in->w * 0.003921569f};
-
- // apply saturation filter
- float3 result = dot(rgb, gMonoMult);
- result = mix(result, rgb, gSaturation);
-
- v_out->y = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
- v_out->z = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
- v_out->w = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/media/libstagefright/include/media/stagefright/MediaFilter.h b/media/libstagefright/include/media/stagefright/MediaFilter.h
deleted file mode 100644
index 1255e0f..0000000
--- a/media/libstagefright/include/media/stagefright/MediaFilter.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 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 MEDIA_FILTER_H_
-#define MEDIA_FILTER_H_
-
-#include <media/stagefright/CodecBase.h>
-
-namespace android {
-
-struct GraphicBufferListener;
-struct SimpleFilter;
-
-struct MediaFilter : public CodecBase {
- MediaFilter();
-
- virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
- virtual void initiateAllocateComponent(const sp<AMessage> &msg);
- virtual void initiateConfigureComponent(const sp<AMessage> &msg);
- virtual void initiateCreateInputSurface();
- virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface);
-
- virtual void initiateStart();
- virtual void initiateShutdown(bool keepComponentAllocated = false);
-
- virtual void signalFlush();
- virtual void signalResume();
-
- virtual void signalRequestIDRFrame();
- virtual void signalSetParameters(const sp<AMessage> &msg);
- virtual void signalEndOfInputStream();
-
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-protected:
- virtual ~MediaFilter();
-
-private:
- struct BufferInfo {
- enum Status {
- OWNED_BY_US,
- OWNED_BY_UPSTREAM,
- };
-
- uint32_t mBufferID;
- int32_t mGeneration;
- int32_t mOutputFlags;
- Status mStatus;
-
- sp<MediaCodecBuffer> mData;
- };
-
- class BufferChannel;
-
- enum State {
- UNINITIALIZED,
- INITIALIZED,
- CONFIGURED,
- STARTED,
- };
-
- enum {
- kWhatInputBufferFilled = 'inpF',
- kWhatOutputBufferDrained = 'outD',
- kWhatShutdown = 'shut',
- kWhatFlush = 'flus',
- kWhatResume = 'resm',
- kWhatAllocateComponent = 'allo',
- kWhatConfigureComponent = 'conf',
- kWhatCreateInputSurface = 'cisf',
- kWhatSignalEndOfInputStream = 'eois',
- kWhatStart = 'star',
- kWhatSetParameters = 'setP',
- kWhatProcessBuffers = 'proc',
- };
-
- enum {
- kPortIndexInput = 0,
- kPortIndexOutput = 1
- };
-
- // member variables
- AString mComponentName;
- State mState;
- status_t mInputEOSResult;
- int32_t mWidth, mHeight;
- int32_t mStride, mSliceHeight;
- int32_t mColorFormatIn, mColorFormatOut;
- size_t mMaxInputSize, mMaxOutputSize;
- int32_t mGeneration;
- sp<AMessage> mInputFormat;
- sp<AMessage> mOutputFormat;
-
- Vector<BufferInfo> mBuffers[2];
- Vector<BufferInfo*> mAvailableInputBuffers;
- Vector<BufferInfo*> mAvailableOutputBuffers;
- bool mPortEOS[2];
-
- sp<SimpleFilter> mFilter;
- sp<GraphicBufferListener> mGraphicBufferListener;
-
- std::shared_ptr<BufferChannel> mBufferChannel;
-
- // helper functions
- void signalProcessBuffers();
- void signalError(status_t error);
-
- status_t allocateBuffersOnPort(OMX_U32 portIndex);
- BufferInfo *findBuffer(
- uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
- ssize_t *index = NULL);
- void postFillThisBuffer(BufferInfo *info);
- void postDrainThisBuffer(BufferInfo *info);
- void postEOS();
- void requestFillEmptyInput();
- void processBuffers();
-
- void onAllocateComponent(const sp<AMessage> &msg);
- void onConfigureComponent(const sp<AMessage> &msg);
- void onStart();
- void onInputBufferFilled(const sp<AMessage> &msg);
- void onOutputBufferDrained(const sp<AMessage> &msg);
- void onShutdown(const sp<AMessage> &msg);
- void onFlush();
- void onSetParameters(const sp<AMessage> &msg);
- void onCreateInputSurface();
- void onInputFrameAvailable();
- void onSignalEndOfInputStream();
-
- DISALLOW_EVIL_CONSTRUCTORS(MediaFilter);
-};
-
-} // namespace android
-
-#endif // MEDIA_FILTER_H_
diff --git a/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h b/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h
deleted file mode 100644
index b42649e..0000000
--- a/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2014 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 RENDERSCRIPT_WRAPPER_H_
-#define RENDERSCRIPT_WRAPPER_H_
-
-#include <RenderScript.h>
-
-namespace android {
-
-struct RenderScriptWrapper : public RefBase {
-public:
- struct RSFilterCallback : public RefBase {
- public:
- // called by RSFilter to process each input buffer
- virtual status_t processBuffers(
- RSC::Allocation* inBuffer,
- RSC::Allocation* outBuffer) = 0;
-
- virtual status_t handleSetParameters(const sp<AMessage> &msg) = 0;
- };
-
- sp<RSFilterCallback> mCallback;
- RSC::sp<RSC::RS> mContext;
-};
-
-} // namespace android
-
-#endif // RENDERSCRIPT_WRAPPER_H_
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index bc5b5db..5dbcb33 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -100,14 +100,50 @@
}
}
+void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
+ const std::vector<playback_track_metadata_v7_t>& metadataVec) {
+ std::lock_guard _laf(mAudioFlinger.mLock);
+ std::lock_guard _l(mLock);
+ auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
+ if (!activeMelPatchId) {
+ ALOGV("%s stream handle %d does not have an active patch", __func__, streamHandle);
+ return;
+ }
+
+ bool shouldActivateCsd = false;
+ for (const auto& metadata : metadataVec) {
+ if (metadata.base.usage == AUDIO_USAGE_GAME || metadata.base.usage == AUDIO_USAGE_MEDIA) {
+ shouldActivateCsd = true;
+ }
+ }
+
+ auto activeMelPatchIt = mActiveMelPatches.find(activeMelPatchId.value());
+ if (activeMelPatchIt != mActiveMelPatches.end()
+ && shouldActivateCsd != activeMelPatchIt->second.csdActive) {
+ if (activeMelPatchIt->second.csdActive) {
+ ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle);
+ stopMelComputationForPatch_l(activeMelPatchIt->second);
+ } else {
+ ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle);
+ startMelComputationForActivePatch_l(activeMelPatchIt->second);
+ }
+ activeMelPatchIt->second.csdActive = shouldActivateCsd;
+ }
+}
+
void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
const PatchPanel::Patch& patch) {
+ if (useHalSoundDoseInterface()) {
+ ALOGV("%s using HAL sound dose, ignore new patch", __func__);
+ return;
+ }
+
ALOGV("%s: handle %d mHalHandle %d device sink %08x",
__func__, handle, patch.mHalHandle,
patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
if (patch.mAudioPatch.num_sources == 0
|| patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
- ALOGW("%s: patch does not contain any mix sources", __func__);
+ ALOGV("%s: patch does not contain any mix sources", __func__);
return;
}
@@ -122,49 +158,46 @@
AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
patch.mAudioPatch.sinks[i].ext.device.address};
mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
-
- bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
- {
- std::lock_guard _l(mLock);
- useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
- }
- if (!useHalSoundDoseInterface) {
- startMelComputationForNewPatch(streamHandle, deviceId);
- }
}
}
+ std::lock_guard _afl(mAudioFlinger.mLock);
std::lock_guard _l(mLock);
- mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
+ ALOGV("%s add patch handle %d to active devices", __func__, handle);
+ startMelComputationForActivePatch_l(newPatch);
+ newPatch.csdActive = true;
+ mActiveMelPatches[handle] = newPatch;
}
-void AudioFlinger::MelReporter::startMelComputationForNewPatch(
- audio_io_handle_t streamHandle, audio_port_handle_t deviceId) {
- // Start the MEL calculation in the PlaybackThread
- std::lock_guard _lAf(mAudioFlinger.mLock);
- auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
- if (thread != nullptr) {
+void AudioFlinger::MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch) {
+ auto thread = mAudioFlinger.checkPlaybackThread_l(patch.streamHandle);
+ if (thread == nullptr) {
+ ALOGE("%s cannot find thread for stream handle %d", __func__, patch.streamHandle);
+ return;
+ }
+
+ for (const auto& deviceHandle : patch.deviceHandles) {
+ ++mActiveDevices[deviceHandle];
+ ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
+ patch.streamHandle, deviceHandle, mActiveDevices[deviceHandle]);
thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
- deviceId,
- streamHandle,
+ deviceHandle,
+ patch.streamHandle,
thread->mSampleRate,
thread->mChannelCount,
thread->mFormat));
- }
+ }
}
void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
- ALOGV("%s", __func__);
-
ActiveMelPatch melPatch;
{
std::lock_guard _l(mLock);
auto patchIt = mActiveMelPatches.find(handle);
if (patchIt == mActiveMelPatches.end()) {
- ALOGW(
- "%s patch does not contain any mix sources with active MEL calculation",
- __func__);
+ ALOGV("%s patch handle %d does not contain any mix sources with active MEL calculation",
+ __func__, handle);
return;
}
@@ -172,10 +205,9 @@
mActiveMelPatches.erase(patchIt);
}
- for (const auto& deviceId : melPatch.deviceHandles) {
- mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
- }
- stopInternalMelComputationForStream(melPatch.streamHandle);
+ std::lock_guard _afl(mAudioFlinger.mLock);
+ std::lock_guard _l(mLock);
+ stopMelComputationForPatch_l(melPatch);
}
sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
@@ -191,17 +223,46 @@
mUseHalSoundDoseInterface = true;
}
-void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
- ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
+void AudioFlinger::MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch) {
+ auto thread = mAudioFlinger.checkPlaybackThread_l(patch.streamHandle);
+ ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
+ for (const auto& deviceId : patch.deviceHandles) {
+ if (mActiveDevices[deviceId] > 0) {
+ --mActiveDevices[deviceId];
+ if (mActiveDevices[deviceId] == 0) {
+ // no stream is using deviceId anymore
+ ALOGI("%s removing device %d from active CSD devices", __func__, deviceId);
+ mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
+ }
+ }
+ }
- std::lock_guard _lAf(mAudioFlinger.mLock);
- mSoundDoseManager->removeStreamProcessor(streamId);
- auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
+ mSoundDoseManager->removeStreamProcessor(patch.streamHandle);
if (thread != nullptr) {
thread->stopMelComputation();
}
}
+
+std::optional<audio_patch_handle_t> AudioFlinger::MelReporter::activePatchStreamHandle_l(
+ audio_io_handle_t streamHandle) {
+ for(const auto& patchIt : mActiveMelPatches) {
+ if (patchIt.second.streamHandle == streamHandle) {
+ return patchIt.first;
+ }
+ }
+ return std::nullopt;
+}
+
+bool AudioFlinger::MelReporter::useHalSoundDoseInterface() {
+ bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
+ {
+ std::lock_guard _l(mLock);
+ useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
+ }
+ return useHalSoundDoseInterface;
+}
+
std::string AudioFlinger::MelReporter::dump() {
std::lock_guard _l(mLock);
std::string output("\nSound Dose:\n");
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index 5e7f0cc..c1b291f 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -37,9 +37,6 @@
void onFirstRef() override;
- /** Returns true if we should compute MEL for the given device. */
- bool shouldComputeMelForDeviceType(audio_devices_t device);
-
/**
* Activates the MEL reporting from the HAL sound dose interface. If the HAL
* does not support the sound dose interface for this module, the internal MEL
@@ -73,22 +70,39 @@
const PatchPanel::Patch& patch) override;
void onReleaseAudioPatch(audio_patch_handle_t handle) override;
+ /**
+ * The new metadata can determine whether we should compute MEL for the given thread.
+ * This is the case only if one of the tracks in the thread mix is using MEDIA or GAME.
+ * Otherwise, this method will disable CSD.
+ **/
+ void updateMetadataForCsd(audio_io_handle_t streamHandle,
+ const std::vector<playback_track_metadata_v7_t>& metadataVec);
private:
- void stopInternalMelComputation();
- void stopInternalMelComputationForStream(audio_io_handle_t streamId);
+ struct ActiveMelPatch {
+ audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
+ std::vector<audio_port_handle_t> deviceHandles;
+ bool csdActive;
+ };
- void startMelComputationForNewPatch(audio_io_handle_t streamHandle,
- audio_port_handle_t deviceId);
+ /** Returns true if we should compute MEL for the given device. */
+ bool shouldComputeMelForDeviceType(audio_devices_t device);
+
+ void stopInternalMelComputation();
+
+ /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
+ void stopMelComputationForPatch_l(const ActiveMelPatch& patch);
+
+ /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
+ void startMelComputationForActivePatch_l(const ActiveMelPatch& patch);
+
+ std::optional<audio_patch_handle_t> activePatchStreamHandle_l(audio_io_handle_t streamHandle);
+
+ bool useHalSoundDoseInterface();
AudioFlinger& mAudioFlinger; // does not own the object
sp<SoundDoseManager> mSoundDoseManager;
- struct ActiveMelPatch {
- audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
- std::vector<audio_port_handle_t> deviceHandles;
- };
-
/**
* Lock for protecting the active mel patches. Do not mix with the AudioFlinger lock.
* Locking order AudioFlinger::mLock -> PatchCommandThread::mLock -> MelReporter::mLock.
@@ -96,5 +110,7 @@
std::mutex mLock;
std::unordered_map<audio_patch_handle_t, ActiveMelPatch>
mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock);
+ std::unordered_map<audio_port_handle_t, int>
+ mActiveDevices GUARDED_BY(AudioFlinger::MelReporter::mLock);
bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false;
};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d274e41..8de900e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3229,10 +3229,10 @@
item.record();
}
-void AudioFlinger::PlaybackThread::updateMetadata_l()
+AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::PlaybackThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
- return; // nothing to do
+ return {}; // nothing to do
}
StreamOutHalInterface::SourceMetadata metadata;
auto backInserter = std::back_inserter(metadata.tracks);
@@ -3241,6 +3241,9 @@
track->copyMetadataTo(backInserter);
}
sendMetadataToBackend_l(metadata);
+ MetadataUpdate change;
+ change.playbackMetadataUpdate = metadata.tracks;
+ return change;
}
void AudioFlinger::PlaybackThread::sendMetadataToBackend_l(
@@ -3478,8 +3481,10 @@
}
void AudioFlinger::PlaybackThread::stopMelComputation() {
- ALOGV("%s: stopping mel processor for thread %d", __func__, id());
- mMelProcessor = nullptr;
+ if (mMelProcessor.load() != nullptr) {
+ ALOGV("%s: stopping mel processor for thread %d", __func__, id());
+ mMelProcessor = nullptr;
+ }
}
void AudioFlinger::PlaybackThread::threadLoop_drain()
@@ -3933,6 +3938,7 @@
checkOutputStageEffects();
}
+ MetadataUpdate metadataUpdate;
{ // scope for mLock
Mutex::Autolock _l(mLock);
@@ -4034,7 +4040,7 @@
mActiveTracks.updatePowerState(this);
- updateMetadata_l();
+ metadataUpdate = updateMetadata_l();
// prevent any changes in effect chain list and in each effect chain
// during mixing and effect process as the audio buffers could be deleted
@@ -4074,6 +4080,11 @@
setHalLatencyMode_l();
} // mLock scope ends
+ if (!metadataUpdate.playbackMetadataUpdate.empty()) {
+ mAudioFlinger->mMelReporter->updateMetadataForCsd(id(),
+ metadataUpdate.playbackMetadataUpdate);
+ }
+
if (mBytesRemaining == 0) {
mCurrentWriteLength = 0;
if (mMixerStatus == MIXER_TRACKS_READY) {
@@ -4783,7 +4794,7 @@
if (configChanged) {
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
- // Force meteadata update after a route change
+ // Force metadata update after a route change
mActiveTracks.setHasChanged();
return status;
@@ -9023,10 +9034,10 @@
mSharedAudioPackageName = "";
}
-void AudioFlinger::RecordThread::updateMetadata_l()
+AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::RecordThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
- return; // nothing to do
+ return {}; // nothing to do
}
StreamInHalInterface::SinkMetadata metadata;
auto backInserter = std::back_inserter(metadata.tracks);
@@ -9034,6 +9045,9 @@
track->copyMetadataTo(backInserter);
}
mInput->stream->updateSinkMetadata(metadata);
+ MetadataUpdate change;
+ change.recordMetadataUpdate = metadata.tracks;
+ return change;
}
// destroyTrack_l() must be called with ThreadBase::mLock held
@@ -10733,10 +10747,10 @@
}
}
-void AudioFlinger::MmapPlaybackThread::updateMetadata_l()
+AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::MmapPlaybackThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
- return; // nothing to do
+ return {}; // nothing to do
}
StreamOutHalInterface::SourceMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
@@ -10752,7 +10766,11 @@
metadata.tracks.push_back(trackMetadata);
}
mOutput->stream->updateSourceMetadata(metadata);
-}
+
+ MetadataUpdate change;
+ change.playbackMetadataUpdate = metadata.tracks;
+ return change;
+};
void AudioFlinger::MmapPlaybackThread::checkSilentMode_l()
{
@@ -10860,10 +10878,10 @@
}
}
-void AudioFlinger::MmapCaptureThread::updateMetadata_l()
+AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::MmapCaptureThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
- return; // nothing to do
+ return {}; // nothing to do
}
StreamInHalInterface::SinkMetadata metadata;
for (const sp<MmapTrack> &track : mActiveTracks) {
@@ -10878,6 +10896,9 @@
metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
+ MetadataUpdate change;
+ change.recordMetadataUpdate = metadata.tracks;
+ return change;
}
void AudioFlinger::MmapCaptureThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 4ab4557..f829efc 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -607,7 +607,11 @@
void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain);
// sends the metadata of the active tracks to the HAL
- virtual void updateMetadata_l() = 0;
+ struct MetadataUpdate {
+ std::vector<playback_track_metadata_v7_t> playbackMetadataUpdate;
+ std::vector<record_track_metadata_v7_t> recordMetadataUpdate;
+ };
+ virtual MetadataUpdate updateMetadata_l() = 0;
String16 getWakeLockTag();
@@ -1277,7 +1281,7 @@
void removeTrack_l(const sp<Track>& track);
void readOutputParameters_l();
- void updateMetadata_l() final;
+ MetadataUpdate updateMetadata_l() final;
virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata);
void collectTimestamps_l();
@@ -1983,7 +1987,7 @@
status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
status_t setPreferredMicrophoneFieldDimension(float zoom);
- void updateMetadata_l() override;
+ MetadataUpdate updateMetadata_l() override;
bool fastTrackAvailable() const { return mFastTrackAvail; }
@@ -2257,7 +2261,7 @@
virtual void checkSilentMode_l();
void processVolume_l() override;
- void updateMetadata_l() override;
+ MetadataUpdate updateMetadata_l() override;
virtual void toAudioPortConfig(struct audio_port_config *config);
@@ -2290,7 +2294,7 @@
status_t exitStandby_l() REQUIRES(mLock) override;
- void updateMetadata_l() override;
+ MetadataUpdate updateMetadata_l() override;
void processVolume_l() override;
void setRecordSilenced(audio_port_handle_t portId,
bool silenced) override;
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index ad65612..6f9e11f 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -163,7 +163,7 @@
auto adt = AudioDeviceTypeAddr(type, address);
auto deviceIt = mActiveDevices.find(adt);
if (deviceIt == mActiveDevices.end()) {
- ALOGE("%s: could not find port id for device %s", __func__, adt.toString().c_str());
+ ALOGI("%s: could not find port id for device %s", __func__, adt.toString().c_str());
return AUDIO_PORT_HANDLE_NONE;
}
return deviceIt->second;
@@ -187,7 +187,6 @@
}
++activeDevice;
}
- return;
}
ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
@@ -206,7 +205,7 @@
auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
if (id == AUDIO_PORT_HANDLE_NONE) {
- ALOGW("%s: no mapped id for audio device with type %d and address %s",
+ ALOGI("%s: no mapped id for audio device with type %d and address %s",
__func__, in_audioDevice.type.type,
in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
@@ -233,7 +232,7 @@
auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
if (id == AUDIO_PORT_HANDLE_NONE) {
- ALOGW("%s: no mapped id for audio device with type %d and address %s",
+ ALOGI("%s: no mapped id for audio device with type %d and address %s",
__func__, in_audioDevice.type.type,
in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index db87ad8..c12efc3 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -176,7 +176,9 @@
std::unordered_map<audio_io_handle_t, wp<audio_utils::MelProcessor>> mActiveProcessors
GUARDED_BY(mLock);
- // map active device address and type to device id
+ // map active device address and type to device id, used also for managing the pause/resume
+ // logic for deviceId's that should not report MEL values (e.g.: do not have an active MUSIC
+ // or GAME stream).
std::map<AudioDeviceTypeAddr, audio_port_handle_t> mActiveDevices GUARDED_BY(mLock);
float mRs2Value GUARDED_BY(mLock);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 54a143c..92292e1 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -62,11 +62,24 @@
void closeOutput(sp<SwAudioOutputDescriptor> &desc);
/**
- * Try to find an output descriptor for the given attributes.
+ * Tries to find the best matching audio policy mix
*
- * @param[in] attributes to consider fowr the research of output descriptor.
- * @param[out] desc to return if an primary output could be found.
- * @param[out] secondaryDesc other desc that the audio should be routed to.
+ * @param[in] attributes to consider for the research of the audio policy mix.
+ * @param[in] config to consider for the research of the audio policy mix.
+ * @param[in] uid to consider for the research of the audio policy mix.
+ * @param[in] session to consider for the research of the audio policy mix.
+ * @param[in] flags to consider for the research of the audio policy mix.
+ * @param[in] availableOutputDevices available output devices can be use during the research
+ * of the audio policy mix
+ * @param[in] requestedDevice currently requested device that can be used determined if the
+ * matching audio policy mix should be used instead of the currently set preferred device.
+ * @param[out] primaryMix to return in case a matching audio plicy mix could be found.
+ * @param[out] secondaryMixes that audio should be routed to in case a matching
+ * secondary mixes could be found.
+ * @param[out] usePrimaryOutputFromPolicyMixes to return in case the audio policy mix
+ * should be use, including the case where the requested device is explicitly disallowed
+ * by the audio policy.
+ *
* @return OK if the request is valid
* otherwise if the request is not supported
*/
@@ -75,8 +88,11 @@
uid_t uid,
audio_session_t session,
audio_output_flags_t flags,
+ const DeviceVector &availableOutputDevices,
+ const sp<DeviceDescriptor>& requestedDevice,
sp<AudioPolicyMix> &primaryMix,
- std::vector<sp<AudioPolicyMix>> *secondaryMixes);
+ std::vector<sp<AudioPolicyMix>> *secondaryMixes,
+ bool& usePrimaryOutputFromPolicyMixes);
sp<DeviceDescriptor> getDeviceAndMixForInputSource(const audio_attributes_t& attributes,
const DeviceVector &availableDeviceTypes,
@@ -132,6 +148,13 @@
const audio_config_base_t& config,
uid_t uid,
audio_session_t session);
+ bool mixDisallowsRequestedDevice(const AudioMix* mix,
+ const sp<DeviceDescriptor>& requestedDevice,
+ const sp<DeviceDescriptor>& mixDevice,
+ const uid_t uid);
+
+ sp<DeviceDescriptor> getOutputDeviceForMix(const AudioMix* mix,
+ const DeviceVector& availableOutputDevices);
};
std::optional<std::string> extractAddressFromAudioAttributes(const audio_attributes_t& attr);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 003dcaf..ba5a6a7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "APM_AudioPolicyMix"
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#include <algorithm>
#include <iterator>
@@ -259,14 +259,25 @@
const audio_attributes_t& attributes, const audio_config_base_t& config, const uid_t uid,
const audio_session_t session,
audio_output_flags_t flags,
+ const DeviceVector &availableOutputDevices,
+ const sp<DeviceDescriptor>& requestedDevice,
sp<AudioPolicyMix> &primaryMix,
- std::vector<sp<AudioPolicyMix>> *secondaryMixes)
+ std::vector<sp<AudioPolicyMix>> *secondaryMixes,
+ bool& usePrimaryOutputFromPolicyMixes)
{
ALOGV("getOutputForAttr() querying %zu mixes:", size());
primaryMix.clear();
+ bool mixesDisallowsRequestedDevice = false;
for (size_t i = 0; i < size(); i++) {
sp<AudioPolicyMix> policyMix = itemAt(i);
const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
+ sp<DeviceDescriptor> mixDevice = getOutputDeviceForMix(policyMix.get(),
+ availableOutputDevices);
+ if (mixDisallowsRequestedDevice(policyMix.get(), requestedDevice, mixDevice, uid)) {
+ ALOGV("%s: Mix %zu: does not allows device", __func__, i);
+ mixesDisallowsRequestedDevice = true;
+ }
+
if (!primaryOutputMix && (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) {
// AAudio does not support MMAP_NO_IRQ loopback render, and there is no way with
// the current MmapStreamInterface::start to reject a specific client added to a shared
@@ -288,6 +299,11 @@
continue; // skip the mix
}
+ if (mixDevice != nullptr && mixDevice->equals(requestedDevice)) {
+ ALOGV("%s: Mix %zu: requested device mathches", __func__, i);
+ mixesDisallowsRequestedDevice = false;
+ }
+
if (primaryOutputMix) {
primaryMix = policyMix;
ALOGV("%s: Mix %zu: set primary desc", __func__, i);
@@ -298,9 +314,36 @@
}
}
}
+
+ // Explicit routing is higher priority than dynamic policy primary output, but policy may
+ // explicitly deny it
+ usePrimaryOutputFromPolicyMixes =
+ (mixesDisallowsRequestedDevice || requestedDevice == nullptr) && primaryMix != nullptr;
+
return NO_ERROR;
}
+sp<DeviceDescriptor> AudioPolicyMixCollection::getOutputDeviceForMix(const AudioMix* mix,
+ const DeviceVector& availableOutputDevices) {
+ ALOGV("%s: device (0x%x, addr=%s) forced by mix", __func__, mix->mDeviceType,
+ mix->mDeviceAddress.c_str());
+ return availableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress,
+ AUDIO_FORMAT_DEFAULT);
+}
+
+bool AudioPolicyMixCollection::mixDisallowsRequestedDevice(const AudioMix* mix,
+ const sp<DeviceDescriptor>& requestedDevice,
+ const sp<DeviceDescriptor>& mixDevice,
+ const uid_t uid) {
+ if (requestedDevice == nullptr || mixDevice == nullptr) {
+ return false;
+ }
+
+ return is_mix_disallows_preferred_device(mix->mRouteFlags)
+ && requestedDevice->equals(mixDevice)
+ && mix->hasUserIdRule(false /* match */, multiuser_get_user_id(uid));
+}
+
bool AudioPolicyMixCollection::mixMatch(const AudioMix* mix, size_t mixIndex,
const audio_attributes_t& attributes, const audio_config_base_t& config,
uid_t uid, audio_session_t session) {
@@ -361,11 +404,7 @@
for (size_t i = 0; i < size(); i++) {
if (itemAt(i)->getOutput() == output) {
// This Desc is involved in a Mix, which has the highest prio
- audio_devices_t deviceType = itemAt(i)->mDeviceType;
- String8 address = itemAt(i)->mDeviceAddress;
- ALOGV("%s: device (0x%x, addr=%s) forced by mix",
- __FUNCTION__, deviceType, address.c_str());
- return availableOutputDevices.getDevice(deviceType, address, AUDIO_FORMAT_DEFAULT);
+ return getOutputDeviceForMix(itemAt(i).get(), availableOutputDevices);
}
}
return nullptr;
@@ -568,13 +607,14 @@
break;
}
}
- if (!deviceMatch && !mix->hasMatchUserIdRule()) {
+ if (!deviceMatch && !mix->hasUserIdRule(true /*match*/)) {
// this mix doesn't go to one of the listed devices for the given userId,
// and it's not already restricting the mix on a userId,
// modify its rules to exclude the userId
- if (!mix->hasUserIdRule(false /*match*/, userId)) {
+ if (!mix->hasUserIdRule(false /* match */, userId)) {
// no need to do it again if userId is already excluded
mix->setExcludeUserId(userId);
+ mix->mRouteFlags = mix->mRouteFlags | MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE;
}
}
}
@@ -595,6 +635,10 @@
EraseCriteriaIf(mix->mCriteria, [userId](const AudioMixMatchCriterion& c) {
return c.mRule == RULE_EXCLUDE_USERID && c.mValue.mUserId == userId;
});
+
+ if (!mix->hasUserIdRule(false /* match */)) {
+ mix->mRouteFlags = mix->mRouteFlags & ~MIX_ROUTE_FLAG_DISALLOWS_PREFERRED_DEVICE;
+ }
}
return NO_ERROR;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0f2b34e..d09e426 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1168,6 +1168,8 @@
ALOGV("%s() attributes=%s stream=%s session %d selectedDeviceId %d", __func__,
toString(*resultAttr).c_str(), toString(*stream).c_str(), session, requestedPortId);
+ bool usePrimaryOutputFromPolicyMixes = false;
+
// The primary output is the explicit routing (eg. setPreferredDevice) if specified,
// otherwise, fallback to the dynamic policies, if none match, query the engine.
// Secondary outputs are always found by dynamic policies as the engine do not support them
@@ -1177,14 +1179,12 @@
.format = config->format,
};
status = mPolicyMixes.getOutputForAttr(*resultAttr, clientConfig, uid, session, *flags,
- primaryMix, secondaryMixes);
+ mAvailableOutputDevices, requestedDevice, primaryMix,
+ secondaryMixes, usePrimaryOutputFromPolicyMixes);
if (status != OK) {
return status;
}
- // Explicit routing is higher priority then any dynamic policy primary output
- bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && primaryMix != nullptr;
-
// FIXME: in case of RENDER policy, the output capabilities should be checked
if ((secondaryMixes != nullptr && !secondaryMixes->empty())
&& !audio_is_linear_pcm(config->format)) {
@@ -3916,7 +3916,8 @@
status_t status = mEngine->clearDevicesRoleForStrategy(strategy, role);
if (status != NO_ERROR) {
- ALOGV("Engine could not remove device role for strategy %d status %d",
+ ALOGW_IF(status != NAME_NOT_FOUND,
+ "Engine could not remove device role for strategy %d status %d",
strategy, status);
return status;
}
@@ -3988,10 +3989,11 @@
status_t status = mEngine->removeDevicesRoleForCapturePreset(
audioSource, role, devices);
- ALOGW_IF(status != NO_ERROR,
+ ALOGW_IF(status != NO_ERROR && status != NAME_NOT_FOUND,
"Engine could not remove devices role (%d) for capture preset %d", role, audioSource);
-
- updateInputRouting();
+ if (status == NO_ERROR) {
+ updateInputRouting();
+ }
return status;
}
@@ -4000,10 +4002,11 @@
ALOGV("%s() audioSource=%d role=%d", __func__, audioSource, role);
status_t status = mEngine->clearDevicesRoleForCapturePreset(audioSource, role);
- ALOGW_IF(status != NO_ERROR,
+ ALOGW_IF(status != NO_ERROR && status != NAME_NOT_FOUND,
"Engine could not clear devices role (%d) for capture preset %d", role, audioSource);
-
- updateInputRouting();
+ if (status == NO_ERROR) {
+ updateInputRouting();
+ }
return status;
}
@@ -6730,6 +6733,7 @@
SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs);
uint32_t maxLatency = 0;
+ bool unneededUsePrimaryOutputFromPolicyMixes = false;
std::vector<sp<SwAudioOutputDescriptor>> invalidatedOutputs;
// take into account dynamic audio policies related changes: if a client is now associated
// to a different policy mix than at creation time, invalidate corresponding stream
@@ -6744,7 +6748,9 @@
}
sp<AudioPolicyMix> primaryMix;
status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(),
- client->uid(), client->session(), client->flags(), primaryMix, nullptr);
+ client->uid(), client->session(), client->flags(), mAvailableOutputDevices,
+ nullptr /* requestedDevice */, primaryMix, nullptr /* secondaryMixes */,
+ unneededUsePrimaryOutputFromPolicyMixes);
if (status != OK) {
continue;
}
@@ -6842,13 +6848,16 @@
void AudioPolicyManager::checkSecondaryOutputs() {
PortHandleVector clientsToInvalidate;
TrackSecondaryOutputsMap trackSecondaryOutputs;
+ bool unneededUsePrimaryOutputFromPolicyMixes = false;
for (size_t i = 0; i < mOutputs.size(); i++) {
const sp<SwAudioOutputDescriptor>& outputDescriptor = mOutputs[i];
for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) {
sp<AudioPolicyMix> primaryMix;
std::vector<sp<AudioPolicyMix>> secondaryMixes;
status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(),
- client->uid(), client->session(), client->flags(), primaryMix, &secondaryMixes);
+ client->uid(), client->session(), client->flags(), mAvailableOutputDevices,
+ nullptr /* requestedDevice */, primaryMix, &secondaryMixes,
+ unneededUsePrimaryOutputFromPolicyMixes);
std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs;
for (auto &secondaryMix : secondaryMixes) {
sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput();
@@ -8282,9 +8291,11 @@
// check dynamic policies but only for primary descriptors (secondary not used for audible
// audio routing, only used for duplication for playback capture)
sp<AudioPolicyMix> policyMix;
+ bool unneededUsePrimaryOutputFromPolicyMixes = false;
status_t status = mPolicyMixes.getOutputForAttr(attr, AUDIO_CONFIG_BASE_INITIALIZER,
- 0 /*uid unknown here*/, AUDIO_SESSION_NONE, AUDIO_OUTPUT_FLAG_NONE, policyMix,
- nullptr /* secondaryMixes */);
+ 0 /*uid unknown here*/, AUDIO_SESSION_NONE, AUDIO_OUTPUT_FLAG_NONE,
+ mAvailableOutputDevices, nullptr /* requestedDevice */, policyMix,
+ nullptr /* secondaryMixes */, unneededUsePrimaryOutputFromPolicyMixes);
if (status != OK) {
return status;
}
diff --git a/services/audiopolicy/service/SpatializerPoseController.cpp b/services/audiopolicy/service/SpatializerPoseController.cpp
index 72dba3d..ab1b6f7 100644
--- a/services/audiopolicy/service/SpatializerPoseController.cpp
+++ b/services/audiopolicy/service/SpatializerPoseController.cpp
@@ -192,7 +192,7 @@
mHeadSensor = INVALID_SENSOR;
}
- mProcessor->recenter(true /* recenterHead */, false /* recenterScreen */);
+ mProcessor->recenter(true /* recenterHead */, false /* recenterScreen */, __func__);
}
void SpatializerPoseController::setScreenSensor(int32_t sensor) {
@@ -229,7 +229,7 @@
mScreenSensor = INVALID_SENSOR;
}
- mProcessor->recenter(false /* recenterHead */, true /* recenterScreen */);
+ mProcessor->recenter(false /* recenterHead */, true /* recenterScreen */, __func__);
}
void SpatializerPoseController::setDesiredMode(HeadTrackingMode mode) {
@@ -276,7 +276,7 @@
void SpatializerPoseController::recenter() {
std::lock_guard lock(mMutex);
- mProcessor->recenter();
+ mProcessor->recenter(true /* recenterHead */, true /* recenterScreen */, __func__);
}
void SpatializerPoseController::onPose(int64_t timestamp, int32_t sensor, const Pose3f& pose,
@@ -286,13 +286,13 @@
mProcessor->setWorldToHeadPose(timestamp, pose,
twist.value_or(Twist3f()) / kTicksPerSecond);
if (isNewReference) {
- mProcessor->recenter(true, false);
+ mProcessor->recenter(true, false, __func__);
}
}
if (sensor == mScreenSensor) {
mProcessor->setWorldToScreenPose(timestamp, pose);
if (isNewReference) {
- mProcessor->recenter(false, true);
+ mProcessor->recenter(false, true, __func__);
}
}
}
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 6813587..b2546d2 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -28,6 +28,7 @@
"liblog",
"libmedia_helper",
"libutils",
+ "libcutils",
"libxml2",
"framework-permission-aidl-cpp",
"libbinder",
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 3f38d01..ef829e1 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -32,6 +32,7 @@
#include <media/RecordingActivityTracker.h>
#include <utils/Log.h>
#include <utils/Vector.h>
+#include <cutils/multiuser.h>
#include "AudioPolicyInterface.h"
#include "AudioPolicyManagerTestClient.h"
@@ -51,6 +52,13 @@
return criterion;
}
+AudioMixMatchCriterion createUserIdCriterion(int userId, bool exclude = false) {
+ AudioMixMatchCriterion criterion;
+ criterion.mValue.mUserId = userId;
+ criterion.mRule = exclude ? RULE_EXCLUDE_USERID : RULE_MATCH_USERID;
+ return criterion;
+}
+
AudioMixMatchCriterion createUsageCriterion(audio_usage_t usage, bool exclude = false) {
AudioMixMatchCriterion criterion;
criterion.mValue.mUsage = usage;
@@ -2161,11 +2169,23 @@
std::string getConfigFile() override { return sCarConfig; }
static const std::string sCarConfig;
+ static const std::string sCarBusMediaOutput;
+ static const std::string sCarBusNavigationOutput;
+ static const std::string sCarRearZoneOneOutput;
+ static const std::string sCarRearZoneTwoOutput;
};
const std::string AudioPolicyManagerCarTest::sCarConfig =
AudioPolicyManagerCarTest::sExecutableDir + "test_car_ap_atmos_offload_configuration.xml";
+const std::string AudioPolicyManagerCarTest::sCarBusMediaOutput = "bus0_media_out";
+
+const std::string AudioPolicyManagerCarTest::sCarBusNavigationOutput = "bus1_navigation_out";
+
+const std::string AudioPolicyManagerCarTest::sCarRearZoneOneOutput = "bus100_audio_zone_1";
+
+const std::string AudioPolicyManagerCarTest::sCarRearZoneTwoOutput = "bus200_audio_zone_2";
+
TEST_F(AudioPolicyManagerCarTest, InitSuccess) {
// SetUp must finish with no assertions.
}
@@ -2177,9 +2197,8 @@
TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrAtmosOutputAfterRegisteringPolicyMix) {
status_t ret;
audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
- const std::string kTestBusMediaOutput = "bus0_media_out";
ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
- AUDIO_DEVICE_OUT_BUS, kTestBusMediaOutput, audioConfig);
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig);
ASSERT_EQ(NO_ERROR, ret);
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
@@ -2207,6 +2226,415 @@
ASSERT_EQ(k48000SamplingRate, outDesc->getSamplingRate());
}
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrAfterRegisteringPolicyMix) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ std::vector<AudioMixMatchCriterion> navMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput, audioConfig, navMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ audio_port_v7 mediaDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusMediaOutput, &mediaDevicePort));
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, mediaAttribute);
+
+ ASSERT_EQ(mediaDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrWithSelectedOutputAfterRegisteringPolicyMix) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ std::vector<AudioMixMatchCriterion> navMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput, audioConfig, navMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ audio_port_v7 navDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusNavigationOutput, &navDevicePort));
+ audio_port_handle_t selectedDeviceId = navDevicePort.id;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, mediaAttribute);
+
+ ASSERT_EQ(navDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrWithSelectedOutputAfterUserAffinities) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ std::vector<AudioMixMatchCriterion> navMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput, audioConfig, navMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ const AudioDeviceTypeAddr mediaOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput);
+ const AudioDeviceTypeAddrVector outputDevices = {mediaOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 0, outputDevices);
+ audio_port_v7 navDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusNavigationOutput, &navDevicePort));
+ audio_port_handle_t selectedDeviceId = navDevicePort.id;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, mediaAttribute);
+
+ ASSERT_NE(navDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrWithExcludeUserIdCriteria) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ std::vector<AudioMixMatchCriterion> navMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ /*exclude=*/ false),
+ createUserIdCriterion(/* userId */ 0, /* exclude */ true)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput, audioConfig, navMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ audio_port_v7 navDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusNavigationOutput, &navDevicePort));
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t navigationAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, navigationAttribute);
+
+ ASSERT_NE(navDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrWithSelectedOutputExcludeUserIdCriteria) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ std::vector<AudioMixMatchCriterion> navMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ /*exclude=*/ false),
+ createUserIdCriterion(0 /* userId */, /* exclude */ true)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput, audioConfig, navMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ audio_port_v7 navDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusNavigationOutput, &navDevicePort));
+ audio_port_handle_t selectedDeviceId = navDevicePort.id;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, mediaAttribute);
+
+ ASSERT_EQ(navDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest,
+ GetOutputForAttrWithMatchingMixAndSelectedOutputAfterUserAffinities) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ std::vector<AudioMixMatchCriterion> navMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput, audioConfig, navMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ const AudioDeviceTypeAddr mediaOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput);
+ const AudioDeviceTypeAddr navOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput);
+ const AudioDeviceTypeAddrVector outputDevices = {mediaOutputDevice, navOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 0, outputDevices);
+ audio_port_v7 navDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusNavigationOutput, &navDevicePort));
+ audio_port_handle_t selectedDeviceId = navDevicePort.id;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, mediaAttribute);
+
+ ASSERT_EQ(navDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest,
+ GetOutputForAttrWithNoMatchingMaxAndSelectedOutputAfterUserAffinities) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ std::vector<AudioMixMatchCriterion> navMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput, audioConfig, navMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ const AudioDeviceTypeAddr mediaOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput);
+ const AudioDeviceTypeAddr navOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput);
+ const AudioDeviceTypeAddrVector outputDevices = {mediaOutputDevice, navOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 0, outputDevices);
+ audio_port_v7 navDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusNavigationOutput, &navDevicePort));
+ audio_port_handle_t selectedDeviceId = navDevicePort.id;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t alarmAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, alarmAttribute);
+
+ ASSERT_EQ(navDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest,
+ GetOutputForAttrWithMatMixAfterUserAffinitiesForOneUser) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarRearZoneOneOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarRearZoneTwoOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ const AudioDeviceTypeAddr mediaOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput);
+ const AudioDeviceTypeAddrVector primaryZoneDevices = {mediaOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 0, primaryZoneDevices);
+ audio_port_v7 primaryZoneDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusMediaOutput, &primaryZoneDevicePort));
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+ uid_t user11AppUid = multiuser_get_uid(/* user_id */ 11, /* app_id */ 12345);
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, mediaAttribute,
+ AUDIO_SESSION_NONE, user11AppUid);
+
+ ASSERT_EQ(primaryZoneDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest,
+ GetOutputForAttrWithMatMixAfterUserAffinitiesForTwoUsers) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarRearZoneOneOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarRearZoneTwoOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ const AudioDeviceTypeAddr mediaOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput);
+ const AudioDeviceTypeAddrVector primaryZoneDevices = {mediaOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 0, primaryZoneDevices);
+ const AudioDeviceTypeAddr secondaryOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarRearZoneOneOutput);
+ const AudioDeviceTypeAddrVector secondaryZoneDevices = {secondaryOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 11, secondaryZoneDevices);
+ audio_port_v7 secondaryZoneDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarRearZoneOneOutput, &secondaryZoneDevicePort));
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+ uid_t user11AppUid = multiuser_get_uid(/* user_id */ 11, /* app_id */ 12345);
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, mediaAttribute,
+ AUDIO_SESSION_NONE, user11AppUid);
+
+ ASSERT_EQ(secondaryZoneDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest,
+ GetOutputForAttrWithMatMixAfterUserAffinitiesForThreeUsers) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarRearZoneOneOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarRearZoneTwoOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ const AudioDeviceTypeAddr mediaOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput);
+ const AudioDeviceTypeAddrVector primaryZoneDevices = {mediaOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 0, primaryZoneDevices);
+ const AudioDeviceTypeAddr secondaryOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarRearZoneOneOutput);
+ const AudioDeviceTypeAddrVector secondaryZoneDevices = {secondaryOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 11, secondaryZoneDevices);
+ const AudioDeviceTypeAddr tertiaryOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarRearZoneTwoOutput);
+ const AudioDeviceTypeAddrVector tertiaryZoneDevices = {tertiaryOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 15, tertiaryZoneDevices);
+ audio_port_v7 tertiaryZoneDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarRearZoneTwoOutput, &tertiaryZoneDevicePort));
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+ uid_t user15AppUid = multiuser_get_uid(/* user_id */ 15, /* app_id */ 12345);
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, mediaAttribute,
+ AUDIO_SESSION_NONE, user15AppUid);
+
+ ASSERT_EQ(tertiaryZoneDevicePort.id, selectedDeviceId);
+}
+
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrWithNoMatchingMix) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ std::vector<AudioMixMatchCriterion> navMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput, audioConfig, navMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ const AudioDeviceTypeAddr mediaOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusMediaOutput);
+ const AudioDeviceTypeAddr navOutputDevice(AUDIO_DEVICE_OUT_BUS, sCarBusNavigationOutput);
+ const AudioDeviceTypeAddrVector outputDevices = {mediaOutputDevice, navOutputDevice};
+ mManager->setUserIdDeviceAffinities(/* userId */ 0, outputDevices);
+ audio_port_v7 navDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusNavigationOutput, &navDevicePort));
+ audio_port_handle_t selectedDeviceId = navDevicePort.id;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t alarmAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, &output, &portId, alarmAttribute);
+
+ ASSERT_EQ(navDevicePort.id, selectedDeviceId);
+}
+
class AudioPolicyManagerTVTest : public AudioPolicyManagerTestWithConfigurationFile {
protected:
std::string getConfigFile() override { return sTvConfig; }
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 7b1759e..1c922ce 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -143,6 +143,7 @@
"libhidlbase",
"libimage_io",
"libjpeg",
+ "libjpegrecoverymap",
"libmedia_codeclist",
"libmedia_omx",
"libmemunreachable",
@@ -182,9 +183,6 @@
"libbinderthreadstateutils",
"media_permission-aidl-cpp",
"libcameraservice_device_independent",
- "libjpegrecoverymap",
- "libjpegencoder",
- "libjpegdecoder",
],
export_shared_lib_headers: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index b179372..a6fd649 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -37,6 +37,7 @@
#include <android-base/macros.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
+#include <android/permission/PermissionChecker.h>
#include <binder/ActivityManager.h>
#include <binder/AppOpsManager.h>
#include <binder/IPCThreadState.h>
@@ -81,6 +82,9 @@
namespace {
const char* kPermissionServiceName = "permission";
+ const char* kActivityServiceName = "activity";
+ const char* kSensorPrivacyServiceName = "sensor_privacy";
+ const char* kAppopsServiceName = "appops";
}; // namespace anonymous
namespace android {
@@ -167,6 +171,15 @@
return (CameraThreadState::getCallingUid() < AID_APP_START);
}
+void CameraService::onServiceRegistration(const String16& name, const sp<IBinder>&) {
+ if (name != String16(kAppopsServiceName)) {
+ return;
+ }
+
+ ALOGV("appops service registered. setting camera audio restriction");
+ mAppOps.setCameraAudioRestriction(mAudioRestriction);
+}
+
void CameraService::onFirstRef()
{
@@ -191,7 +204,19 @@
mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
mSensorPrivacyPolicy->registerSelf();
mInjectionStatusListener = new InjectionStatusListener(this);
- mAppOps.setCameraAudioRestriction(mAudioRestriction);
+
+ // appops function setCamerAudioRestriction uses getService which
+ // is blocking till the appops service is ready. To enable early
+ // boot availability for cameraservice, use checkService which is
+ // non blocking and register for notifications
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->checkService(String16(kAppopsServiceName));
+ if (!binder) {
+ sm->registerForNotifications(String16(kAppopsServiceName), this);
+ } else {
+ mAppOps.setCameraAudioRestriction(mAudioRestriction);
+ }
+
sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
if (hcs->registerAsService() != android::OK) {
// Deprecated, so it will fail to register on newer devices
@@ -667,11 +692,18 @@
broadcastTorchModeStatus(cameraId, newStatus, systemCameraKind);
}
-static bool hasPermissionsForSystemCamera(int callingPid, int callingUid,
- bool logPermissionFailure = false) {
- return checkPermission(sSystemCameraPermission, callingPid, callingUid,
- logPermissionFailure) &&
- checkPermission(sCameraPermission, callingPid, callingUid);
+static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
+ permission::PermissionChecker permissionChecker;
+ AttributionSourceState attributionSource{};
+ attributionSource.pid = callingPid;
+ attributionSource.uid = callingUid;
+ bool checkPermissionForSystemCamera = permissionChecker.checkPermissionForPreflight(
+ sSystemCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
+ != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
+ sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
+ != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ return checkPermissionForSystemCamera && checkPermissionForCamera;
}
Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
@@ -750,8 +782,14 @@
const std::vector<std::string> *deviceIds = &mNormalDeviceIdsWithoutSystemCamera;
auto callingPid = CameraThreadState::getCallingPid();
auto callingUid = CameraThreadState::getCallingUid();
- if (checkPermission(sSystemCameraPermission, callingPid, callingUid,
- /*logPermissionFailure*/false) || getpid() == callingPid) {
+ permission::PermissionChecker permissionChecker;
+ AttributionSourceState attributionSource{};
+ attributionSource.pid = callingPid;
+ attributionSource.uid = callingUid;
+ bool checkPermissionForSystemCamera = permissionChecker.checkPermissionForPreflight(
+ sSystemCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
+ != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ if (checkPermissionForSystemCamera || getpid() == callingPid) {
deviceIds = &mNormalDeviceIds;
}
if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(deviceIds->size())) {
@@ -822,9 +860,16 @@
// If it's not calling from cameraserver, check the permission only if
// android.permission.CAMERA is required. If android.permission.SYSTEM_CAMERA was needed,
// it would've already been checked in shouldRejectSystemCameraConnection.
+ permission::PermissionChecker permissionChecker;
+ AttributionSourceState attributionSource{};
+ attributionSource.pid = callingPid;
+ attributionSource.uid = callingUid;
+ bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
+ sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
+ != permission::PermissionChecker::PERMISSION_HARD_DENIED;
if ((callingPid != getpid()) &&
(deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
- !checkPermission(sCameraPermission, callingPid, callingUid)) {
+ !checkPermissionForCamera) {
res = cameraInfo->removePermissionEntries(
mCameraProviderManager->getProviderTagIdLocked(String8(cameraId).string()),
&tagsRemoved);
@@ -1258,6 +1303,9 @@
Status CameraService::validateClientPermissionsLocked(const String8& cameraId,
const String8& clientName8, int& clientUid, int& clientPid,
/*out*/int& originalClientPid) const {
+ permission::PermissionChecker permissionChecker;
+ AttributionSourceState attributionSource{};
+
int callingPid = CameraThreadState::getCallingPid();
int callingUid = CameraThreadState::getCallingUid();
@@ -1304,9 +1352,14 @@
// If it's not calling from cameraserver, check the permission if the
// device isn't a system only camera (shouldRejectSystemCameraConnection already checks for
// android.permission.SYSTEM_CAMERA for system only camera devices).
+ attributionSource.pid = clientPid;
+ attributionSource.uid = clientUid;
+ attributionSource.packageName = clientName8;
+ bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
+ sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
+ != permission::PermissionChecker::PERMISSION_HARD_DENIED;
if (callingPid != getpid() &&
- (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
- !checkPermission(sCameraPermission, clientPid, clientUid)) {
+ (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) && !checkPermissionForCamera) {
ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
"Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" without camera permission",
@@ -1695,7 +1748,7 @@
// characteristics) even if clients don't have android.permission.CAMERA. We do not want the
// same behavior for system camera devices.
if (!systemClient && systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
- !hasPermissionsForSystemCamera(cPid, cUid, /*logPermissionFailure*/true)) {
+ !hasPermissionsForSystemCamera(cPid, cUid)) {
ALOGW("Rejecting access to system only camera %s, inadequete permissions",
cameraId.c_str());
return true;
@@ -2649,7 +2702,14 @@
// Check for camera permissions
int callingPid = CameraThreadState::getCallingPid();
int callingUid = CameraThreadState::getCallingUid();
- if ((callingPid != getpid()) && !checkPermission(sCameraPermission, callingPid, callingUid)) {
+ permission::PermissionChecker permissionChecker;
+ AttributionSourceState attributionSource{};
+ attributionSource.pid = callingPid;
+ attributionSource.uid = callingUid;
+ bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
+ sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
+ != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ if ((callingPid != getpid()) && !checkPermissionForCamera) {
ALOGE("%s: pid %d doesn't have camera permissions", __FUNCTION__, callingPid);
return STATUS_ERROR(ERROR_PERMISSION_DENIED,
"android.permission.CAMERA needed to call"
@@ -2696,8 +2756,13 @@
auto clientUid = CameraThreadState::getCallingUid();
auto clientPid = CameraThreadState::getCallingPid();
- bool openCloseCallbackAllowed = checkPermission(sCameraOpenCloseListenerPermission,
- clientPid, clientUid, /*logPermissionFailure*/false);
+ permission::PermissionChecker permissionChecker;
+ AttributionSourceState attributionSource{};
+ attributionSource.uid = clientUid;
+ attributionSource.pid = clientPid;
+ bool openCloseCallbackAllowed = permissionChecker.checkPermissionForPreflight(
+ sCameraOpenCloseListenerPermission, attributionSource, String16(),
+ AppOpsManager::OP_NONE) != permission::PermissionChecker::PERMISSION_HARD_DENIED;
Mutex::Autolock lock(mServiceLock);
@@ -3792,7 +3857,7 @@
// UidPolicy
// ----------------------------------------------------------------------------
-void CameraService::UidPolicy::registerSelf() {
+void CameraService::UidPolicy::registerWithActivityManager() {
Mutex::Autolock _l(mUidLock);
if (mRegistered) return;
@@ -3809,6 +3874,27 @@
}
}
+void CameraService::UidPolicy::onServiceRegistration(const String16& name, const sp<IBinder>&) {
+ if (name != String16(kActivityServiceName)) {
+ return;
+ }
+
+ registerWithActivityManager();
+}
+
+void CameraService::UidPolicy::registerSelf() {
+ // Use check service to see if the activity service is available
+ // If not available then register for notifications, instead of blocking
+ // till the service is ready
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->checkService(String16(kActivityServiceName));
+ if (!binder) {
+ sm->registerForNotifications(String16(kActivityServiceName), this);
+ } else {
+ registerWithActivityManager();
+ }
+}
+
void CameraService::UidPolicy::unregisterSelf() {
Mutex::Autolock _l(mUidLock);
@@ -4022,7 +4108,9 @@
// ----------------------------------------------------------------------------
// SensorPrivacyPolicy
// ----------------------------------------------------------------------------
-void CameraService::SensorPrivacyPolicy::registerSelf() {
+
+void CameraService::SensorPrivacyPolicy::registerWithSensorPrivacyManager()
+{
Mutex::Autolock _l(mSensorPrivacyLock);
if (mRegistered) {
return;
@@ -4037,6 +4125,27 @@
}
}
+void CameraService::SensorPrivacyPolicy::onServiceRegistration(const String16& name,
+ const sp<IBinder>&) {
+ if (name != String16(kSensorPrivacyServiceName)) {
+ return;
+ }
+
+ registerWithSensorPrivacyManager();
+}
+
+void CameraService::SensorPrivacyPolicy::registerSelf() {
+ // Use checkservice to see if the sensor_privacy service is available
+ // If service is not available then register for notification
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->checkService(String16(kSensorPrivacyServiceName));
+ if (!binder) {
+ sm->registerForNotifications(String16(kSensorPrivacyServiceName),this);
+ } else {
+ registerWithSensorPrivacyManager();
+ }
+}
+
void CameraService::SensorPrivacyPolicy::unregisterSelf() {
Mutex::Autolock _l(mSensorPrivacyLock);
mSpm.removeSensorPrivacyListener(this);
@@ -4046,6 +4155,10 @@
}
bool CameraService::SensorPrivacyPolicy::isSensorPrivacyEnabled() {
+ if (!mRegistered) {
+ registerWithSensorPrivacyManager();
+ }
+
Mutex::Autolock _l(mSensorPrivacyLock);
return mSensorPrivacyEnabled;
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index c5671505..fb0ece5 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -71,7 +71,8 @@
public BinderService<CameraService>,
public virtual ::android::hardware::BnCameraService,
public virtual IBinder::DeathRecipient,
- public virtual CameraProviderManager::StatusListener
+ public virtual CameraProviderManager::StatusListener,
+ public virtual IServiceManager::LocalRegistrationCallback
{
friend class BinderService<CameraService>;
friend class CameraOfflineSessionClient;
@@ -101,6 +102,9 @@
// Implementation of BinderService<T>
static char const* getServiceName() { return "media.camera"; }
+ // Implementation of IServiceManager::LocalRegistrationCallback
+ virtual void onServiceRegistration(const String16& name, const sp<IBinder>& binder) override;
+
// Non-null arguments for cameraServiceProxyWrapper should be provided for
// testing purposes only.
CameraService(std::shared_ptr<CameraServiceProxyWrapper>
@@ -714,7 +718,10 @@
// Observer for UID lifecycle enforcing that UIDs in idle
// state cannot use the camera to protect user privacy.
- class UidPolicy : public BnUidObserver, public virtual IBinder::DeathRecipient {
+ class UidPolicy :
+ public BnUidObserver,
+ public virtual IBinder::DeathRecipient,
+ public virtual IServiceManager::LocalRegistrationCallback {
public:
explicit UidPolicy(sp<CameraService> service)
: mRegistered(false), mService(service) {}
@@ -739,12 +746,16 @@
void registerMonitorUid(uid_t uid);
void unregisterMonitorUid(uid_t uid);
+ // Implementation of IServiceManager::LocalRegistrationCallback
+ virtual void onServiceRegistration(const String16& name,
+ const sp<IBinder>& binder) override;
// IBinder::DeathRecipient implementation
virtual void binderDied(const wp<IBinder> &who);
private:
bool isUidActiveLocked(uid_t uid, String16 callingPackage);
int32_t getProcStateLocked(uid_t uid);
void updateOverrideUid(uid_t uid, String16 callingPackage, bool active, bool insert);
+ void registerWithActivityManager();
struct MonitoredUid {
int32_t procState;
@@ -764,7 +775,8 @@
// If sensor privacy is enabled then all apps, including those that are active, should be
// prevented from accessing the camera.
class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener,
- public virtual IBinder::DeathRecipient {
+ public virtual IBinder::DeathRecipient,
+ public virtual IServiceManager::LocalRegistrationCallback {
public:
explicit SensorPrivacyPolicy(wp<CameraService> service)
: mService(service), mSensorPrivacyEnabled(false), mRegistered(false) {}
@@ -778,6 +790,9 @@
binder::Status onSensorPrivacyChanged(int toggleType, int sensor,
bool enabled);
+ // Implementation of IServiceManager::LocalRegistrationCallback
+ virtual void onServiceRegistration(const String16& name,
+ const sp<IBinder>& binder) override;
// IBinder::DeathRecipient implementation
virtual void binderDied(const wp<IBinder> &who);
@@ -789,6 +804,7 @@
bool mRegistered;
bool hasCameraPrivacyFeature();
+ void registerWithSensorPrivacyManager();
};
sp<UidPolicy> mUidPolicy;