Merge "CCodecConfig: round frame rate instead of truncating to increase the accuracy"
diff --git a/Android.bp b/Android.bp
index 0e0ea1f..5aa2029 100644
--- a/Android.bp
+++ b/Android.bp
@@ -75,10 +75,10 @@
"av-types-aidl-cpp",
],
header_libs: [
- "libaudioclient_aidl_conversion_util",
+ "libaudio_aidl_conversion_common_util_cpp",
],
export_header_lib_headers: [
- "libaudioclient_aidl_conversion_util",
+ "libaudio_aidl_conversion_common_util_cpp",
],
host_supported: true,
vendor_available: true,
diff --git a/apex/Android.bp b/apex/Android.bp
index 570ca01..b0d7c02 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -67,13 +67,15 @@
// Use a custom AndroidManifest.xml used for API targeting.
androidManifest: ":com.android.media-androidManifest",
- // IMPORTANT: q-launched-apex-module enables the build system to make
- // sure the package compatible to Android 10 in two ways:
+ // IMPORTANT: q-launched-dcla-enabled-apex-module enables the build system to make
+ // sure the package compatible to Android 10 in two ways(if flag APEX_BUILD_FOR_PRE_S_DEVICES=1
+ // is set):
// - build the APEX package compatible to Android 10
// so that the package can be installed.
// - build artifacts (lib/javalib/bin) against Android 10 SDK
// so that the artifacts can run.
- defaults: ["q-launched-apex-module"],
+ // If the flag is not set, the package is built to be compatible with Android 12.
+ defaults: ["q-launched-dcla-enabled-apex-module"],
// Indicates that pre-installed version of this apex can be compressed.
// Whether it actually will be compressed is controlled on per-device basis.
compressible: true,
@@ -191,13 +193,15 @@
// Use a custom AndroidManifest.xml used for API targeting.
androidManifest: ":com.android.media.swcodec-androidManifest",
- // IMPORTANT: q-launched-apex-module enables the build system to make
- // sure the package compatible to Android 10 in two ways:
+ // IMPORTANT: q-launched-dcla-enabled-apex-module enables the build system to make
+ // sure the package compatible to Android 10 in two ways(if flag APEX_BUILD_FOR_PRE_S_DEVICES=1
+ // is set):
// - build the APEX package compatible to Android 10
// so that the package can be installed.
// - build artifacts (lib/javalib/bin) against Android 10 SDK
// so that the artifacts can run.
- defaults: ["q-launched-apex-module"],
+ // If the flag is not set, the package is built to be compatible with Android 12.
+ defaults: ["q-launched-dcla-enabled-apex-module"],
// Indicates that pre-installed version of this apex can be compressed.
// Whether it actually will be compressed is controlled on per-device basis.
compressible: true,
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 408d216..1e1a49d 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -35,6 +35,7 @@
"CryptoHalAidl.cpp",
"DrmUtils.cpp",
"DrmHalListener.cpp",
+ "DrmStatus.cpp",
],
local_include_dirs: [
@@ -74,6 +75,7 @@
static_libs: [
"resourcemanager_aidl_interface-ndk",
"libaidlcommonsupport",
+ "libjsoncpp",
],
export_shared_lib_headers: [
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index f95d527..fc1780d 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -71,7 +71,7 @@
mCryptoHalHidl->notifyResolution(width, height);
}
-status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
// This requires plugin to be created.
if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId);
return mCryptoHalHidl->setMediaDrmSession(sessionId);
diff --git a/drm/libmediadrm/CryptoHalAidl.cpp b/drm/libmediadrm/CryptoHalAidl.cpp
index f01ecb3..c1fd797 100644
--- a/drm/libmediadrm/CryptoHalAidl.cpp
+++ b/drm/libmediadrm/CryptoHalAidl.cpp
@@ -260,7 +260,7 @@
}
}
-status_t CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
diff --git a/drm/libmediadrm/CryptoHalHidl.cpp b/drm/libmediadrm/CryptoHalHidl.cpp
index 55364b5..458a1ae 100644
--- a/drm/libmediadrm/CryptoHalHidl.cpp
+++ b/drm/libmediadrm/CryptoHalHidl.cpp
@@ -386,7 +386,7 @@
ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
}
-status_t CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
diff --git a/drm/libmediadrm/DrmStatus.cpp b/drm/libmediadrm/DrmStatus.cpp
new file mode 100644
index 0000000..0258801
--- /dev/null
+++ b/drm/libmediadrm/DrmStatus.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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 <mediadrm/DrmStatus.h>
+#include <json/json.h>
+
+namespace android {
+
+DrmStatus::DrmStatus(status_t err, const char *msg) : mStatus(err) {
+ Json::Value errorDetails;
+ Json::Reader reader;
+ if (!reader.parse(msg, errorDetails)) {
+ mErrMsg = msg;
+ return;
+ }
+
+ std::string errMsg;
+ auto val = errorDetails["cdmError"];
+ if (!val.isNull()) {
+ mCdmErr = val.asInt();
+ }
+ val = errorDetails["oemError"];
+ if (!val.isNull()) {
+ mOemErr = val.asInt();
+ }
+ val = errorDetails["context"];
+ if (!val.isNull()) {
+ mCtx = val.asInt();
+ }
+ val = errorDetails["errorMessage"];
+ if (!val.isNull()) {
+ mErrMsg = val.asString();
+ } else {
+ mErrMsg = msg;
+ }
+}
+
+} // namespace android
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index be0cd4b..cb103f7 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -32,6 +32,7 @@
#include <android/hardware/drm/1.4/IDrmFactory.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/HidlSupport.h>
+#include <json/json.h>
#include <cutils/properties.h>
#include <utils/Errors.h>
@@ -362,18 +363,23 @@
}
} // namespace
-std::string GetExceptionMessage(status_t err, const char* msg,
+std::string GetExceptionMessage(const DrmStatus &err, const char* defaultMsg,
const Vector<::V1_4::LogMessage>& logs) {
std::string ruler("==============================");
std::string header("Beginning of DRM Plugin Log");
std::string footer("End of DRM Plugin Log");
+ std::string msg(err.getErrorMessage());
String8 msg8;
- if (msg) {
- msg8 += msg;
+ if (!msg.empty()) {
+ msg8 += msg.c_str();
+ msg8 += ": ";
+ } else if (defaultMsg) {
+ msg8 += defaultMsg;
msg8 += ": ";
}
- auto errStr = StrCryptoError(err);
- msg8 += errStr.c_str();
+ msg8 += StrCryptoError(err).c_str();
+ msg8 += String8::format("\ncdm err: %d, oem err: %d, ctx: %d",
+ err.getCdmErr(), err.getOemErr(), err.getContext());
msg8 += String8::format("\n%s %s %s", ruler.c_str(), header.c_str(), ruler.c_str());
for (auto log : logs) {
@@ -410,6 +416,141 @@
return logs;
}
+DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl) {
+ if (statusAidl.isOk()) return OK;
+ if (statusAidl.getExceptionCode() != EX_SERVICE_SPECIFIC) return DEAD_OBJECT;
+ auto astatus = static_cast<StatusAidl>(statusAidl.getServiceSpecificError());
+ status_t status{};
+ switch (astatus) {
+ case StatusAidl::OK:
+ status = OK;
+ break;
+ case StatusAidl::BAD_VALUE:
+ status = BAD_VALUE;
+ break;
+ case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
+ status = ERROR_DRM_CANNOT_HANDLE;
+ break;
+ case StatusAidl::ERROR_DRM_DECRYPT:
+ status = ERROR_DRM_DECRYPT;
+ break;
+ case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
+ status = ERROR_DRM_DEVICE_REVOKED;
+ break;
+ case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
+ status = ERROR_DRM_FRAME_TOO_LARGE;
+ break;
+ case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ status = ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+ break;
+ case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
+ status = ERROR_DRM_INSUFFICIENT_SECURITY;
+ break;
+ case StatusAidl::ERROR_DRM_INVALID_STATE:
+ status = ERROR_DRM_INVALID_STATE;
+ break;
+ case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
+ status = ERROR_DRM_LICENSE_EXPIRED;
+ break;
+ case StatusAidl::ERROR_DRM_NO_LICENSE:
+ status = ERROR_DRM_NO_LICENSE;
+ break;
+ case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
+ status = ERROR_DRM_NOT_PROVISIONED;
+ break;
+ case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
+ status = ERROR_DRM_RESOURCE_BUSY;
+ break;
+ case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
+ status = ERROR_DRM_RESOURCE_CONTENTION;
+ break;
+ case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
+ status = ERROR_DRM_SESSION_LOST_STATE;
+ break;
+ case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
+ status = ERROR_DRM_SESSION_NOT_OPENED;
+ break;
+
+ // New in S / drm@1.4:
+ case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+ status = ERROR_DRM_ZERO_SUBSAMPLES;
+ break;
+ case StatusAidl::CRYPTO_LIBRARY_ERROR:
+ status = ERROR_DRM_CRYPTO_LIBRARY;
+ break;
+ case StatusAidl::GENERAL_OEM_ERROR:
+ status = ERROR_DRM_GENERIC_OEM;
+ break;
+ case StatusAidl::GENERAL_PLUGIN_ERROR:
+ status = ERROR_DRM_GENERIC_PLUGIN;
+ break;
+ case StatusAidl::INIT_DATA_INVALID:
+ status = ERROR_DRM_INIT_DATA;
+ break;
+ case StatusAidl::KEY_NOT_LOADED:
+ status = ERROR_DRM_KEY_NOT_LOADED;
+ break;
+ case StatusAidl::LICENSE_PARSE_ERROR:
+ status = ERROR_DRM_LICENSE_PARSE;
+ break;
+ case StatusAidl::LICENSE_POLICY_ERROR:
+ status = ERROR_DRM_LICENSE_POLICY;
+ break;
+ case StatusAidl::LICENSE_RELEASE_ERROR:
+ status = ERROR_DRM_LICENSE_RELEASE;
+ break;
+ case StatusAidl::LICENSE_REQUEST_REJECTED:
+ status = ERROR_DRM_LICENSE_REQUEST_REJECTED;
+ break;
+ case StatusAidl::LICENSE_RESTORE_ERROR:
+ status = ERROR_DRM_LICENSE_RESTORE;
+ break;
+ case StatusAidl::LICENSE_STATE_ERROR:
+ status = ERROR_DRM_LICENSE_STATE;
+ break;
+ case StatusAidl::MALFORMED_CERTIFICATE:
+ status = ERROR_DRM_CERTIFICATE_MALFORMED;
+ break;
+ case StatusAidl::MEDIA_FRAMEWORK_ERROR:
+ status = ERROR_DRM_MEDIA_FRAMEWORK;
+ break;
+ case StatusAidl::MISSING_CERTIFICATE:
+ status = ERROR_DRM_CERTIFICATE_MISSING;
+ break;
+ case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
+ status = ERROR_DRM_PROVISIONING_CERTIFICATE;
+ break;
+ case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
+ status = ERROR_DRM_PROVISIONING_CONFIG;
+ break;
+ case StatusAidl::PROVISIONING_PARSE_ERROR:
+ status = ERROR_DRM_PROVISIONING_PARSE;
+ break;
+ case StatusAidl::PROVISIONING_REQUEST_REJECTED:
+ status = ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
+ break;
+ case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
+ status = ERROR_DRM_PROVISIONING_RETRY;
+ break;
+ case StatusAidl::SECURE_STOP_RELEASE_ERROR:
+ status = ERROR_DRM_SECURE_STOP_RELEASE;
+ break;
+ case StatusAidl::STORAGE_READ_FAILURE:
+ status = ERROR_DRM_STORAGE_READ;
+ break;
+ case StatusAidl::STORAGE_WRITE_FAILURE:
+ status = ERROR_DRM_STORAGE_WRITE;
+ break;
+
+ case StatusAidl::ERROR_DRM_UNKNOWN:
+ default:
+ status = ERROR_DRM_UNKNOWN;
+ break;
+ }
+
+ return DrmStatus(status, statusAidl.getMessage());
+}
+
LogBuffer gLogBuf;
} // namespace DrmUtils
} // namespace android
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
index a85e3cf..deda9ef 100644
--- a/drm/libmediadrm/fuzzer/Android.bp
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -37,6 +37,7 @@
"liblog",
"resourcemanager_aidl_interface-ndk",
"libaidlcommonsupport",
+ "libjsoncpp",
],
header_libs: [
"libmedia_headers",
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 32a6741..60cbbf8 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -38,7 +38,7 @@
virtual bool requiresSecureDecoderComponent(
const char *mime) const;
virtual void notifyResolution(uint32_t width, uint32_t height);
- virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+ virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId);
virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
const drm::V1_0::SharedBuffer &source, size_t offset,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
index 50878a6..eec4585 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
@@ -49,7 +49,7 @@
virtual status_t destroyPlugin();
virtual bool requiresSecureDecoderComponent(const char* mime) const;
virtual void notifyResolution(uint32_t width, uint32_t height);
- virtual status_t setMediaDrmSession(const Vector<uint8_t>& sessionId);
+ virtual DrmStatus setMediaDrmSession(const Vector<uint8_t>& sessionId);
virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode,
const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source,
size_t offset, const CryptoPlugin::SubSample* subSamples,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
index 6db1e89..0150d7c 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
@@ -57,7 +57,7 @@
virtual void notifyResolution(uint32_t width, uint32_t height);
- virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+ virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId);
virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
diff --git a/drm/libmediadrm/include/mediadrm/DrmStatus.h b/drm/libmediadrm/interface/mediadrm/DrmStatus.h
similarity index 65%
rename from drm/libmediadrm/include/mediadrm/DrmStatus.h
rename to drm/libmediadrm/interface/mediadrm/DrmStatus.h
index 4f29a5a..15826ca 100644
--- a/drm/libmediadrm/include/mediadrm/DrmStatus.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmStatus.h
@@ -16,27 +16,35 @@
#ifndef DRM_STATUS_
#define DRM_STATUS_
-#include <stdint.h>
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/Errors.h>
+#include <stdint.h>
+#include <string>
+
namespace android {
struct DrmStatus {
public:
- DrmStatus(status_t status, int32_t cdmerr = 0, int32_t oemerr = 0)
- : mStatus(status), mCdmErr(cdmerr), mOemErr(oemerr) {}
+ DrmStatus(status_t status, int32_t cdmErr = 0, int32_t oemErr = 0,
+ int32_t ctx = 0, std::string errMsg = "")
+ : mStatus(status), mCdmErr(cdmErr), mOemErr(oemErr),
+ mCtx(ctx), mErrMsg(errMsg) {}
+ DrmStatus(status_t err, const char *msg);
operator status_t() const { return mStatus; }
- int32_t cdmErr() const { return mCdmErr; }
- int32_t oemErr() const { return mOemErr; }
+ int32_t getCdmErr() const { return mCdmErr; }
+ int32_t getOemErr() const { return mOemErr; }
+ int32_t getContext() const { return mCtx; }
+ std::string getErrorMessage() const { return mErrMsg; }
bool operator==(status_t other) const { return mStatus == other; }
bool operator!=(status_t other) const { return mStatus != other; }
private:
- status_t mStatus;
- int32_t mCdmErr{}, mOemErr{};
+ status_t mStatus{};
+ int32_t mCdmErr{}, mOemErr{}, mCtx{};
+ std::string mErrMsg;
};
} // namespace android
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index 32390d6..2632ebd 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -199,98 +199,7 @@
return toStatusT_1_4(err);
}
-inline DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl) {
- if (statusAidl.isOk()) return OK;
- if (statusAidl.getExceptionCode() != EX_SERVICE_SPECIFIC) return DEAD_OBJECT;
- auto status = static_cast<StatusAidl>(statusAidl.getServiceSpecificError());
- switch (status) {
- case StatusAidl::OK:
- return OK;
- case StatusAidl::BAD_VALUE:
- return BAD_VALUE;
- case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
- return ERROR_DRM_CANNOT_HANDLE;
- case StatusAidl::ERROR_DRM_DECRYPT:
- return ERROR_DRM_DECRYPT;
- case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
- return ERROR_DRM_DEVICE_REVOKED;
- case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
- return ERROR_DRM_FRAME_TOO_LARGE;
- case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
- return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
- case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
- return ERROR_DRM_INSUFFICIENT_SECURITY;
- case StatusAidl::ERROR_DRM_INVALID_STATE:
- return ERROR_DRM_INVALID_STATE;
- case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
- return ERROR_DRM_LICENSE_EXPIRED;
- case StatusAidl::ERROR_DRM_NO_LICENSE:
- return ERROR_DRM_NO_LICENSE;
- case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
- return ERROR_DRM_NOT_PROVISIONED;
- case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
- return ERROR_DRM_RESOURCE_BUSY;
- case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
- return ERROR_DRM_RESOURCE_CONTENTION;
- case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
- return ERROR_DRM_SESSION_LOST_STATE;
- case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
- return ERROR_DRM_SESSION_NOT_OPENED;
-
- // New in S / drm@1.4:
- case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
- return ERROR_DRM_ZERO_SUBSAMPLES;
- case StatusAidl::CRYPTO_LIBRARY_ERROR:
- return ERROR_DRM_CRYPTO_LIBRARY;
- case StatusAidl::GENERAL_OEM_ERROR:
- return ERROR_DRM_GENERIC_OEM;
- case StatusAidl::GENERAL_PLUGIN_ERROR:
- return ERROR_DRM_GENERIC_PLUGIN;
- case StatusAidl::INIT_DATA_INVALID:
- return ERROR_DRM_INIT_DATA;
- case StatusAidl::KEY_NOT_LOADED:
- return ERROR_DRM_KEY_NOT_LOADED;
- case StatusAidl::LICENSE_PARSE_ERROR:
- return ERROR_DRM_LICENSE_PARSE;
- case StatusAidl::LICENSE_POLICY_ERROR:
- return ERROR_DRM_LICENSE_POLICY;
- case StatusAidl::LICENSE_RELEASE_ERROR:
- return ERROR_DRM_LICENSE_RELEASE;
- case StatusAidl::LICENSE_REQUEST_REJECTED:
- return ERROR_DRM_LICENSE_REQUEST_REJECTED;
- case StatusAidl::LICENSE_RESTORE_ERROR:
- return ERROR_DRM_LICENSE_RESTORE;
- case StatusAidl::LICENSE_STATE_ERROR:
- return ERROR_DRM_LICENSE_STATE;
- case StatusAidl::MALFORMED_CERTIFICATE:
- return ERROR_DRM_CERTIFICATE_MALFORMED;
- case StatusAidl::MEDIA_FRAMEWORK_ERROR:
- return ERROR_DRM_MEDIA_FRAMEWORK;
- case StatusAidl::MISSING_CERTIFICATE:
- return ERROR_DRM_CERTIFICATE_MISSING;
- case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
- return ERROR_DRM_PROVISIONING_CERTIFICATE;
- case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
- return ERROR_DRM_PROVISIONING_CONFIG;
- case StatusAidl::PROVISIONING_PARSE_ERROR:
- return ERROR_DRM_PROVISIONING_PARSE;
- case StatusAidl::PROVISIONING_REQUEST_REJECTED:
- return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
- case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
- return ERROR_DRM_PROVISIONING_RETRY;
- case StatusAidl::SECURE_STOP_RELEASE_ERROR:
- return ERROR_DRM_SECURE_STOP_RELEASE;
- case StatusAidl::STORAGE_READ_FAILURE:
- return ERROR_DRM_STORAGE_READ;
- case StatusAidl::STORAGE_WRITE_FAILURE:
- return ERROR_DRM_STORAGE_WRITE;
-
- case StatusAidl::ERROR_DRM_UNKNOWN:
- default:
- return ERROR_DRM_UNKNOWN;
- }
- return ERROR_DRM_UNKNOWN;
-}
+DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl);
template<typename T, typename U>
status_t GetLogMessagesAidl(const std::shared_ptr<U> &obj, Vector<::V1_4::LogMessage> &logs) {
@@ -374,14 +283,16 @@
return OK;
}
-std::string GetExceptionMessage(status_t err, const char *msg,
+std::string GetExceptionMessage(const DrmStatus & err, const char *defaultMsg,
const Vector<::V1_4::LogMessage> &logs);
template<typename T>
-std::string GetExceptionMessage(status_t err, const char *msg, const sp<T> &iface) {
+std::string GetExceptionMessage(const DrmStatus &err, const char *defaultMsg, const sp<T> &iface) {
Vector<::V1_4::LogMessage> logs;
- iface->getLogMessages(logs);
- return GetExceptionMessage(err, msg, logs);
+ if (iface != NULL) {
+ iface->getLogMessages(logs);
+ }
+ return GetExceptionMessage(err, defaultMsg, logs);
}
} // namespace DrmUtils
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
index 2c4df60..4087186 100644
--- a/drm/libmediadrm/interface/mediadrm/ICrypto.h
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -17,6 +17,7 @@
#include <cutils/native_handle.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ABase.h>
+#include <mediadrm/DrmStatus.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
@@ -65,7 +66,7 @@
virtual void notifyResolution(uint32_t width, uint32_t height) = 0;
- virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
+ virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
enum DestinationType {
kDestinationTypeSharedMemory, // non-secure
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
new file mode 100644
index 0000000..7d8a859
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -0,0 +1,2266 @@
+/*
+ * Copyright (C) 2022 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 <algorithm>
+#include <map>
+#include <utility>
+#include <vector>
+
+#define LOG_TAG "AidlConversionCppNdk"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "media/AidlConversionCppNdk.h"
+
+#include <media/ShmemCompat.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Utilities
+
+#if defined(BACKEND_NDK)
+/* AIDL String generated in NDK is different than CPP */
+#define GET_DEVICE_DESC_CONNECTION(x) AudioDeviceDescription::CONNECTION_##x
+namespace aidl {
+#else
+#define GET_DEVICE_DESC_CONNECTION(x) AudioDeviceDescription::CONNECTION_##x()
+#endif
+
+namespace android {
+
+using ::android::BAD_VALUE;
+using ::android::OK;
+using ::android::base::unexpected;
+
+using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioConfig;
+using media::audio::common::AudioConfigBase;
+using media::audio::common::AudioContentType;
+using media::audio::common::AudioDevice;
+using media::audio::common::AudioDeviceAddress;
+using media::audio::common::AudioDeviceDescription;
+using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioDualMonoMode;
+using media::audio::common::AudioEncapsulationMetadataType;
+using media::audio::common::AudioEncapsulationMode;
+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::AudioInputFlags;
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioLatencyMode;
+using media::audio::common::AudioMode;
+using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPlaybackRate;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioPortExt;
+using media::audio::common::AudioPortMixExt;
+using media::audio::common::AudioPortMixExtUseCase;
+using media::audio::common::AudioProfile;
+using media::audio::common::AudioSource;
+using media::audio::common::AudioStandard;
+using media::audio::common::AudioStreamType;
+using media::audio::common::AudioUsage;
+using media::audio::common::AudioUuid;
+using media::audio::common::ExtraAudioDescriptor;
+using media::audio::common::Int;
+using media::audio::common::PcmType;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Converters
+
+::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
+ if (aidl.size() > maxSize - 1) {
+ return BAD_VALUE;
+ }
+ aidl.copy(dest, aidl.size());
+ dest[aidl.size()] = '\0';
+ return OK;
+}
+
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
+ if (legacy == nullptr) {
+ return unexpected(BAD_VALUE);
+ }
+ if (strnlen(legacy, maxSize) == maxSize) {
+ // No null-terminator.
+ return unexpected(BAD_VALUE);
+ }
+ return std::string(legacy);
+}
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
+ return convertReinterpret<audio_module_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
+ return convertReinterpret<audio_io_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
+ return convertReinterpret<audio_port_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
+ return convertReinterpret<audio_patch_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
+ return convertReinterpret<audio_unique_id_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl) {
+ return convertReinterpret<audio_hw_sync_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
+ return convertReinterpret<pid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
+ return convertReinterpret<uid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
+ return String16(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
+ return std::string(String8(legacy).c_str());
+}
+
+// TODO b/182392769: create an optional -> optional util
+ConversionResult<std::optional<String16>>
+aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl) {
+ if (!aidl.has_value()) {
+ return std::nullopt;
+ }
+ ConversionResult<String16> conversion =
+ VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.value()));
+ return conversion.value();
+}
+
+ConversionResult<std::optional<std::string_view>>
+legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy) {
+ if (!legacy.has_value()) {
+ return std::nullopt;
+ }
+ ConversionResult<std::string> conversion =
+ VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.value()));
+ return conversion.value();
+}
+
+ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
+ return String8(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
+ return std::string(legacy.c_str());
+}
+
+namespace {
+
+namespace detail {
+using AudioChannelBitPair = std::pair<audio_channel_mask_t, int>;
+using AudioChannelBitPairs = std::vector<AudioChannelBitPair>;
+using AudioChannelPair = std::pair<audio_channel_mask_t, AudioChannelLayout>;
+using AudioChannelPairs = std::vector<AudioChannelPair>;
+using AudioDevicePair = std::pair<audio_devices_t, AudioDeviceDescription>;
+using AudioDevicePairs = std::vector<AudioDevicePair>;
+using AudioFormatPair = std::pair<audio_format_t, AudioFormatDescription>;
+using AudioFormatPairs = std::vector<AudioFormatPair>;
+}
+
+const detail::AudioChannelBitPairs& getInAudioChannelBits() {
+ static const detail::AudioChannelBitPairs pairs = {
+ { AUDIO_CHANNEL_IN_LEFT, AudioChannelLayout::CHANNEL_FRONT_LEFT },
+ { AUDIO_CHANNEL_IN_RIGHT, AudioChannelLayout::CHANNEL_FRONT_RIGHT },
+ // AUDIO_CHANNEL_IN_FRONT is at the end
+ { AUDIO_CHANNEL_IN_BACK, AudioChannelLayout::CHANNEL_BACK_CENTER },
+ // AUDIO_CHANNEL_IN_*_PROCESSED not supported
+ // AUDIO_CHANNEL_IN_PRESSURE not supported
+ // AUDIO_CHANNEL_IN_*_AXIS not supported
+ // AUDIO_CHANNEL_IN_VOICE_* not supported
+ { AUDIO_CHANNEL_IN_BACK_LEFT, AudioChannelLayout::CHANNEL_BACK_LEFT },
+ { AUDIO_CHANNEL_IN_BACK_RIGHT, AudioChannelLayout::CHANNEL_BACK_RIGHT },
+ { AUDIO_CHANNEL_IN_CENTER, AudioChannelLayout::CHANNEL_FRONT_CENTER },
+ { AUDIO_CHANNEL_IN_LOW_FREQUENCY, AudioChannelLayout::CHANNEL_LOW_FREQUENCY },
+ { AUDIO_CHANNEL_IN_TOP_LEFT, AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT },
+ { AUDIO_CHANNEL_IN_TOP_RIGHT, AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT },
+ // When going from aidl to legacy, IN_CENTER is used
+ { AUDIO_CHANNEL_IN_FRONT, AudioChannelLayout::CHANNEL_FRONT_CENTER }
+ };
+ return pairs;
+}
+
+const detail::AudioChannelPairs& getInAudioChannelPairs() {
+ static const detail::AudioChannelPairs pairs = {
+#define DEFINE_INPUT_LAYOUT(n) \
+ { \
+ AUDIO_CHANNEL_IN_##n, \
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
+ AudioChannelLayout::LAYOUT_##n) \
+ }
+
+ DEFINE_INPUT_LAYOUT(MONO),
+ DEFINE_INPUT_LAYOUT(STEREO),
+ DEFINE_INPUT_LAYOUT(FRONT_BACK),
+ // AUDIO_CHANNEL_IN_6 not supported
+ DEFINE_INPUT_LAYOUT(2POINT0POINT2),
+ DEFINE_INPUT_LAYOUT(2POINT1POINT2),
+ DEFINE_INPUT_LAYOUT(3POINT0POINT2),
+ DEFINE_INPUT_LAYOUT(3POINT1POINT2),
+ DEFINE_INPUT_LAYOUT(5POINT1)
+#undef DEFINE_INPUT_LAYOUT
+ };
+ return pairs;
+}
+
+const detail::AudioChannelBitPairs& getOutAudioChannelBits() {
+ static const detail::AudioChannelBitPairs pairs = {
+#define DEFINE_OUTPUT_BITS(n) \
+ { AUDIO_CHANNEL_OUT_##n, AudioChannelLayout::CHANNEL_##n }
+
+ DEFINE_OUTPUT_BITS(FRONT_LEFT),
+ DEFINE_OUTPUT_BITS(FRONT_RIGHT),
+ DEFINE_OUTPUT_BITS(FRONT_CENTER),
+ DEFINE_OUTPUT_BITS(LOW_FREQUENCY),
+ DEFINE_OUTPUT_BITS(BACK_LEFT),
+ DEFINE_OUTPUT_BITS(BACK_RIGHT),
+ DEFINE_OUTPUT_BITS(FRONT_LEFT_OF_CENTER),
+ DEFINE_OUTPUT_BITS(FRONT_RIGHT_OF_CENTER),
+ DEFINE_OUTPUT_BITS(BACK_CENTER),
+ DEFINE_OUTPUT_BITS(SIDE_LEFT),
+ DEFINE_OUTPUT_BITS(SIDE_RIGHT),
+ DEFINE_OUTPUT_BITS(TOP_CENTER),
+ DEFINE_OUTPUT_BITS(TOP_FRONT_LEFT),
+ DEFINE_OUTPUT_BITS(TOP_FRONT_CENTER),
+ DEFINE_OUTPUT_BITS(TOP_FRONT_RIGHT),
+ DEFINE_OUTPUT_BITS(TOP_BACK_LEFT),
+ DEFINE_OUTPUT_BITS(TOP_BACK_CENTER),
+ DEFINE_OUTPUT_BITS(TOP_BACK_RIGHT),
+ DEFINE_OUTPUT_BITS(TOP_SIDE_LEFT),
+ DEFINE_OUTPUT_BITS(TOP_SIDE_RIGHT),
+ DEFINE_OUTPUT_BITS(BOTTOM_FRONT_LEFT),
+ DEFINE_OUTPUT_BITS(BOTTOM_FRONT_CENTER),
+ DEFINE_OUTPUT_BITS(BOTTOM_FRONT_RIGHT),
+ DEFINE_OUTPUT_BITS(LOW_FREQUENCY_2),
+ DEFINE_OUTPUT_BITS(FRONT_WIDE_LEFT),
+ DEFINE_OUTPUT_BITS(FRONT_WIDE_RIGHT),
+#undef DEFINE_OUTPUT_BITS
+ { AUDIO_CHANNEL_OUT_HAPTIC_A, AudioChannelLayout::CHANNEL_HAPTIC_A },
+ { AUDIO_CHANNEL_OUT_HAPTIC_B, AudioChannelLayout::CHANNEL_HAPTIC_B }
+ };
+ return pairs;
+}
+
+const detail::AudioChannelPairs& getOutAudioChannelPairs() {
+ static const detail::AudioChannelPairs pairs = {
+#define DEFINE_OUTPUT_LAYOUT(n) \
+ { \
+ AUDIO_CHANNEL_OUT_##n, \
+ AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
+ AudioChannelLayout::LAYOUT_##n) \
+ }
+
+ DEFINE_OUTPUT_LAYOUT(MONO),
+ DEFINE_OUTPUT_LAYOUT(STEREO),
+ DEFINE_OUTPUT_LAYOUT(2POINT1),
+ DEFINE_OUTPUT_LAYOUT(TRI),
+ DEFINE_OUTPUT_LAYOUT(TRI_BACK),
+ DEFINE_OUTPUT_LAYOUT(3POINT1),
+ DEFINE_OUTPUT_LAYOUT(2POINT0POINT2),
+ DEFINE_OUTPUT_LAYOUT(2POINT1POINT2),
+ DEFINE_OUTPUT_LAYOUT(3POINT0POINT2),
+ DEFINE_OUTPUT_LAYOUT(3POINT1POINT2),
+ DEFINE_OUTPUT_LAYOUT(QUAD),
+ DEFINE_OUTPUT_LAYOUT(QUAD_SIDE),
+ DEFINE_OUTPUT_LAYOUT(SURROUND),
+ DEFINE_OUTPUT_LAYOUT(PENTA),
+ DEFINE_OUTPUT_LAYOUT(5POINT1),
+ DEFINE_OUTPUT_LAYOUT(5POINT1_SIDE),
+ DEFINE_OUTPUT_LAYOUT(5POINT1POINT2),
+ DEFINE_OUTPUT_LAYOUT(5POINT1POINT4),
+ DEFINE_OUTPUT_LAYOUT(6POINT1),
+ DEFINE_OUTPUT_LAYOUT(7POINT1),
+ DEFINE_OUTPUT_LAYOUT(7POINT1POINT2),
+ DEFINE_OUTPUT_LAYOUT(7POINT1POINT4),
+ DEFINE_OUTPUT_LAYOUT(13POINT_360RA),
+ DEFINE_OUTPUT_LAYOUT(22POINT2),
+ DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_A),
+ DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_A),
+ DEFINE_OUTPUT_LAYOUT(HAPTIC_AB),
+ DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_AB),
+ DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_AB)
+#undef DEFINE_OUTPUT_LAYOUT
+ };
+ return pairs;
+}
+
+const detail::AudioChannelPairs& getVoiceAudioChannelPairs() {
+ static const detail::AudioChannelPairs pairs = {
+#define DEFINE_VOICE_LAYOUT(n) \
+ { \
+ AUDIO_CHANNEL_IN_VOICE_##n, \
+ AudioChannelLayout::make<AudioChannelLayout::Tag::voiceMask>( \
+ AudioChannelLayout::VOICE_##n) \
+ }
+ DEFINE_VOICE_LAYOUT(UPLINK_MONO),
+ DEFINE_VOICE_LAYOUT(DNLINK_MONO),
+ DEFINE_VOICE_LAYOUT(CALL_MONO)
+#undef DEFINE_VOICE_LAYOUT
+ };
+ return pairs;
+}
+
+AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
+ const std::string& connection = "") {
+ AudioDeviceDescription result;
+ result.type = type;
+ result.connection = connection;
+ return result;
+}
+
+void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
+ audio_devices_t inputType, audio_devices_t outputType,
+ AudioDeviceType inType, AudioDeviceType outType,
+ const std::string& connection = "") {
+ pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
+ pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
+}
+
+const detail::AudioDevicePairs& getAudioDevicePairs() {
+ static const detail::AudioDevicePairs pairs = []() {
+ detail::AudioDevicePairs pairs = {{
+ {
+ AUDIO_DEVICE_NONE, AudioDeviceDescription{}
+ },
+ {
+ AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER_EARPIECE)
+ },
+ {
+ AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER)
+ },
+ {
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_HEADPHONE,
+ GET_DEVICE_DESC_CONNECTION(ANALOG))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(BT_SCO))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_CARKIT,
+ GET_DEVICE_DESC_CONNECTION(BT_SCO))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_HEADPHONE,
+ GET_DEVICE_DESC_CONNECTION(BT_A2DP))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER,
+ GET_DEVICE_DESC_CONNECTION(BT_A2DP))
+ },
+ {
+ AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_TELEPHONY_TX)
+ },
+ {
+ AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_LINE_AUX)
+ },
+ {
+ AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER_SAFE)
+ },
+ {
+ AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_HEARING_AID,
+ GET_DEVICE_DESC_CONNECTION(WIRELESS))
+ },
+ {
+ AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_ECHO_CANCELLER)
+ },
+ {
+ AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_SPEAKER,
+ GET_DEVICE_DESC_CONNECTION(BT_LE))
+ },
+ {
+ AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_BROADCAST,
+ GET_DEVICE_DESC_CONNECTION(BT_LE))
+ },
+ // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
+ {
+ AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
+ AudioDeviceType::IN_MICROPHONE)
+ },
+ {
+ AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
+ AudioDeviceType::IN_MICROPHONE_BACK)
+ },
+ {
+ AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
+ AudioDeviceType::IN_TELEPHONY_RX)
+ },
+ {
+ AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
+ AudioDeviceType::IN_TV_TUNER)
+ },
+ {
+ AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
+ AudioDeviceType::IN_LOOPBACK)
+ },
+ {
+ AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
+ AudioDeviceType::IN_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(BT_LE))
+ },
+ {
+ AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
+ AudioDeviceType::IN_ECHO_REFERENCE)
+ }
+ }};
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
+ AudioDeviceType::IN_DEFAULT, AudioDeviceType::OUT_DEFAULT);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+ GET_DEVICE_DESC_CONNECTION(ANALOG));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+ AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+ GET_DEVICE_DESC_CONNECTION(BT_SCO));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(HDMI));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
+ AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
+ GET_DEVICE_DESC_CONNECTION(ANALOG));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
+ AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
+ GET_DEVICE_DESC_CONNECTION(USB));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
+ AudioDeviceType::IN_ACCESSORY, AudioDeviceType::OUT_ACCESSORY,
+ GET_DEVICE_DESC_CONNECTION(USB));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(USB));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
+ AudioDeviceType::IN_FM_TUNER, AudioDeviceType::OUT_FM);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(ANALOG));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(SPDIF));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(BT_A2DP));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(IP_V4));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(BUS));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
+ AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
+ AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+ GET_DEVICE_DESC_CONNECTION(USB));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(HDMI_ARC));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+ GET_DEVICE_DESC_CONNECTION(HDMI_EARC));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
+ AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+ GET_DEVICE_DESC_CONNECTION(BT_LE));
+ return pairs;
+ }();
+#undef GET_DEVICE_DESC_CONNECTION
+ return pairs;
+}
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+ AudioFormatDescription result;
+ result.type = type;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+ auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+ result.pcm = pcm;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+ AudioFormatDescription result;
+ result.encoding = encoding;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType transport,
+ const std::string& encoding) {
+ auto result = make_AudioFormatDescription(encoding);
+ result.pcm = transport;
+ return result;
+}
+
+const detail::AudioFormatPairs& getAudioFormatPairs() {
+ static const detail::AudioFormatPairs pairs = {{
+ {AUDIO_FORMAT_INVALID,
+ make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID)},
+ {AUDIO_FORMAT_DEFAULT, AudioFormatDescription{}},
+ {AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(PcmType::INT_16_BIT)},
+ {AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(PcmType::UINT_8_BIT)},
+ {AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(PcmType::INT_32_BIT)},
+ {AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(PcmType::FIXED_Q_8_24)},
+ {AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(PcmType::FLOAT_32_BIT)},
+ {AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(PcmType::INT_24_BIT)},
+ {AUDIO_FORMAT_MP3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEG)},
+ {AUDIO_FORMAT_AMR_NB,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_NB)},
+ {AUDIO_FORMAT_AMR_WB,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_WB)},
+ {AUDIO_FORMAT_AAC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_MP4)},
+ {AUDIO_FORMAT_AAC_MAIN,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_MAIN)},
+ {AUDIO_FORMAT_AAC_LC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LC)},
+ {AUDIO_FORMAT_AAC_SSR,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_SSR)},
+ {AUDIO_FORMAT_AAC_LTP,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LTP)},
+ {AUDIO_FORMAT_AAC_HE_V1,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_HE_V1)},
+ {AUDIO_FORMAT_AAC_SCALABLE,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE)},
+ {AUDIO_FORMAT_AAC_ERLC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ERLC)},
+ {AUDIO_FORMAT_AAC_LD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LD)},
+ {AUDIO_FORMAT_AAC_HE_V2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_HE_V2)},
+ {AUDIO_FORMAT_AAC_ELD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ELD)},
+ {AUDIO_FORMAT_AAC_XHE,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_XHE)
+
+ },
+ // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
+ // ago.
+ {AUDIO_FORMAT_VORBIS,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_VORBIS)},
+ {AUDIO_FORMAT_OPUS, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_OPUS)},
+ {AUDIO_FORMAT_AC3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AC3)},
+ {AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EAC3)},
+ {AUDIO_FORMAT_E_AC3_JOC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EAC3_JOC)},
+ {AUDIO_FORMAT_DTS, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS)},
+ {AUDIO_FORMAT_DTS_HD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_HD)},
+ {AUDIO_FORMAT_DTS_HD_MA,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_HD_MA)},
+ {AUDIO_FORMAT_DTS_UHD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1)},
+ {AUDIO_FORMAT_DTS_UHD_P2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2)},
+ // In the future, we would like to represent encapsulated bitstreams as
+ // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
+ // specify the format of the encapsulated bitstream.
+ {AUDIO_FORMAT_IEC61937,
+ make_AudioFormatDescription(PcmType::INT_16_BIT,
+ ::android::MEDIA_MIMETYPE_AUDIO_IEC61937)},
+ {AUDIO_FORMAT_DOLBY_TRUEHD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD)},
+ {AUDIO_FORMAT_EVRC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRC)},
+ {AUDIO_FORMAT_EVRCB,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCB)},
+ {AUDIO_FORMAT_EVRCWB,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCWB)},
+ {AUDIO_FORMAT_EVRCNW,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCNW)},
+ {AUDIO_FORMAT_AAC_ADIF,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADIF)},
+ {AUDIO_FORMAT_WMA, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_WMA)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")},
+ {AUDIO_FORMAT_AMR_WB_PLUS,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)},
+ {AUDIO_FORMAT_MP2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)},
+ {AUDIO_FORMAT_QCELP,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_QCELP)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")},
+ {AUDIO_FORMAT_FLAC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_FLAC)},
+ {AUDIO_FORMAT_ALAC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_ALAC)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")},
+ {AUDIO_FORMAT_AAC_ADTS,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS)},
+ {AUDIO_FORMAT_AAC_ADTS_MAIN,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN)},
+ {AUDIO_FORMAT_AAC_ADTS_LC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC)},
+ {AUDIO_FORMAT_AAC_ADTS_SSR,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR)},
+ {AUDIO_FORMAT_AAC_ADTS_LTP,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP)},
+ {AUDIO_FORMAT_AAC_ADTS_HE_V1,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1)},
+ {AUDIO_FORMAT_AAC_ADTS_SCALABLE,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE)},
+ {AUDIO_FORMAT_AAC_ADTS_ERLC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC)},
+ {AUDIO_FORMAT_AAC_ADTS_LD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD)},
+ {AUDIO_FORMAT_AAC_ADTS_HE_V2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2)},
+ {AUDIO_FORMAT_AAC_ADTS_ELD,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD)},
+ {AUDIO_FORMAT_AAC_ADTS_XHE,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE)},
+ {// Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
+ AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")},
+ {AUDIO_FORMAT_APTX, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_APTX)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")},
+ {AUDIO_FORMAT_AC4, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AC4)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")},
+ {AUDIO_FORMAT_MAT,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_1_0,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+ std::string(".1.0"))},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_2_0,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+ std::string(".2.0"))},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_2_1,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+ std::string(".2.1"))},
+ {AUDIO_FORMAT_AAC_LATM,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC)},
+ {AUDIO_FORMAT_AAC_LATM_LC,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC)},
+ {AUDIO_FORMAT_AAC_LATM_HE_V1,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1)},
+ {AUDIO_FORMAT_AAC_LATM_HE_V2,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_ADAPTIVE,
+ make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")},
+ {AUDIO_FORMAT_MPEGH,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1)},
+ {AUDIO_FORMAT_MPEGH_BL_L3,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3)},
+ {AUDIO_FORMAT_MPEGH_BL_L4,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4)},
+ {AUDIO_FORMAT_MPEGH_LC_L3,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3)},
+ {AUDIO_FORMAT_MPEGH_LC_L4,
+ make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4)},
+ {AUDIO_FORMAT_IEC60958,
+ make_AudioFormatDescription(PcmType::INT_24_BIT,
+ ::android::MEDIA_MIMETYPE_AUDIO_IEC60958)},
+ {AUDIO_FORMAT_DRA, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DRA)},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_ADAPTIVE_QLEA,
+ make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r3")},
+ {// Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_ADAPTIVE_R4,
+ make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r4")},
+ }};
+ return pairs;
+}
+
+template<typename S, typename T>
+std::map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
+ std::map<S, T> result(v.begin(), v.end());
+ LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+ return result;
+}
+
+template<typename S, typename T>
+std::map<S, T> make_DirectMap(
+ const std::vector<std::pair<S, T>>& v1, const std::vector<std::pair<S, T>>& v2) {
+ std::map<S, T> result(v1.begin(), v1.end());
+ LOG_ALWAYS_FATAL_IF(result.size() != v1.size(), "Duplicate key elements detected in v1");
+ result.insert(v2.begin(), v2.end());
+ LOG_ALWAYS_FATAL_IF(result.size() != v1.size() + v2.size(),
+ "Duplicate key elements detected in v1+v2");
+ return result;
+}
+
+template<typename S, typename T>
+std::map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
+ std::map<T, S> result;
+ std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
+ [](const std::pair<S, T>& p) {
+ return std::make_pair(p.second, p.first);
+ });
+ LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+ return result;
+}
+
+} // namespace
+
+audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ int aidlLayout, bool isInput) {
+ auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
+ const int aidlLayoutInitial = aidlLayout; // for error message
+ audio_channel_mask_t legacy = AUDIO_CHANNEL_NONE;
+ for (const auto& bitPair : bitMapping) {
+ if ((aidlLayout & bitPair.second) == bitPair.second) {
+ legacy = static_cast<audio_channel_mask_t>(legacy | bitPair.first);
+ aidlLayout &= ~bitPair.second;
+ if (aidlLayout == 0) {
+ return legacy;
+ }
+ }
+ }
+ ALOGE("%s: aidl layout 0x%x contains bits 0x%x that have no match to legacy %s bits",
+ __func__, aidlLayoutInitial, aidlLayout, isInput ? "input" : "output");
+ return AUDIO_CHANNEL_NONE;
+}
+
+ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ const AudioChannelLayout& aidl, bool isInput) {
+ using ReverseMap = std::map<AudioChannelLayout, audio_channel_mask_t>;
+ using Tag = AudioChannelLayout::Tag;
+ static const ReverseMap mIn = make_ReverseMap(getInAudioChannelPairs());
+ static const ReverseMap mOut = make_ReverseMap(getOutAudioChannelPairs());
+ static const ReverseMap mVoice = make_ReverseMap(getVoiceAudioChannelPairs());
+
+ auto convert = [](const AudioChannelLayout& aidl, const ReverseMap& m,
+ const char* func, const char* type) -> ConversionResult<audio_channel_mask_t> {
+ if (auto it = m.find(aidl); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGW("%s: no legacy %s audio_channel_mask_t found for %s", func, type,
+ aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+ };
+
+ switch (aidl.getTag()) {
+ case Tag::none:
+ return AUDIO_CHANNEL_NONE;
+ case Tag::invalid:
+ return AUDIO_CHANNEL_INVALID;
+ case Tag::indexMask:
+ // Index masks do not have pre-defined values.
+ if (const int bits = aidl.get<Tag::indexMask>();
+ __builtin_popcount(bits) != 0 &&
+ __builtin_popcount(bits) <= AUDIO_CHANNEL_COUNT_MAX) {
+ return audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
+ } else {
+ ALOGE("%s: invalid indexMask value 0x%x in %s",
+ __func__, bits, aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+ case Tag::layoutMask:
+ // The fast path is to find a direct match for some known layout mask.
+ if (const auto layoutMatch = convert(aidl, isInput ? mIn : mOut, __func__,
+ isInput ? "input" : "output");
+ layoutMatch.ok()) {
+ return layoutMatch;
+ }
+ // If a match for a predefined layout wasn't found, make a custom one from bits.
+ if (audio_channel_mask_t bitMask =
+ aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ aidl.get<Tag::layoutMask>(), isInput);
+ bitMask != AUDIO_CHANNEL_NONE) {
+ return bitMask;
+ }
+ return unexpected(BAD_VALUE);
+ case Tag::voiceMask:
+ return convert(aidl, mVoice, __func__, "voice");
+ }
+ ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
+ return unexpected(BAD_VALUE);
+}
+
+int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+ audio_channel_mask_t legacy, bool isInput) {
+ auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
+ const int legacyInitial = legacy; // for error message
+ int aidlLayout = 0;
+ for (const auto& bitPair : bitMapping) {
+ if ((legacy & bitPair.first) == bitPair.first) {
+ aidlLayout |= bitPair.second;
+ legacy = static_cast<audio_channel_mask_t>(legacy & ~bitPair.first);
+ if (legacy == 0) {
+ return aidlLayout;
+ }
+ }
+ }
+ ALOGE("%s: legacy %s audio_channel_mask_t 0x%x contains unrecognized bits 0x%x",
+ __func__, isInput ? "input" : "output", legacyInitial, legacy);
+ return 0;
+}
+
+ConversionResult<AudioChannelLayout> legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ audio_channel_mask_t legacy, bool isInput) {
+ using DirectMap = std::map<audio_channel_mask_t, AudioChannelLayout>;
+ using Tag = AudioChannelLayout::Tag;
+ static const DirectMap mInAndVoice = make_DirectMap(
+ getInAudioChannelPairs(), getVoiceAudioChannelPairs());
+ static const DirectMap mOut = make_DirectMap(getOutAudioChannelPairs());
+
+ auto convert = [](const audio_channel_mask_t legacy, const DirectMap& m,
+ const char* func, const char* type) -> ConversionResult<AudioChannelLayout> {
+ if (auto it = m.find(legacy); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGW("%s: no AudioChannelLayout found for legacy %s audio_channel_mask_t value 0x%x",
+ func, type, legacy);
+ return unexpected(BAD_VALUE);
+ }
+ };
+
+ if (legacy == AUDIO_CHANNEL_NONE) {
+ return AudioChannelLayout{};
+ } else if (legacy == AUDIO_CHANNEL_INVALID) {
+ return AudioChannelLayout::make<Tag::invalid>(0);
+ }
+
+ const audio_channel_representation_t repr = audio_channel_mask_get_representation(legacy);
+ if (repr == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+ if (audio_channel_mask_is_valid(legacy)) {
+ const int indexMask = VALUE_OR_RETURN(
+ convertIntegral<int>(audio_channel_mask_get_bits(legacy)));
+ return AudioChannelLayout::make<Tag::indexMask>(indexMask);
+ } else {
+ ALOGE("%s: legacy audio_channel_mask_t value 0x%x is invalid", __func__, legacy);
+ return unexpected(BAD_VALUE);
+ }
+ } else if (repr == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
+ // The fast path is to find a direct match for some known layout mask.
+ if (const auto layoutMatch = convert(legacy, isInput ? mInAndVoice : mOut, __func__,
+ isInput ? "input / voice" : "output");
+ layoutMatch.ok()) {
+ return layoutMatch;
+ }
+ // If a match for a predefined layout wasn't found, make a custom one from bits,
+ // rejecting those with voice channel bits.
+ if (!isInput ||
+ (legacy & (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK)) == 0) {
+ if (int bitMaskLayout =
+ legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+ legacy, isInput);
+ bitMaskLayout != 0) {
+ return AudioChannelLayout::make<Tag::layoutMask>(bitMaskLayout);
+ }
+ } else {
+ ALOGE("%s: legacy audio_channel_mask_t value 0x%x contains voice bits",
+ __func__, legacy);
+ }
+ return unexpected(BAD_VALUE);
+ }
+
+ ALOGE("%s: unknown representation %d in audio_channel_mask_t value 0x%x",
+ __func__, repr, legacy);
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+ const AudioDeviceDescription& aidl) {
+ static const std::map<AudioDeviceDescription, audio_devices_t> m =
+ make_ReverseMap(getAudioDevicePairs());
+ if (auto it = m.find(aidl); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ audio_devices_t legacy) {
+ static const std::map<audio_devices_t, AudioDeviceDescription> m =
+ make_DirectMap(getAudioDevicePairs());
+ if (auto it = m.find(legacy); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
+ __func__, legacy);
+ return unexpected(BAD_VALUE);
+ }
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const AudioDevice& aidl,
+ audio_devices_t* legacyType, char* legacyAddress) {
+ *legacyType = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+ return aidl2legacy_string(
+ aidl.address.get<AudioDeviceAddress::id>(),
+ legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const AudioDevice& aidl,
+ audio_devices_t* legacyType, String8* legacyAddress) {
+ *legacyType = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+ *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
+ aidl.address.get<AudioDeviceAddress::id>()));
+ return OK;
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const AudioDevice& aidl,
+ audio_devices_t* legacyType, std::string* legacyAddress) {
+ *legacyType = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+ *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
+ return OK;
+}
+
+ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const char* legacyAddress) {
+ AudioDevice aidl;
+ aidl.type = VALUE_OR_RETURN(
+ legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
+ const std::string aidl_id = VALUE_OR_RETURN(
+ legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+ return aidl;
+}
+
+ConversionResult<AudioDevice>
+legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const String8& legacyAddress) {
+ AudioDevice aidl;
+ aidl.type = VALUE_OR_RETURN(
+ legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
+ const std::string aidl_id = VALUE_OR_RETURN(
+ legacy2aidl_String8_string(legacyAddress));
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+ return aidl;
+}
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+ const AudioFormatDescription& aidl) {
+ static const std::map<AudioFormatDescription, audio_format_t> m =
+ make_ReverseMap(getAudioFormatPairs());
+ if (auto it = m.find(aidl); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
+ audio_format_t legacy) {
+ static const std::map<audio_format_t, AudioFormatDescription> m =
+ make_DirectMap(getAudioFormatPairs());
+ if (auto it = m.find(legacy); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
+ __func__, legacy);
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(
+ AudioGainMode aidl) {
+ switch (aidl) {
+ case AudioGainMode::JOINT:
+ return AUDIO_GAIN_MODE_JOINT;
+ case AudioGainMode::CHANNELS:
+ return AUDIO_GAIN_MODE_CHANNELS;
+ case AudioGainMode::RAMP:
+ return AUDIO_GAIN_MODE_RAMP;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(
+ audio_gain_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_GAIN_MODE_JOINT:
+ return AudioGainMode::JOINT;
+ case AUDIO_GAIN_MODE_CHANNELS:
+ return AudioGainMode::CHANNELS;
+ case AUDIO_GAIN_MODE_RAMP:
+ return AudioGainMode::RAMP;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
+ return convertBitmask<audio_gain_mode_t, int32_t, audio_gain_mode_t, AudioGainMode>(
+ aidl, aidl2legacy_AudioGainMode_audio_gain_mode_t,
+ // AudioGainMode is index-based.
+ indexToEnum_index<AudioGainMode>,
+ // AUDIO_GAIN_MODE_* constants are mask-based.
+ enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
+ return convertBitmask<int32_t, audio_gain_mode_t, AudioGainMode, audio_gain_mode_t>(
+ legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
+ // AUDIO_GAIN_MODE_* constants are mask-based.
+ indexToEnum_bitmask<audio_gain_mode_t>,
+ // AudioGainMode is index-based.
+ enumToMask_index<int32_t, AudioGainMode>);
+}
+
+ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
+ const AudioGainConfig& aidl, bool isInput) {
+ audio_gain_config legacy;
+ legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
+ legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
+ legacy.channel_mask = VALUE_OR_RETURN(
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+ const bool isJoint = bitmaskIsSet(aidl.mode, AudioGainMode::JOINT);
+ size_t numValues = isJoint ? 1
+ : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
+ : audio_channel_count_from_out_mask(legacy.channel_mask);
+ if (aidl.values.size() != numValues || aidl.values.size() > std::size(legacy.values)) {
+ return unexpected(BAD_VALUE);
+ }
+ for (size_t i = 0; i < numValues; ++i) {
+ legacy.values[i] = VALUE_OR_RETURN(convertIntegral<int>(aidl.values[i]));
+ }
+ legacy.ramp_duration_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.rampDurationMs));
+ return legacy;
+}
+
+ConversionResult<AudioGainConfig> legacy2aidl_audio_gain_config_AudioGainConfig(
+ const audio_gain_config& legacy, bool isInput) {
+ AudioGainConfig aidl;
+ aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
+ aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
+ aidl.channelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+ const bool isJoint = (legacy.mode & AUDIO_GAIN_MODE_JOINT) != 0;
+ size_t numValues = isJoint ? 1
+ : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
+ : audio_channel_count_from_out_mask(legacy.channel_mask);
+ aidl.values.resize(numValues);
+ for (size_t i = 0; i < numValues; ++i) {
+ aidl.values[i] = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.values[i]));
+ }
+ aidl.rampDurationMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.ramp_duration_ms));
+ return aidl;
+}
+
+ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
+ AudioInputFlags aidl) {
+ switch (aidl) {
+ case AudioInputFlags::FAST:
+ return AUDIO_INPUT_FLAG_FAST;
+ case AudioInputFlags::HW_HOTWORD:
+ return AUDIO_INPUT_FLAG_HW_HOTWORD;
+ case AudioInputFlags::RAW:
+ return AUDIO_INPUT_FLAG_RAW;
+ case AudioInputFlags::SYNC:
+ return AUDIO_INPUT_FLAG_SYNC;
+ case AudioInputFlags::MMAP_NOIRQ:
+ return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+ case AudioInputFlags::VOIP_TX:
+ return AUDIO_INPUT_FLAG_VOIP_TX;
+ case AudioInputFlags::HW_AV_SYNC:
+ return AUDIO_INPUT_FLAG_HW_AV_SYNC;
+ case AudioInputFlags::DIRECT:
+ return AUDIO_INPUT_FLAG_DIRECT;
+ case AudioInputFlags::ULTRASOUND:
+ return AUDIO_INPUT_FLAG_ULTRASOUND;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
+ audio_input_flags_t legacy) {
+ switch (legacy) {
+ case AUDIO_INPUT_FLAG_NONE:
+ break; // shouldn't get here. must be listed -Werror,-Wswitch
+ case AUDIO_INPUT_FLAG_FAST:
+ return AudioInputFlags::FAST;
+ case AUDIO_INPUT_FLAG_HW_HOTWORD:
+ return AudioInputFlags::HW_HOTWORD;
+ case AUDIO_INPUT_FLAG_RAW:
+ return AudioInputFlags::RAW;
+ case AUDIO_INPUT_FLAG_SYNC:
+ return AudioInputFlags::SYNC;
+ case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
+ return AudioInputFlags::MMAP_NOIRQ;
+ case AUDIO_INPUT_FLAG_VOIP_TX:
+ return AudioInputFlags::VOIP_TX;
+ case AUDIO_INPUT_FLAG_HW_AV_SYNC:
+ return AudioInputFlags::HW_AV_SYNC;
+ case AUDIO_INPUT_FLAG_DIRECT:
+ return AudioInputFlags::DIRECT;
+ case AUDIO_INPUT_FLAG_ULTRASOUND:
+ return AudioInputFlags::ULTRASOUND;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
+ AudioOutputFlags aidl) {
+ switch (aidl) {
+ case AudioOutputFlags::DIRECT:
+ return AUDIO_OUTPUT_FLAG_DIRECT;
+ case AudioOutputFlags::PRIMARY:
+ return AUDIO_OUTPUT_FLAG_PRIMARY;
+ case AudioOutputFlags::FAST:
+ return AUDIO_OUTPUT_FLAG_FAST;
+ case AudioOutputFlags::DEEP_BUFFER:
+ return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ case AudioOutputFlags::COMPRESS_OFFLOAD:
+ return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+ case AudioOutputFlags::NON_BLOCKING:
+ return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+ case AudioOutputFlags::HW_AV_SYNC:
+ return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+ case AudioOutputFlags::TTS:
+ return AUDIO_OUTPUT_FLAG_TTS;
+ case AudioOutputFlags::RAW:
+ return AUDIO_OUTPUT_FLAG_RAW;
+ case AudioOutputFlags::SYNC:
+ return AUDIO_OUTPUT_FLAG_SYNC;
+ case AudioOutputFlags::IEC958_NONAUDIO:
+ return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+ case AudioOutputFlags::DIRECT_PCM:
+ return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+ case AudioOutputFlags::MMAP_NOIRQ:
+ return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ case AudioOutputFlags::VOIP_RX:
+ return AUDIO_OUTPUT_FLAG_VOIP_RX;
+ case AudioOutputFlags::INCALL_MUSIC:
+ return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+ case AudioOutputFlags::GAPLESS_OFFLOAD:
+ return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
+ case AudioOutputFlags::ULTRASOUND:
+ return AUDIO_OUTPUT_FLAG_ULTRASOUND;
+ case AudioOutputFlags::SPATIALIZER:
+ return AUDIO_OUTPUT_FLAG_SPATIALIZER;
+ case AudioOutputFlags::BIT_PERFECT:
+ return AUDIO_OUTPUT_FLAG_BIT_PERFECT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
+ audio_output_flags_t legacy) {
+ switch (legacy) {
+ case AUDIO_OUTPUT_FLAG_NONE:
+ break; // shouldn't get here. must be listed -Werror,-Wswitch
+ case AUDIO_OUTPUT_FLAG_DIRECT:
+ return AudioOutputFlags::DIRECT;
+ case AUDIO_OUTPUT_FLAG_PRIMARY:
+ return AudioOutputFlags::PRIMARY;
+ case AUDIO_OUTPUT_FLAG_FAST:
+ return AudioOutputFlags::FAST;
+ case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
+ return AudioOutputFlags::DEEP_BUFFER;
+ case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
+ return AudioOutputFlags::COMPRESS_OFFLOAD;
+ case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
+ return AudioOutputFlags::NON_BLOCKING;
+ case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
+ return AudioOutputFlags::HW_AV_SYNC;
+ case AUDIO_OUTPUT_FLAG_TTS:
+ return AudioOutputFlags::TTS;
+ case AUDIO_OUTPUT_FLAG_RAW:
+ return AudioOutputFlags::RAW;
+ case AUDIO_OUTPUT_FLAG_SYNC:
+ return AudioOutputFlags::SYNC;
+ case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
+ return AudioOutputFlags::IEC958_NONAUDIO;
+ case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
+ return AudioOutputFlags::DIRECT_PCM;
+ case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
+ return AudioOutputFlags::MMAP_NOIRQ;
+ case AUDIO_OUTPUT_FLAG_VOIP_RX:
+ return AudioOutputFlags::VOIP_RX;
+ case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
+ return AudioOutputFlags::INCALL_MUSIC;
+ case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
+ return AudioOutputFlags::GAPLESS_OFFLOAD;
+ case AUDIO_OUTPUT_FLAG_ULTRASOUND:
+ return AudioOutputFlags::ULTRASOUND;
+ case AUDIO_OUTPUT_FLAG_SPATIALIZER:
+ return AudioOutputFlags::SPATIALIZER;
+ case AUDIO_OUTPUT_FLAG_BIT_PERFECT:
+ return AudioOutputFlags::BIT_PERFECT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
+ int32_t aidl) {
+ using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
+
+ LegacyMask converted = VALUE_OR_RETURN(
+ (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
+ aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
+ indexToEnum_index<AudioInputFlags>,
+ enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
+ return static_cast<audio_input_flags_t>(converted);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
+ audio_input_flags_t legacy) {
+ using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
+
+ LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
+ return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
+ legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
+ indexToEnum_bitmask<audio_input_flags_t>,
+ enumToMask_index<int32_t, AudioInputFlags>);
+}
+
+ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
+ int32_t aidl) {
+ return convertBitmask<audio_output_flags_t,
+ int32_t,
+ audio_output_flags_t,
+ AudioOutputFlags>(
+ aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
+ indexToEnum_index<AudioOutputFlags>,
+ enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
+ audio_output_flags_t legacy) {
+ using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
+
+ LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
+ return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
+ legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
+ indexToEnum_bitmask<audio_output_flags_t>,
+ enumToMask_index<int32_t, AudioOutputFlags>);
+}
+
+ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
+ const AudioIoFlags& aidl, bool isInput) {
+ audio_io_flags legacy;
+ if (isInput) {
+ legacy.input = VALUE_OR_RETURN(
+ aidl2legacy_int32_t_audio_input_flags_t_mask(
+ VALUE_OR_RETURN(UNION_GET(aidl, input))));
+ } else {
+ legacy.output = VALUE_OR_RETURN(
+ aidl2legacy_int32_t_audio_output_flags_t_mask(
+ VALUE_OR_RETURN(UNION_GET(aidl, output))));
+ }
+ return legacy;
+}
+
+ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+ const audio_io_flags& legacy, bool isInput) {
+ AudioIoFlags aidl;
+ if (isInput) {
+ UNION_SET(aidl, input,
+ VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
+ } else {
+ UNION_SET(aidl, output,
+ VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
+ }
+ return aidl;
+}
+
+ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
+ AudioStreamType aidl) {
+ switch (aidl) {
+ case AudioStreamType::INVALID:
+ break; // return error
+ case AudioStreamType::SYS_RESERVED_DEFAULT:
+ return AUDIO_STREAM_DEFAULT;
+ case AudioStreamType::VOICE_CALL:
+ return AUDIO_STREAM_VOICE_CALL;
+ case AudioStreamType::SYSTEM:
+ return AUDIO_STREAM_SYSTEM;
+ case AudioStreamType::RING:
+ return AUDIO_STREAM_RING;
+ case AudioStreamType::MUSIC:
+ return AUDIO_STREAM_MUSIC;
+ case AudioStreamType::ALARM:
+ return AUDIO_STREAM_ALARM;
+ case AudioStreamType::NOTIFICATION:
+ return AUDIO_STREAM_NOTIFICATION;
+ case AudioStreamType::BLUETOOTH_SCO:
+ return AUDIO_STREAM_BLUETOOTH_SCO;
+ case AudioStreamType::ENFORCED_AUDIBLE:
+ return AUDIO_STREAM_ENFORCED_AUDIBLE;
+ case AudioStreamType::DTMF:
+ return AUDIO_STREAM_DTMF;
+ case AudioStreamType::TTS:
+ return AUDIO_STREAM_TTS;
+ case AudioStreamType::ACCESSIBILITY:
+ return AUDIO_STREAM_ACCESSIBILITY;
+ case AudioStreamType::ASSISTANT:
+ return AUDIO_STREAM_ASSISTANT;
+ case AudioStreamType::SYS_RESERVED_REROUTING:
+ return AUDIO_STREAM_REROUTING;
+ case AudioStreamType::SYS_RESERVED_PATCH:
+ return AUDIO_STREAM_PATCH;
+ case AudioStreamType::CALL_ASSISTANT:
+ return AUDIO_STREAM_CALL_ASSISTANT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
+ audio_stream_type_t legacy) {
+ switch (legacy) {
+ case AUDIO_STREAM_DEFAULT:
+ return AudioStreamType::SYS_RESERVED_DEFAULT;
+ case AUDIO_STREAM_VOICE_CALL:
+ return AudioStreamType::VOICE_CALL;
+ case AUDIO_STREAM_SYSTEM:
+ return AudioStreamType::SYSTEM;
+ case AUDIO_STREAM_RING:
+ return AudioStreamType::RING;
+ case AUDIO_STREAM_MUSIC:
+ return AudioStreamType::MUSIC;
+ case AUDIO_STREAM_ALARM:
+ return AudioStreamType::ALARM;
+ case AUDIO_STREAM_NOTIFICATION:
+ return AudioStreamType::NOTIFICATION;
+ case AUDIO_STREAM_BLUETOOTH_SCO:
+ return AudioStreamType::BLUETOOTH_SCO;
+ case AUDIO_STREAM_ENFORCED_AUDIBLE:
+ return AudioStreamType::ENFORCED_AUDIBLE;
+ case AUDIO_STREAM_DTMF:
+ return AudioStreamType::DTMF;
+ case AUDIO_STREAM_TTS:
+ return AudioStreamType::TTS;
+ case AUDIO_STREAM_ACCESSIBILITY:
+ return AudioStreamType::ACCESSIBILITY;
+ case AUDIO_STREAM_ASSISTANT:
+ return AudioStreamType::ASSISTANT;
+ case AUDIO_STREAM_REROUTING:
+ return AudioStreamType::SYS_RESERVED_REROUTING;
+ case AUDIO_STREAM_PATCH:
+ return AudioStreamType::SYS_RESERVED_PATCH;
+ case AUDIO_STREAM_CALL_ASSISTANT:
+ return AudioStreamType::CALL_ASSISTANT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
+ AudioSource aidl) {
+ switch (aidl) {
+ case AudioSource::SYS_RESERVED_INVALID:
+ return AUDIO_SOURCE_INVALID;
+ case AudioSource::DEFAULT:
+ return AUDIO_SOURCE_DEFAULT;
+ case AudioSource::MIC:
+ return AUDIO_SOURCE_MIC;
+ case AudioSource::VOICE_UPLINK:
+ return AUDIO_SOURCE_VOICE_UPLINK;
+ case AudioSource::VOICE_DOWNLINK:
+ return AUDIO_SOURCE_VOICE_DOWNLINK;
+ case AudioSource::VOICE_CALL:
+ return AUDIO_SOURCE_VOICE_CALL;
+ case AudioSource::CAMCORDER:
+ return AUDIO_SOURCE_CAMCORDER;
+ case AudioSource::VOICE_RECOGNITION:
+ return AUDIO_SOURCE_VOICE_RECOGNITION;
+ case AudioSource::VOICE_COMMUNICATION:
+ return AUDIO_SOURCE_VOICE_COMMUNICATION;
+ case AudioSource::REMOTE_SUBMIX:
+ return AUDIO_SOURCE_REMOTE_SUBMIX;
+ case AudioSource::UNPROCESSED:
+ return AUDIO_SOURCE_UNPROCESSED;
+ case AudioSource::VOICE_PERFORMANCE:
+ return AUDIO_SOURCE_VOICE_PERFORMANCE;
+ case AudioSource::ULTRASOUND:
+ return AUDIO_SOURCE_ULTRASOUND;
+ case AudioSource::ECHO_REFERENCE:
+ return AUDIO_SOURCE_ECHO_REFERENCE;
+ case AudioSource::FM_TUNER:
+ return AUDIO_SOURCE_FM_TUNER;
+ case AudioSource::HOTWORD:
+ return AUDIO_SOURCE_HOTWORD;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioSource> legacy2aidl_audio_source_t_AudioSource(
+ audio_source_t legacy) {
+ switch (legacy) {
+ case AUDIO_SOURCE_INVALID:
+ return AudioSource::SYS_RESERVED_INVALID;
+ case AUDIO_SOURCE_DEFAULT:
+ return AudioSource::DEFAULT;
+ case AUDIO_SOURCE_MIC:
+ return AudioSource::MIC;
+ case AUDIO_SOURCE_VOICE_UPLINK:
+ return AudioSource::VOICE_UPLINK;
+ case AUDIO_SOURCE_VOICE_DOWNLINK:
+ return AudioSource::VOICE_DOWNLINK;
+ case AUDIO_SOURCE_VOICE_CALL:
+ return AudioSource::VOICE_CALL;
+ case AUDIO_SOURCE_CAMCORDER:
+ return AudioSource::CAMCORDER;
+ case AUDIO_SOURCE_VOICE_RECOGNITION:
+ return AudioSource::VOICE_RECOGNITION;
+ case AUDIO_SOURCE_VOICE_COMMUNICATION:
+ return AudioSource::VOICE_COMMUNICATION;
+ case AUDIO_SOURCE_REMOTE_SUBMIX:
+ return AudioSource::REMOTE_SUBMIX;
+ case AUDIO_SOURCE_UNPROCESSED:
+ return AudioSource::UNPROCESSED;
+ case AUDIO_SOURCE_VOICE_PERFORMANCE:
+ return AudioSource::VOICE_PERFORMANCE;
+ case AUDIO_SOURCE_ULTRASOUND:
+ return AudioSource::ULTRASOUND;
+ case AUDIO_SOURCE_ECHO_REFERENCE:
+ return AudioSource::ECHO_REFERENCE;
+ case AUDIO_SOURCE_FM_TUNER:
+ return AudioSource::FM_TUNER;
+ case AUDIO_SOURCE_HOTWORD:
+ return AudioSource::HOTWORD;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
+ return convertReinterpret<audio_session_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
+ return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(AudioContentType aidl) {
+ switch (aidl) {
+ case AudioContentType::UNKNOWN:
+ return AUDIO_CONTENT_TYPE_UNKNOWN;
+ case AudioContentType::SPEECH:
+ return AUDIO_CONTENT_TYPE_SPEECH;
+ case AudioContentType::MUSIC:
+ return AUDIO_CONTENT_TYPE_MUSIC;
+ case AudioContentType::MOVIE:
+ return AUDIO_CONTENT_TYPE_MOVIE;
+ case AudioContentType::SONIFICATION:
+ return AUDIO_CONTENT_TYPE_SONIFICATION;
+ case AudioContentType::ULTRASOUND:
+ return AUDIO_CONTENT_TYPE_ULTRASOUND;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
+ switch (legacy) {
+ case AUDIO_CONTENT_TYPE_UNKNOWN:
+ return AudioContentType::UNKNOWN;
+ case AUDIO_CONTENT_TYPE_SPEECH:
+ return AudioContentType::SPEECH;
+ case AUDIO_CONTENT_TYPE_MUSIC:
+ return AudioContentType::MUSIC;
+ case AUDIO_CONTENT_TYPE_MOVIE:
+ return AudioContentType::MOVIE;
+ case AUDIO_CONTENT_TYPE_SONIFICATION:
+ return AudioContentType::SONIFICATION;
+ case AUDIO_CONTENT_TYPE_ULTRASOUND:
+ return AudioContentType::ULTRASOUND;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_usage_t>
+aidl2legacy_AudioUsage_audio_usage_t(AudioUsage aidl) {
+ switch (aidl) {
+ case AudioUsage::INVALID:
+ break; // return error
+ case AudioUsage::UNKNOWN:
+ return AUDIO_USAGE_UNKNOWN;
+ case AudioUsage::MEDIA:
+ return AUDIO_USAGE_MEDIA;
+ case AudioUsage::VOICE_COMMUNICATION:
+ return AUDIO_USAGE_VOICE_COMMUNICATION;
+ case AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
+ return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+ case AudioUsage::ALARM:
+ return AUDIO_USAGE_ALARM;
+ case AudioUsage::NOTIFICATION:
+ return AUDIO_USAGE_NOTIFICATION;
+ case AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
+ return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
+ return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+ case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
+ return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
+ case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
+ return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
+ case AudioUsage::NOTIFICATION_EVENT:
+ return AUDIO_USAGE_NOTIFICATION_EVENT;
+ case AudioUsage::ASSISTANCE_ACCESSIBILITY:
+ return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+ case AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
+ return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+ case AudioUsage::ASSISTANCE_SONIFICATION:
+ return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+ case AudioUsage::GAME:
+ return AUDIO_USAGE_GAME;
+ case AudioUsage::VIRTUAL_SOURCE:
+ return AUDIO_USAGE_VIRTUAL_SOURCE;
+ case AudioUsage::ASSISTANT:
+ return AUDIO_USAGE_ASSISTANT;
+ case AudioUsage::CALL_ASSISTANT:
+ return AUDIO_USAGE_CALL_ASSISTANT;
+ case AudioUsage::EMERGENCY:
+ return AUDIO_USAGE_EMERGENCY;
+ case AudioUsage::SAFETY:
+ return AUDIO_USAGE_SAFETY;
+ case AudioUsage::VEHICLE_STATUS:
+ return AUDIO_USAGE_VEHICLE_STATUS;
+ case AudioUsage::ANNOUNCEMENT:
+ return AUDIO_USAGE_ANNOUNCEMENT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioUsage>
+legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
+ switch (legacy) {
+ case AUDIO_USAGE_UNKNOWN:
+ return AudioUsage::UNKNOWN;
+ case AUDIO_USAGE_MEDIA:
+ return AudioUsage::MEDIA;
+ case AUDIO_USAGE_VOICE_COMMUNICATION:
+ return AudioUsage::VOICE_COMMUNICATION;
+ case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+ return AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
+ case AUDIO_USAGE_ALARM:
+ return AudioUsage::ALARM;
+ case AUDIO_USAGE_NOTIFICATION:
+ return AudioUsage::NOTIFICATION;
+ case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+ return AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+ return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST;
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+ return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT;
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+ return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED;
+ case AUDIO_USAGE_NOTIFICATION_EVENT:
+ return AudioUsage::NOTIFICATION_EVENT;
+ case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+ return AudioUsage::ASSISTANCE_ACCESSIBILITY;
+ case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+ return AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
+ case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+ return AudioUsage::ASSISTANCE_SONIFICATION;
+ case AUDIO_USAGE_GAME:
+ return AudioUsage::GAME;
+ case AUDIO_USAGE_VIRTUAL_SOURCE:
+ return AudioUsage::VIRTUAL_SOURCE;
+ case AUDIO_USAGE_ASSISTANT:
+ return AudioUsage::ASSISTANT;
+ case AUDIO_USAGE_CALL_ASSISTANT:
+ return AudioUsage::CALL_ASSISTANT;
+ case AUDIO_USAGE_EMERGENCY:
+ return AudioUsage::EMERGENCY;
+ case AUDIO_USAGE_SAFETY:
+ return AudioUsage::SAFETY;
+ case AUDIO_USAGE_VEHICLE_STATUS:
+ return AudioUsage::VEHICLE_STATUS;
+ case AUDIO_USAGE_ANNOUNCEMENT:
+ return AudioUsage::ANNOUNCEMENT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
+ switch (aidl) {
+ case AudioEncapsulationMode::INVALID:
+ break; // return error
+ case AudioEncapsulationMode::NONE:
+ return AUDIO_ENCAPSULATION_MODE_NONE;
+ case AudioEncapsulationMode::ELEMENTARY_STREAM:
+ return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
+ case AudioEncapsulationMode::HANDLE:
+ return AUDIO_ENCAPSULATION_MODE_HANDLE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationMode>
+legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_ENCAPSULATION_MODE_NONE:
+ return AudioEncapsulationMode::NONE;
+ case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
+ return AudioEncapsulationMode::ELEMENTARY_STREAM;
+ case AUDIO_ENCAPSULATION_MODE_HANDLE:
+ return AudioEncapsulationMode::HANDLE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const AudioOffloadInfo& aidl) {
+ audio_offload_info_t legacy = AUDIO_INFO_INITIALIZER;
+ audio_config_base_t base = VALUE_OR_RETURN(
+ aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, false /*isInput*/));
+ legacy.sample_rate = base.sample_rate;
+ legacy.channel_mask = base.channel_mask;
+ legacy.format = base.format;
+ legacy.stream_type = VALUE_OR_RETURN(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+ legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitRatePerSecond));
+ legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
+ legacy.has_video = aidl.hasVideo;
+ legacy.is_streaming = aidl.isStreaming;
+ legacy.bit_width = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitWidth));
+ legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.offloadBufferSize));
+ legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+ legacy.encapsulation_mode = VALUE_OR_RETURN(
+ aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(aidl.encapsulationMode));
+ legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
+ legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
+ return legacy;
+}
+
+ConversionResult<AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
+ AudioOffloadInfo aidl;
+ // Version 0.1 fields.
+ if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
+ return unexpected(BAD_VALUE);
+ }
+ const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
+ .channel_mask = legacy.channel_mask, .format = legacy.format };
+ aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(
+ base, false /*isInput*/));
+ aidl.streamType = VALUE_OR_RETURN(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
+ aidl.bitRatePerSecond = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
+ aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
+ aidl.hasVideo = legacy.has_video;
+ aidl.isStreaming = legacy.is_streaming;
+ aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
+ aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
+ aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+
+ // Version 0.2 fields.
+ if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
+ if (legacy.size <
+ offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
+ return unexpected(BAD_VALUE);
+ }
+ aidl.encapsulationMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(
+ legacy.encapsulation_mode));
+ aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
+ aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
+ }
+ return aidl;
+}
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
+ const audio_config_base_t legacyBase = VALUE_OR_RETURN(
+ aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, isInput));
+ audio_config_t legacy = AUDIO_CONFIG_INITIALIZER;
+ legacy.sample_rate = legacyBase.sample_rate;
+ legacy.channel_mask = legacyBase.channel_mask;
+ legacy.format = legacyBase.format;
+ legacy.offload_info = VALUE_OR_RETURN(
+ aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
+ legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
+ return legacy;
+}
+
+ConversionResult<AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput) {
+ const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
+ .channel_mask = legacy.channel_mask, .format = legacy.format };
+ AudioConfig aidl;
+ aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(base, isInput));
+ aidl.offloadInfo = VALUE_OR_RETURN(
+ legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
+ aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
+ return aidl;
+}
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(const AudioConfigBase& aidl, bool isInput) {
+ audio_config_base_t legacy;
+ legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+ legacy.channel_mask = VALUE_OR_RETURN(
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+ legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+ return legacy;
+}
+
+ConversionResult<AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput) {
+ AudioConfigBase aidl;
+ aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+ aidl.channelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+ aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+ return aidl;
+}
+
+ConversionResult<audio_uuid_t>
+aidl2legacy_AudioUuid_audio_uuid_t(const AudioUuid& aidl) {
+ audio_uuid_t legacy;
+ legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
+ legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
+ legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
+ legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
+ if (aidl.node.size() != std::size(legacy.node)) {
+ return unexpected(BAD_VALUE);
+ }
+ std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
+ return legacy;
+}
+
+ConversionResult<AudioUuid>
+legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
+ AudioUuid aidl;
+ aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
+ aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
+ aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
+ aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
+ std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
+ return aidl;
+}
+
+ConversionResult<audio_encapsulation_metadata_type_t>
+aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
+ AudioEncapsulationMetadataType aidl) {
+ switch (aidl) {
+ case AudioEncapsulationMetadataType::NONE:
+ return AUDIO_ENCAPSULATION_METADATA_TYPE_NONE;
+ case AudioEncapsulationMetadataType::FRAMEWORK_TUNER:
+ return AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER;
+ case AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR:
+ return AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationMetadataType>
+legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+ audio_encapsulation_metadata_type_t legacy) {
+ switch (legacy) {
+ case AUDIO_ENCAPSULATION_METADATA_TYPE_NONE:
+ return AudioEncapsulationMetadataType::NONE;
+ case AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER:
+ return AudioEncapsulationMetadataType::FRAMEWORK_TUNER;
+ case AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR:
+ return AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t>
+aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl) {
+ return convertBitmask<uint32_t,
+ int32_t,
+ audio_encapsulation_mode_t,
+ AudioEncapsulationMode>(
+ aidl, aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t,
+ indexToEnum_index<AudioEncapsulationMode>,
+ enumToMask_index<uint32_t, audio_encapsulation_mode_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy) {
+ return convertBitmask<int32_t,
+ uint32_t,
+ AudioEncapsulationMode,
+ audio_encapsulation_mode_t>(
+ legacy, legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode,
+ indexToEnum_index<audio_encapsulation_mode_t>,
+ enumToMask_index<int32_t, AudioEncapsulationMode>);
+}
+
+ConversionResult<uint32_t>
+aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl) {
+ return convertBitmask<uint32_t,
+ int32_t,
+ audio_encapsulation_metadata_type_t,
+ AudioEncapsulationMetadataType>(
+ aidl, aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t,
+ indexToEnum_index<AudioEncapsulationMetadataType>,
+ enumToMask_index<uint32_t, audio_encapsulation_metadata_type_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy) {
+ return convertBitmask<int32_t,
+ uint32_t,
+ AudioEncapsulationMetadataType,
+ audio_encapsulation_metadata_type_t>(
+ legacy, legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType,
+ indexToEnum_index<audio_encapsulation_metadata_type_t>,
+ enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
+}
+
+ConversionResult<audio_profile>
+aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
+ audio_profile legacy;
+ legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+
+ if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
+ convertIntegral<int32_t, unsigned int>));
+ legacy.num_sample_rates = aidl.sampleRates.size();
+
+ if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(aidl.channelMasks.begin(), aidl.channelMasks.end(), legacy.channel_masks,
+ [isInput](const AudioChannelLayout& l) {
+ return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
+ }));
+ legacy.num_channel_masks = aidl.channelMasks.size();
+
+ legacy.encapsulation_type = VALUE_OR_RETURN(
+ aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(aidl.encapsulationType));
+ return legacy;
+}
+
+ConversionResult<AudioProfile>
+legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
+ AudioProfile aidl;
+ aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+
+ if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
+ std::back_inserter(aidl.sampleRates),
+ convertIntegral<unsigned int, int32_t>));
+
+ if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
+ return unexpected(BAD_VALUE);
+ }
+ RETURN_IF_ERROR(
+ convertRange(legacy.channel_masks, legacy.channel_masks + legacy.num_channel_masks,
+ std::back_inserter(aidl.channelMasks),
+ [isInput](audio_channel_mask_t m) {
+ return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
+ }));
+
+ aidl.encapsulationType = VALUE_OR_RETURN(
+ legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+ legacy.encapsulation_type));
+ return aidl;
+}
+
+ConversionResult<audio_gain>
+aidl2legacy_AudioGain_audio_gain(const AudioGain& aidl, bool isInput) {
+ audio_gain legacy;
+ legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
+ legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ aidl.channelMask, isInput));
+ legacy.min_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.minValue));
+ legacy.max_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.maxValue));
+ legacy.default_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.defaultValue));
+ legacy.step_value = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.stepValue));
+ legacy.min_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.minRampMs));
+ legacy.max_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.maxRampMs));
+ return legacy;
+}
+
+ConversionResult<AudioGain>
+legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput) {
+ AudioGain aidl;
+ aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
+ aidl.channelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+ aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
+ aidl.maxValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_value));
+ aidl.defaultValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.default_value));
+ aidl.stepValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.step_value));
+ aidl.minRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_ramp_ms));
+ aidl.maxRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_ramp_ms));
+ return aidl;
+}
+
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(AudioMode aidl) {
+ switch (aidl) {
+ case AudioMode::SYS_RESERVED_INVALID:
+ return AUDIO_MODE_INVALID;
+ case AudioMode::SYS_RESERVED_CURRENT:
+ return AUDIO_MODE_CURRENT;
+ case AudioMode::NORMAL:
+ return AUDIO_MODE_NORMAL;
+ case AudioMode::RINGTONE:
+ return AUDIO_MODE_RINGTONE;
+ case AudioMode::IN_CALL:
+ return AUDIO_MODE_IN_CALL;
+ case AudioMode::IN_COMMUNICATION:
+ return AUDIO_MODE_IN_COMMUNICATION;
+ case AudioMode::CALL_SCREEN:
+ return AUDIO_MODE_CALL_SCREEN;
+ case AudioMode::SYS_RESERVED_CALL_REDIRECT:
+ return AUDIO_MODE_CALL_REDIRECT;
+ case AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT:
+ return AUDIO_MODE_COMMUNICATION_REDIRECT;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_MODE_INVALID:
+ return AudioMode::SYS_RESERVED_INVALID;
+ case AUDIO_MODE_CURRENT:
+ return AudioMode::SYS_RESERVED_CURRENT;
+ case AUDIO_MODE_NORMAL:
+ return AudioMode::NORMAL;
+ case AUDIO_MODE_RINGTONE:
+ return AudioMode::RINGTONE;
+ case AUDIO_MODE_IN_CALL:
+ return AudioMode::IN_CALL;
+ case AUDIO_MODE_IN_COMMUNICATION:
+ return AudioMode::IN_COMMUNICATION;
+ case AUDIO_MODE_CALL_SCREEN:
+ return AudioMode::CALL_SCREEN;
+ case AUDIO_MODE_CALL_REDIRECT:
+ return AudioMode::SYS_RESERVED_CALL_REDIRECT;
+ case AUDIO_MODE_COMMUNICATION_REDIRECT:
+ return AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT;
+ case AUDIO_MODE_CNT:
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_standard_t>
+aidl2legacy_AudioStandard_audio_standard_t(AudioStandard aidl) {
+ switch (aidl) {
+ case AudioStandard::NONE:
+ return AUDIO_STANDARD_NONE;
+ case AudioStandard::EDID:
+ return AUDIO_STANDARD_EDID;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStandard>
+legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy) {
+ switch (legacy) {
+ case AUDIO_STANDARD_NONE:
+ return AudioStandard::NONE;
+ case AUDIO_STANDARD_EDID:
+ return AudioStandard::EDID;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_extra_audio_descriptor>
+aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
+ const ExtraAudioDescriptor& aidl) {
+ audio_extra_audio_descriptor legacy;
+ legacy.standard = VALUE_OR_RETURN(aidl2legacy_AudioStandard_audio_standard_t(aidl.standard));
+ if (aidl.audioDescriptor.size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+ return unexpected(BAD_VALUE);
+ }
+ legacy.descriptor_length = aidl.audioDescriptor.size();
+ std::copy(aidl.audioDescriptor.begin(), aidl.audioDescriptor.end(),
+ std::begin(legacy.descriptor));
+ legacy.encapsulation_type =
+ VALUE_OR_RETURN(aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+ aidl.encapsulationType));
+ return legacy;
+}
+
+ConversionResult<ExtraAudioDescriptor>
+legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
+ const audio_extra_audio_descriptor& legacy) {
+ ExtraAudioDescriptor aidl;
+ aidl.standard = VALUE_OR_RETURN(legacy2aidl_audio_standard_t_AudioStandard(legacy.standard));
+ if (legacy.descriptor_length > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+ return unexpected(BAD_VALUE);
+ }
+ aidl.audioDescriptor.resize(legacy.descriptor_length);
+ std::copy(legacy.descriptor, legacy.descriptor + legacy.descriptor_length,
+ aidl.audioDescriptor.begin());
+ aidl.encapsulationType =
+ VALUE_OR_RETURN(legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+ legacy.encapsulation_type));
+ return aidl;
+}
+
+ConversionResult<audio_encapsulation_type_t>
+aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+ const AudioEncapsulationType& aidl) {
+ switch (aidl) {
+ case AudioEncapsulationType::NONE:
+ return AUDIO_ENCAPSULATION_TYPE_NONE;
+ case AudioEncapsulationType::IEC61937:
+ return AUDIO_ENCAPSULATION_TYPE_IEC61937;
+ case AudioEncapsulationType::PCM:
+ return AUDIO_ENCAPSULATION_TYPE_PCM;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationType>
+legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+ const audio_encapsulation_type_t & legacy) {
+ switch (legacy) {
+ case AUDIO_ENCAPSULATION_TYPE_NONE:
+ return AudioEncapsulationType::NONE;
+ case AUDIO_ENCAPSULATION_TYPE_IEC61937:
+ return AudioEncapsulationType::IEC61937;
+ case AUDIO_ENCAPSULATION_TYPE_PCM:
+ return AudioEncapsulationType::PCM;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(AudioDualMonoMode aidl) {
+ switch (aidl) {
+ case AudioDualMonoMode::OFF:
+ return AUDIO_DUAL_MONO_MODE_OFF;
+ case AudioDualMonoMode::LR:
+ return AUDIO_DUAL_MONO_MODE_LR;
+ case AudioDualMonoMode::LL:
+ return AUDIO_DUAL_MONO_MODE_LL;
+ case AudioDualMonoMode::RR:
+ return AUDIO_DUAL_MONO_MODE_RR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_DUAL_MONO_MODE_OFF:
+ return AudioDualMonoMode::OFF;
+ case AUDIO_DUAL_MONO_MODE_LR:
+ return AudioDualMonoMode::LR;
+ case AUDIO_DUAL_MONO_MODE_LL:
+ return AudioDualMonoMode::LL;
+ case AUDIO_DUAL_MONO_MODE_RR:
+ return AudioDualMonoMode::RR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ AudioPlaybackRate::TimestretchFallbackMode aidl) {
+ switch (aidl) {
+ case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT:
+ return AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT;
+ case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT:
+ return AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
+ case AudioPlaybackRate::TimestretchFallbackMode::MUTE:
+ return AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+ case AudioPlaybackRate::TimestretchFallbackMode::FAIL:
+ return AUDIO_TIMESTRETCH_FALLBACK_FAIL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ audio_timestretch_fallback_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
+ return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT;
+ case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
+ return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT;
+ case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
+ return AudioPlaybackRate::TimestretchFallbackMode::MUTE;
+ case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
+ return AudioPlaybackRate::TimestretchFallbackMode::FAIL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+ AudioPlaybackRate::TimestretchMode aidl) {
+ switch (aidl) {
+ case AudioPlaybackRate::TimestretchMode::DEFAULT:
+ return AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
+ case AudioPlaybackRate::TimestretchMode::VOICE:
+ return AUDIO_TIMESTRETCH_STRETCH_VOICE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+ audio_timestretch_stretch_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
+ return AudioPlaybackRate::TimestretchMode::DEFAULT;
+ case AUDIO_TIMESTRETCH_STRETCH_VOICE:
+ return AudioPlaybackRate::TimestretchMode::VOICE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const AudioPlaybackRate& aidl) {
+ audio_playback_rate_t legacy;
+ legacy.mSpeed = aidl.speed;
+ legacy.mPitch = aidl.pitch;
+ legacy.mFallbackMode = VALUE_OR_RETURN(
+ aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ aidl.fallbackMode));
+ legacy.mStretchMode = VALUE_OR_RETURN(
+ aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(aidl.timestretchMode));
+ return legacy;
+}
+
+ConversionResult<AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
+ AudioPlaybackRate aidl;
+ aidl.speed = legacy.mSpeed;
+ aidl.pitch = legacy.mPitch;
+ aidl.fallbackMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ legacy.mFallbackMode));
+ aidl.timestretchMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(legacy.mStretchMode));
+ return aidl;
+}
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(AudioLatencyMode aidl) {
+ switch (aidl) {
+ case AudioLatencyMode::FREE:
+ return AUDIO_LATENCY_MODE_FREE;
+ case AudioLatencyMode::LOW:
+ return AUDIO_LATENCY_MODE_LOW;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_LATENCY_MODE_FREE:
+ return AudioLatencyMode::FREE;
+ case AUDIO_LATENCY_MODE_LOW:
+ return AudioLatencyMode::LOW;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+} // namespace android
+
+#if defined(BACKEND_NDK)
+} // aidl
+#endif
\ No newline at end of file
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
new file mode 100644
index 0000000..4a1df3a
--- /dev/null
+++ b/media/audioaidlconversion/Android.bp
@@ -0,0 +1,140 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_defaults {
+ name: "audio_aidl_conversion_common_util_default",
+ host_supported: true,
+ vendor_available: true,
+ double_loadable: true,
+ min_sdk_version: "29",
+ export_include_dirs: [
+ "include",
+ ],
+ header_libs: [
+ "libbase_headers",
+ "liberror_headers",
+ ],
+ export_header_lib_headers: [
+ "libbase_headers",
+ "liberror_headers",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.btservices",
+ "com.android.media",
+ "com.android.media.swcodec",
+ ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+// This is intended for clients needing to include AidlConversionUtil.h, without extra dependencies.
+cc_library_headers {
+ name: "libaudio_aidl_conversion_common_util_cpp",
+ defaults: [
+ "audio_aidl_conversion_common_util_default",
+ ],
+}
+
+cc_library_headers {
+ name: "libaudio_aidl_conversion_common_util_ndk",
+ defaults: [
+ "audio_aidl_conversion_common_util_default",
+ ],
+ cflags: [
+ "-DBACKEND_NDK",
+ ],
+}
+
+cc_defaults {
+ name: "audio_aidl_conversion_common_default",
+ export_include_dirs: ["include"],
+ host_supported: true,
+ vendor_available: true,
+ double_loadable: true,
+ min_sdk_version: "29",
+ header_libs: [
+ "libaudio_system_headers",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libshmemcompat",
+ "libstagefright_foundation",
+ "libutils",
+ "shared-file-region-aidl-cpp",
+ "framework-permission-aidl-cpp",
+ ],
+ export_shared_lib_headers: [
+ "libbase",
+ "shared-file-region-aidl-cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-error=deprecated-declarations",
+ ],
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+/**
+ * Only AIDL CPP backend conversion supported.
+ */
+cc_library {
+ name: "libaudio_aidl_conversion_common_cpp",
+ srcs: ["AidlConversionCppNdk.cpp"],
+ header_libs: [
+ "libaudio_aidl_conversion_common_util_cpp",
+ ],
+ export_header_lib_headers: [
+ "libaudio_aidl_conversion_common_util_cpp",
+ ],
+ defaults: [
+ "audio_aidl_conversion_common_default",
+ "latest_android_media_audio_common_types_cpp_export_shared",
+ ],
+}
+
+/**
+ * Only AIDL NDK backend conversion supported.
+ */
+cc_library {
+ name: "libaudio_aidl_conversion_common_ndk",
+ srcs: ["AidlConversionCppNdk.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_media_audio_common_types_ndk_shared",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ cflags: [
+ "-DBACKEND_NDK",
+ ],
+}
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
new file mode 100644
index 0000000..c25ddb1
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2022 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 <limits>
+#include <type_traits>
+#include <system/audio.h>
+
+/**
+ * Can handle conversion between AIDL (both CPP and NDK backend) and legacy type.
+ * Controlled by the cflags preprocessor in Android.bp.
+ */
+#if defined(BACKEND_NDK)
+#define PREFIX(f) <aidl/f>
+#else
+#define PREFIX(f) <f>
+#endif
+
+#include PREFIX(android/media/audio/common/AudioChannelLayout.h)
+#include PREFIX(android/media/audio/common/AudioConfig.h)
+#include PREFIX(android/media/audio/common/AudioConfigBase.h)
+#include PREFIX(android/media/audio/common/AudioContentType.h)
+#include PREFIX(android/media/audio/common/AudioDeviceDescription.h)
+#include PREFIX(android/media/audio/common/AudioDualMonoMode.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
+#include PREFIX(android/media/audio/common/AudioFormatDescription.h)
+#include PREFIX(android/media/audio/common/AudioGain.h)
+#include PREFIX(android/media/audio/common/AudioGainConfig.h)
+#include PREFIX(android/media/audio/common/AudioGainMode.h)
+#include PREFIX(android/media/audio/common/AudioInputFlags.h)
+#include PREFIX(android/media/audio/common/AudioIoFlags.h)
+#include PREFIX(android/media/audio/common/AudioLatencyMode.h)
+#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/AudioPortExt.h)
+#include PREFIX(android/media/audio/common/AudioPortMixExt.h)
+#include PREFIX(android/media/audio/common/AudioPlaybackRate.h)
+#include PREFIX(android/media/audio/common/AudioProfile.h)
+#include PREFIX(android/media/audio/common/AudioSource.h)
+#include PREFIX(android/media/audio/common/AudioStandard.h)
+#include PREFIX(android/media/audio/common/AudioUsage.h)
+#include PREFIX(android/media/audio/common/AudioUuid.h)
+#include PREFIX(android/media/audio/common/ExtraAudioDescriptor.h)
+#include PREFIX(android/media/audio/common/Int.h)
+#undef PREFIX
+
+#include <media/AidlConversionUtil.h>
+#include <system/audio.h>
+#include <system/audio_effect.h>
+
+using ::android::String16;
+using ::android::String8;
+
+#if defined(BACKEND_NDK)
+namespace aidl {
+#endif
+
+namespace android {
+
+// 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);
+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);
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
+
+ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy);
+
+ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
+
+ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy);
+
+ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy);
+
+ConversionResult<std::optional<String16>>
+aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl);
+ConversionResult<std::optional<std::string_view>>
+legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy);
+
+ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+ const media::audio::common::AudioChannelLayout& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioChannelLayout>
+legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput);
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(
+ const media::audio::common::AudioConfigBase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput);
+
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
+
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+
+ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
+ int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
+ audio_input_flags_t legacy);
+
+ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
+ int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
+ audio_output_flags_t legacy);
+
+ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
+ const media::audio::common::AudioIoFlags& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+ const audio_io_flags& legacy, bool isInput);
+
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(
+ media::audio::common::AudioContentType aidl);
+ConversionResult<media::audio::common::AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
+
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+ const media::audio::common::AudioDeviceDescription& aidl);
+ConversionResult<media::audio::common::AudioDeviceDescription>
+legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
+
+::android::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(
+ const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+ String8* legacyAddress);
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+ const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+ std::string* legacyAddress);
+
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const char* legacyAddress);
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const String8& legacyAddress);
+
+ConversionResult<audio_extra_audio_descriptor>
+aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
+ const media::audio::common::ExtraAudioDescriptor& aidl);
+
+ConversionResult<media::audio::common::ExtraAudioDescriptor>
+legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
+ const audio_extra_audio_descriptor& legacy);
+
+ConversionResult<audio_encapsulation_metadata_type_t>
+aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
+ media::audio::common::AudioEncapsulationMetadataType aidl);
+ConversionResult<media::audio::common::AudioEncapsulationMetadataType>
+legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+ audio_encapsulation_metadata_type_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(
+ media::audio::common::AudioEncapsulationMode aidl);
+ConversionResult<media::audio::common::AudioEncapsulationMode>
+legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy);
+
+ConversionResult<audio_encapsulation_type_t>
+aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+ const media::audio::common::AudioEncapsulationType& aidl);
+ConversionResult<media::audio::common::AudioEncapsulationType>
+legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+ const audio_encapsulation_type_t& legacy);
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+ const media::audio::common::AudioFormatDescription& aidl);
+ConversionResult<media::audio::common::AudioFormatDescription>
+legacy2aidl_audio_format_t_AudioFormatDescription(audio_format_t legacy);
+
+ConversionResult<audio_gain_mode_t>
+aidl2legacy_AudioGainMode_audio_gain_mode_t(media::audio::common::AudioGainMode aidl);
+ConversionResult<media::audio::common::AudioGainMode>
+legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy);
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
+
+ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
+ const media::audio::common::AudioGainConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioGainConfig>
+legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
+
+ConversionResult<audio_gain>
+aidl2legacy_AudioGain_audio_gain(const media::audio::common::AudioGain& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioGain>
+legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput);
+
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
+
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(media::audio::common::AudioMode aidl);
+ConversionResult<media::audio::common::AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(
+ const media::audio::common::AudioOffloadInfo& aidl);
+ConversionResult<media::audio::common::AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
+
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+
+ConversionResult<audio_profile> aidl2legacy_AudioProfile_audio_profile(
+ const media::audio::common::AudioProfile& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioProfile> legacy2aidl_audio_profile_AudioProfile(
+ const audio_profile& legacy, bool isInput);
+
+ConversionResult<audio_standard_t> aidl2legacy_AudioStandard_audio_standard_t(
+ media::audio::common::AudioStandard aidl);
+ConversionResult<media::audio::common::AudioStandard> legacy2aidl_audio_standard_t_AudioStandard(
+ audio_standard_t legacy);
+
+ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
+ media::audio::common::AudioSource aidl);
+ConversionResult<media::audio::common::AudioSource> legacy2aidl_audio_source_t_AudioSource(
+ audio_source_t legacy);
+
+ConversionResult<audio_usage_t> aidl2legacy_AudioUsage_audio_usage_t(
+ media::audio::common::AudioUsage aidl);
+ConversionResult<media::audio::common::AudioUsage> legacy2aidl_audio_usage_t_AudioUsage(
+ audio_usage_t legacy);
+
+ConversionResult<audio_uuid_t> aidl2legacy_AudioUuid_audio_uuid_t(
+ const media::audio::common::AudioUuid &aidl);
+ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
+ const audio_uuid_t& legacy);
+
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::audio::common::AudioDualMonoMode aidl);
+ConversionResult<media::audio::common::AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ media::audio::common::AudioPlaybackRate::TimestretchFallbackMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ audio_timestretch_fallback_mode_t legacy);
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+ media::audio::common::AudioPlaybackRate::TimestretchMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+ audio_timestretch_stretch_mode_t legacy);
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(
+ const media::audio::common::AudioPlaybackRate& aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(media::audio::common::AudioLatencyMode aidl);
+ConversionResult<media::audio::common::AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy);
+
+} // namespace android
+
+#if defined(BACKEND_NDK)
+} // aidl
+#endif
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/audioaidlconversion/include/media/AidlConversionUtil.h
similarity index 80%
rename from media/libaudioclient/include/media/AidlConversionUtil.h
rename to media/audioaidlconversion/include/media/AidlConversionUtil.h
index 8817c35..95daa4a 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil.h
@@ -20,15 +20,21 @@
#include <type_traits>
#include <utility>
-#include <binder/Enums.h>
+#include <android-base/expected.h>
#include <binder/Status.h>
#include <error/Result.h>
-namespace android {
+#if defined(BACKEND_NDK)
+#include <android/binder_status.h>
+namespace aidl {
+#else
+#include <binder/Enums.h>
+#endif
template <typename T>
-using ConversionResult = error::Result<T>;
+using ConversionResult = ::android::error::Result<T>;
+namespace android {
/**
* A generic template to safely cast between integral types, respecting limits of the destination
* type.
@@ -39,15 +45,15 @@
// have the signed converted to unsigned and produce wrong results.
if (std::is_signed_v<From> && !std::is_signed_v<To>) {
if (from < 0 || from > std::numeric_limits<To>::max()) {
- return base::unexpected(BAD_VALUE);
+ return ::android::base::unexpected(::android::BAD_VALUE);
}
} else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
if (from > std::numeric_limits<To>::max()) {
- return base::unexpected(BAD_VALUE);
+ return ::android::base::unexpected(::android::BAD_VALUE);
}
} else {
if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
- return base::unexpected(BAD_VALUE);
+ return ::android::base::unexpected(::android::BAD_VALUE);
}
}
return static_cast<To>(from);
@@ -67,14 +73,14 @@
* A generic template that helps convert containers of convertible types, using iterators.
*/
template<typename InputIterator, typename OutputIterator, typename Func>
-status_t convertRange(InputIterator start,
+::android::status_t convertRange(InputIterator start,
InputIterator end,
OutputIterator out,
const Func& itemConversion) {
for (InputIterator iter = start; iter != end; ++iter, ++out) {
*out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
}
- return OK;
+ return ::android::OK;
}
/**
@@ -82,7 +88,7 @@
* Uses a limit as maximum conversion items.
*/
template<typename InputIterator, typename OutputIterator, typename Func>
-status_t convertRangeWithLimit(InputIterator start,
+::android::status_t convertRangeWithLimit(InputIterator start,
InputIterator end,
OutputIterator out,
const Func& itemConversion,
@@ -94,7 +100,7 @@
for (InputIterator iter = start; (iter != last); ++iter, ++out) {
*out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
}
- return OK;
+ return ::android::OK;
}
/**
@@ -140,7 +146,7 @@
OutputContainer output;
auto ins = std::inserter(output, output.begin());
for (const auto& item1 : input1) {
- RETURN_IF_ERROR(iter2 != input2.end() ? OK : BAD_VALUE);
+ RETURN_IF_ERROR(iter2 != input2.end() ? ::android::OK : ::android::BAD_VALUE);
*ins = VALUE_OR_RETURN(itemConversion(item1, *iter2++));
}
return output;
@@ -248,7 +254,8 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilities for working with AIDL unions.
// UNION_GET(obj, fieldname) returns a ConversionResult<T> containing either the strongly-typed
-// value of the respective field, or BAD_VALUE if the union is not set to the requested field.
+// value of the respective field, or ::android::BAD_VALUE if the union is not set to the requested
+// field.
// UNION_SET(obj, fieldname, value) sets the requested field to the given value.
template<typename T, typename T::Tag tag>
@@ -257,7 +264,7 @@
template<typename T, typename T::Tag tag>
ConversionResult<UnionFieldType<T, tag>> unionGetField(const T& u) {
if (u.getTag() != tag) {
- return base::unexpected(BAD_VALUE);
+ return ::android::base::unexpected(::android::BAD_VALUE);
}
return u.template get<tag>();
}
@@ -275,7 +282,11 @@
*/
template <typename T>
bool isValidEnum(T value) {
- constexpr android::enum_range<T> er{};
+#if defined(BACKEND_NDK)
+ constexpr ndk::enum_range<T> er{};
+#else
+ constexpr ::android::enum_range<T> er{};
+#endif
return std::find(er.begin(), er.end(), value) != er.end();
}
@@ -294,7 +305,7 @@
}
/**
- * Return the equivalent Android status_t from a binder exception code.
+ * Return the equivalent Android ::android::status_t from a binder exception code.
*
* Generally one should use statusTFromBinderStatus() instead.
*
@@ -304,33 +315,33 @@
* Note: for EX_TRANSACTION_FAILED and EX_SERVICE_SPECIFIC a more detailed error code
* can be found from transactionError() or serviceSpecificErrorCode().
*/
-static inline status_t statusTFromExceptionCode(int32_t exceptionCode) {
+static inline ::android::status_t statusTFromExceptionCode(int32_t exceptionCode) {
using namespace ::android::binder;
switch (exceptionCode) {
case Status::EX_NONE:
- return OK;
- case Status::EX_SECURITY: // Java SecurityException, rethrows locally in Java
- return PERMISSION_DENIED;
- case Status::EX_BAD_PARCELABLE: // Java BadParcelableException, rethrows in Java
- case Status::EX_ILLEGAL_ARGUMENT: // Java IllegalArgumentException, rethrows in Java
- case Status::EX_NULL_POINTER: // Java NullPointerException, rethrows in Java
- return BAD_VALUE;
- case Status::EX_ILLEGAL_STATE: // Java IllegalStateException, rethrows in Java
- case Status::EX_UNSUPPORTED_OPERATION: // Java UnsupportedOperationException, rethrows
- return INVALID_OPERATION;
+ return ::android::OK;
+ case Status::EX_SECURITY: // Java SecurityException, rethrows locally in Java
+ return ::android::PERMISSION_DENIED;
+ case Status::EX_BAD_PARCELABLE: // Java BadParcelableException, rethrows in Java
+ case Status::EX_ILLEGAL_ARGUMENT: // Java IllegalArgumentException, rethrows in Java
+ case Status::EX_NULL_POINTER: // Java NullPointerException, rethrows in Java
+ return ::android::BAD_VALUE;
+ case Status::EX_ILLEGAL_STATE: // Java IllegalStateException, rethrows in Java
+ case Status::EX_UNSUPPORTED_OPERATION: // Java UnsupportedOperationException, rethrows
+ return ::android::INVALID_OPERATION;
case Status::EX_HAS_REPLY_HEADER: // Native strictmode violation
- case Status::EX_PARCELABLE: // Java bootclass loader (not standard exception), rethrows
- case Status::EX_NETWORK_MAIN_THREAD: // Java NetworkOnMainThreadException, rethrows
+ case Status::EX_PARCELABLE: // Java bootclass loader (not standard exception), rethrows
+ case Status::EX_NETWORK_MAIN_THREAD: // Java NetworkOnMainThreadException, rethrows
case Status::EX_TRANSACTION_FAILED: // Native - see error code
- case Status::EX_SERVICE_SPECIFIC: // Java ServiceSpecificException,
- // rethrows in Java with integer error code
- return UNKNOWN_ERROR;
+ case Status::EX_SERVICE_SPECIFIC: // Java ServiceSpecificException,
+ // rethrows in Java with integer error code
+ return ::android::UNKNOWN_ERROR;
}
- return UNKNOWN_ERROR;
+ return ::android::UNKNOWN_ERROR;
}
/**
- * Return the equivalent Android status_t from a binder status.
+ * Return the equivalent Android ::android::status_t from a binder status.
*
* Used to handle errors from a AIDL method declaration
*
@@ -340,8 +351,8 @@
*
* return_type method(type0 param0, ...)
*/
-static inline status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
- return status.isOk() ? OK // check OK,
+static inline ::android::status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
+ return status.isOk() ? ::android::OK // check ::android::OK,
: status.serviceSpecificErrorCode() // service-side error, not standard Java exception
// (fromServiceSpecificError)
?: status.transactionError() // a native binder transaction error (fromStatusT)
@@ -356,23 +367,23 @@
* where Java callers expect an exception, not an integer return value.
*/
static inline ::android::binder::Status binderStatusFromStatusT(
- status_t status, const char *optionalMessage = nullptr) {
+ ::android::status_t status, const char *optionalMessage = nullptr) {
const char * const emptyIfNull = optionalMessage == nullptr ? "" : optionalMessage;
// From binder::Status instructions:
// Prefer a generic exception code when possible, then a service specific
- // code, and finally a status_t for low level failures or legacy support.
+ // code, and finally a ::android::status_t for low level failures or legacy support.
// Exception codes and service specific errors map to nicer exceptions for
// Java clients.
using namespace ::android::binder;
switch (status) {
- case OK:
+ case ::android::OK:
return Status::ok();
- case PERMISSION_DENIED: // throw SecurityException on Java side
+ case ::android::PERMISSION_DENIED: // throw SecurityException on Java side
return Status::fromExceptionCode(Status::EX_SECURITY, emptyIfNull);
- case BAD_VALUE: // throw IllegalArgumentException on Java side
+ case ::android::BAD_VALUE: // throw IllegalArgumentException on Java side
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, emptyIfNull);
- case INVALID_OPERATION: // throw IllegalStateException on Java side
+ case ::android::INVALID_OPERATION: // throw IllegalStateException on Java side
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, emptyIfNull);
}
@@ -387,3 +398,7 @@
} // namespace aidl_utils
} // namespace android
+
+#if defined(BACKEND_NDK)
+} // namespace aidl
+#endif
\ No newline at end of file
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 90d51fd..f75e58d 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -42,9 +42,6 @@
using media::audio::common::AudioDeviceAddress;
using media::audio::common::AudioDeviceDescription;
using media::audio::common::AudioDeviceType;
-using media::audio::common::AudioEncapsulationMetadataType;
-using media::audio::common::AudioEncapsulationMode;
-using media::audio::common::AudioEncapsulationType;
using media::audio::common::AudioFormatDescription;
using media::audio::common::AudioFormatType;
using media::audio::common::AudioGain;
@@ -138,127 +135,6 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Converters
-status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
- if (aidl.size() > maxSize - 1) {
- return BAD_VALUE;
- }
- aidl.copy(dest, aidl.size());
- dest[aidl.size()] = '\0';
- return OK;
-}
-
-ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
- if (legacy == nullptr) {
- return unexpected(BAD_VALUE);
- }
- if (strnlen(legacy, maxSize) == maxSize) {
- // No null-terminator.
- return unexpected(BAD_VALUE);
- }
- return std::string(legacy);
-}
-
-ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
- return convertReinterpret<audio_module_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
- return convertReinterpret<audio_io_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
- return convertReinterpret<audio_port_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
- return convertReinterpret<audio_patch_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
- return convertReinterpret<audio_unique_id_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl) {
- return convertReinterpret<audio_hw_sync_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
- return convertReinterpret<pid_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
- return convertReinterpret<uid_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
- return String16(aidl.data(), aidl.size());
-}
-
-ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
- return std::string(String8(legacy).c_str());
-}
-
-// TODO b/182392769: create an optional -> optional util
-ConversionResult<std::optional<String16>>
-aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl) {
- if (!aidl.has_value()) {
- return std::nullopt;
- }
- ConversionResult<String16> conversion =
- VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.value()));
- return conversion.value();
-}
-
-ConversionResult<std::optional<std::string_view>>
-legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy) {
- if (!legacy.has_value()) {
- return std::nullopt;
- }
- ConversionResult<std::string> conversion =
- VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.value()));
- return conversion.value();
-}
-
-ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
- return String8(aidl.data(), aidl.size());
-}
-
-ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
- return std::string(legacy.c_str());
-}
-
ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
media::AudioIoConfigEvent aidl) {
switch (aidl) {
@@ -365,1477 +241,6 @@
return unexpected(BAD_VALUE);
}
-namespace {
-
-namespace detail {
-using AudioChannelBitPair = std::pair<audio_channel_mask_t, int>;
-using AudioChannelBitPairs = std::vector<AudioChannelBitPair>;
-using AudioChannelPair = std::pair<audio_channel_mask_t, AudioChannelLayout>;
-using AudioChannelPairs = std::vector<AudioChannelPair>;
-using AudioDevicePair = std::pair<audio_devices_t, AudioDeviceDescription>;
-using AudioDevicePairs = std::vector<AudioDevicePair>;
-using AudioFormatPair = std::pair<audio_format_t, AudioFormatDescription>;
-using AudioFormatPairs = std::vector<AudioFormatPair>;
-}
-
-const detail::AudioChannelBitPairs& getInAudioChannelBits() {
- static const detail::AudioChannelBitPairs pairs = {
- { AUDIO_CHANNEL_IN_LEFT, AudioChannelLayout::CHANNEL_FRONT_LEFT },
- { AUDIO_CHANNEL_IN_RIGHT, AudioChannelLayout::CHANNEL_FRONT_RIGHT },
- // AUDIO_CHANNEL_IN_FRONT is at the end
- { AUDIO_CHANNEL_IN_BACK, AudioChannelLayout::CHANNEL_BACK_CENTER },
- // AUDIO_CHANNEL_IN_*_PROCESSED not supported
- // AUDIO_CHANNEL_IN_PRESSURE not supported
- // AUDIO_CHANNEL_IN_*_AXIS not supported
- // AUDIO_CHANNEL_IN_VOICE_* not supported
- { AUDIO_CHANNEL_IN_BACK_LEFT, AudioChannelLayout::CHANNEL_BACK_LEFT },
- { AUDIO_CHANNEL_IN_BACK_RIGHT, AudioChannelLayout::CHANNEL_BACK_RIGHT },
- { AUDIO_CHANNEL_IN_CENTER, AudioChannelLayout::CHANNEL_FRONT_CENTER },
- { AUDIO_CHANNEL_IN_LOW_FREQUENCY, AudioChannelLayout::CHANNEL_LOW_FREQUENCY },
- { AUDIO_CHANNEL_IN_TOP_LEFT, AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT },
- { AUDIO_CHANNEL_IN_TOP_RIGHT, AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT },
- // When going from aidl to legacy, IN_CENTER is used
- { AUDIO_CHANNEL_IN_FRONT, AudioChannelLayout::CHANNEL_FRONT_CENTER }
- };
- return pairs;
-}
-
-const detail::AudioChannelPairs& getInAudioChannelPairs() {
- static const detail::AudioChannelPairs pairs = {
-#define DEFINE_INPUT_LAYOUT(n) \
- { \
- AUDIO_CHANNEL_IN_##n, \
- AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
- AudioChannelLayout::LAYOUT_##n) \
- }
-
- DEFINE_INPUT_LAYOUT(MONO),
- DEFINE_INPUT_LAYOUT(STEREO),
- DEFINE_INPUT_LAYOUT(FRONT_BACK),
- // AUDIO_CHANNEL_IN_6 not supported
- DEFINE_INPUT_LAYOUT(2POINT0POINT2),
- DEFINE_INPUT_LAYOUT(2POINT1POINT2),
- DEFINE_INPUT_LAYOUT(3POINT0POINT2),
- DEFINE_INPUT_LAYOUT(3POINT1POINT2),
- DEFINE_INPUT_LAYOUT(5POINT1)
-#undef DEFINE_INPUT_LAYOUT
- };
- return pairs;
-}
-
-const detail::AudioChannelBitPairs& getOutAudioChannelBits() {
- static const detail::AudioChannelBitPairs pairs = {
-#define DEFINE_OUTPUT_BITS(n) \
- { AUDIO_CHANNEL_OUT_##n, AudioChannelLayout::CHANNEL_##n }
-
- DEFINE_OUTPUT_BITS(FRONT_LEFT),
- DEFINE_OUTPUT_BITS(FRONT_RIGHT),
- DEFINE_OUTPUT_BITS(FRONT_CENTER),
- DEFINE_OUTPUT_BITS(LOW_FREQUENCY),
- DEFINE_OUTPUT_BITS(BACK_LEFT),
- DEFINE_OUTPUT_BITS(BACK_RIGHT),
- DEFINE_OUTPUT_BITS(FRONT_LEFT_OF_CENTER),
- DEFINE_OUTPUT_BITS(FRONT_RIGHT_OF_CENTER),
- DEFINE_OUTPUT_BITS(BACK_CENTER),
- DEFINE_OUTPUT_BITS(SIDE_LEFT),
- DEFINE_OUTPUT_BITS(SIDE_RIGHT),
- DEFINE_OUTPUT_BITS(TOP_CENTER),
- DEFINE_OUTPUT_BITS(TOP_FRONT_LEFT),
- DEFINE_OUTPUT_BITS(TOP_FRONT_CENTER),
- DEFINE_OUTPUT_BITS(TOP_FRONT_RIGHT),
- DEFINE_OUTPUT_BITS(TOP_BACK_LEFT),
- DEFINE_OUTPUT_BITS(TOP_BACK_CENTER),
- DEFINE_OUTPUT_BITS(TOP_BACK_RIGHT),
- DEFINE_OUTPUT_BITS(TOP_SIDE_LEFT),
- DEFINE_OUTPUT_BITS(TOP_SIDE_RIGHT),
- DEFINE_OUTPUT_BITS(BOTTOM_FRONT_LEFT),
- DEFINE_OUTPUT_BITS(BOTTOM_FRONT_CENTER),
- DEFINE_OUTPUT_BITS(BOTTOM_FRONT_RIGHT),
- DEFINE_OUTPUT_BITS(LOW_FREQUENCY_2),
- DEFINE_OUTPUT_BITS(FRONT_WIDE_LEFT),
- DEFINE_OUTPUT_BITS(FRONT_WIDE_RIGHT),
-#undef DEFINE_OUTPUT_BITS
- { AUDIO_CHANNEL_OUT_HAPTIC_A, AudioChannelLayout::CHANNEL_HAPTIC_A },
- { AUDIO_CHANNEL_OUT_HAPTIC_B, AudioChannelLayout::CHANNEL_HAPTIC_B }
- };
- return pairs;
-}
-
-const detail::AudioChannelPairs& getOutAudioChannelPairs() {
- static const detail::AudioChannelPairs pairs = {
-#define DEFINE_OUTPUT_LAYOUT(n) \
- { \
- AUDIO_CHANNEL_OUT_##n, \
- AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
- AudioChannelLayout::LAYOUT_##n) \
- }
-
- DEFINE_OUTPUT_LAYOUT(MONO),
- DEFINE_OUTPUT_LAYOUT(STEREO),
- DEFINE_OUTPUT_LAYOUT(2POINT1),
- DEFINE_OUTPUT_LAYOUT(TRI),
- DEFINE_OUTPUT_LAYOUT(TRI_BACK),
- DEFINE_OUTPUT_LAYOUT(3POINT1),
- DEFINE_OUTPUT_LAYOUT(2POINT0POINT2),
- DEFINE_OUTPUT_LAYOUT(2POINT1POINT2),
- DEFINE_OUTPUT_LAYOUT(3POINT0POINT2),
- DEFINE_OUTPUT_LAYOUT(3POINT1POINT2),
- DEFINE_OUTPUT_LAYOUT(QUAD),
- DEFINE_OUTPUT_LAYOUT(QUAD_SIDE),
- DEFINE_OUTPUT_LAYOUT(SURROUND),
- DEFINE_OUTPUT_LAYOUT(PENTA),
- DEFINE_OUTPUT_LAYOUT(5POINT1),
- DEFINE_OUTPUT_LAYOUT(5POINT1_SIDE),
- DEFINE_OUTPUT_LAYOUT(5POINT1POINT2),
- DEFINE_OUTPUT_LAYOUT(5POINT1POINT4),
- DEFINE_OUTPUT_LAYOUT(6POINT1),
- DEFINE_OUTPUT_LAYOUT(7POINT1),
- DEFINE_OUTPUT_LAYOUT(7POINT1POINT2),
- DEFINE_OUTPUT_LAYOUT(7POINT1POINT4),
- DEFINE_OUTPUT_LAYOUT(13POINT_360RA),
- DEFINE_OUTPUT_LAYOUT(22POINT2),
- DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_A),
- DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_A),
- DEFINE_OUTPUT_LAYOUT(HAPTIC_AB),
- DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_AB),
- DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_AB)
-#undef DEFINE_OUTPUT_LAYOUT
- };
- return pairs;
-}
-
-const detail::AudioChannelPairs& getVoiceAudioChannelPairs() {
- static const detail::AudioChannelPairs pairs = {
-#define DEFINE_VOICE_LAYOUT(n) \
- { \
- AUDIO_CHANNEL_IN_VOICE_##n, \
- AudioChannelLayout::make<AudioChannelLayout::Tag::voiceMask>( \
- AudioChannelLayout::VOICE_##n) \
- }
- DEFINE_VOICE_LAYOUT(UPLINK_MONO),
- DEFINE_VOICE_LAYOUT(DNLINK_MONO),
- DEFINE_VOICE_LAYOUT(CALL_MONO)
-#undef DEFINE_VOICE_LAYOUT
- };
- return pairs;
-}
-
-AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
- const std::string& connection = "") {
- AudioDeviceDescription result;
- result.type = type;
- result.connection = connection;
- return result;
-}
-
-void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
- audio_devices_t inputType, audio_devices_t outputType,
- AudioDeviceType inType, AudioDeviceType outType,
- const std::string& connection = "") {
- pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
- pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
-}
-
-const detail::AudioDevicePairs& getAudioDevicePairs() {
- static const detail::AudioDevicePairs pairs = []() {
- detail::AudioDevicePairs pairs = {{
- {
- AUDIO_DEVICE_NONE, AudioDeviceDescription{}
- },
- {
- AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER_EARPIECE)
- },
- {
- AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER)
- },
- {
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
- AudioDeviceType::OUT_HEADPHONE,
- AudioDeviceDescription::CONNECTION_ANALOG())
- },
- {
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
- AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_BT_SCO())
- },
- {
- AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
- AudioDeviceType::OUT_CARKIT,
- AudioDeviceDescription::CONNECTION_BT_SCO())
- },
- {
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
- AudioDeviceType::OUT_HEADPHONE,
- AudioDeviceDescription::CONNECTION_BT_A2DP())
- },
- {
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER,
- AudioDeviceDescription::CONNECTION_BT_A2DP())
- },
- {
- AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
- AudioDeviceType::OUT_TELEPHONY_TX)
- },
- {
- AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
- AudioDeviceType::OUT_LINE_AUX)
- },
- {
- AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER_SAFE)
- },
- {
- AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
- AudioDeviceType::OUT_HEARING_AID,
- AudioDeviceDescription::CONNECTION_WIRELESS())
- },
- {
- AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
- AudioDeviceType::OUT_ECHO_CANCELLER)
- },
- {
- AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SPEAKER,
- AudioDeviceDescription::CONNECTION_BT_LE())
- },
- {
- AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
- AudioDeviceType::OUT_BROADCAST,
- AudioDeviceDescription::CONNECTION_BT_LE())
- },
- // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
- {
- AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
- AudioDeviceType::IN_MICROPHONE)
- },
- {
- AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
- AudioDeviceType::IN_MICROPHONE_BACK)
- },
- {
- AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
- AudioDeviceType::IN_TELEPHONY_RX)
- },
- {
- AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
- AudioDeviceType::IN_TV_TUNER)
- },
- {
- AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
- AudioDeviceType::IN_LOOPBACK)
- },
- {
- AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
- AudioDeviceType::IN_DEVICE,
- AudioDeviceDescription::CONNECTION_BT_LE())
- },
- {
- AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
- AudioDeviceType::IN_ECHO_REFERENCE)
- }
- }};
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
- AudioDeviceType::IN_DEFAULT, AudioDeviceType::OUT_DEFAULT);
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
- AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_ANALOG());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
- AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_BT_SCO());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_HDMI());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX);
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
- AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
- AudioDeviceDescription::CONNECTION_ANALOG());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
- AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
- AudioDeviceDescription::CONNECTION_USB());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
- AudioDeviceType::IN_ACCESSORY, AudioDeviceType::OUT_ACCESSORY,
- AudioDeviceDescription::CONNECTION_USB());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_USB());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
- AudioDeviceType::IN_FM_TUNER, AudioDeviceType::OUT_FM);
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_ANALOG());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_SPDIF());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_BT_A2DP());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_IP_V4());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_BUS());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
- AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
- AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_USB());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_HDMI_ARC());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
- AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
- AudioDeviceDescription::CONNECTION_HDMI_EARC());
- append_AudioDeviceDescription(pairs,
- AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
- AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
- AudioDeviceDescription::CONNECTION_BT_LE());
- return pairs;
- }();
- return pairs;
-}
-
-AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
- AudioFormatDescription result;
- result.type = type;
- return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
- auto result = make_AudioFormatDescription(AudioFormatType::PCM);
- result.pcm = pcm;
- return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
- AudioFormatDescription result;
- result.encoding = encoding;
- return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType transport,
- const std::string& encoding) {
- auto result = make_AudioFormatDescription(encoding);
- result.pcm = transport;
- return result;
-}
-
-const detail::AudioFormatPairs& getAudioFormatPairs() {
- static const detail::AudioFormatPairs pairs = {{
- {
- AUDIO_FORMAT_INVALID,
- make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID)
- },
- {
- AUDIO_FORMAT_DEFAULT, AudioFormatDescription{}
- },
- {
- AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(PcmType::INT_16_BIT)
- },
- {
- AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(PcmType::UINT_8_BIT)
- },
- {
- AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(PcmType::INT_32_BIT)
- },
- {
- AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(PcmType::FIXED_Q_8_24)
- },
- {
- AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(PcmType::FLOAT_32_BIT)
- },
- {
- AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(PcmType::INT_24_BIT)
- },
- {
- AUDIO_FORMAT_MP3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG)
- },
- {
- AUDIO_FORMAT_AMR_NB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_NB)
- },
- {
- AUDIO_FORMAT_AMR_WB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB)
- },
- {
- AUDIO_FORMAT_AAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_MP4)
- },
- {
- AUDIO_FORMAT_AAC_MAIN, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_MAIN)
- },
- {
- AUDIO_FORMAT_AAC_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LC)
- },
- {
- AUDIO_FORMAT_AAC_SSR, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_SSR)
- },
- {
- AUDIO_FORMAT_AAC_LTP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LTP)
- },
- {
- AUDIO_FORMAT_AAC_HE_V1, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1)
- },
- {
- AUDIO_FORMAT_AAC_SCALABLE,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE)
- },
- {
- AUDIO_FORMAT_AAC_ERLC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ERLC)
- },
- {
- AUDIO_FORMAT_AAC_LD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LD)
- },
- {
- AUDIO_FORMAT_AAC_HE_V2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2)
- },
- {
- AUDIO_FORMAT_AAC_ELD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ELD)
- },
- {
- AUDIO_FORMAT_AAC_XHE, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_XHE)
- },
- // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
- // ago.
- {
- AUDIO_FORMAT_VORBIS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_VORBIS)
- },
- {
- AUDIO_FORMAT_OPUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_OPUS)
- },
- {
- AUDIO_FORMAT_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC3)
- },
- {
- AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3)
- },
- {
- AUDIO_FORMAT_E_AC3_JOC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3_JOC)
- },
- {
- AUDIO_FORMAT_DTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS)
- },
- {
- AUDIO_FORMAT_DTS_HD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_HD)
- },
- {
- AUDIO_FORMAT_DTS_HD_MA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_HD_MA)
- },
- {
- AUDIO_FORMAT_DTS_UHD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1)
- },
- {
- AUDIO_FORMAT_DTS_UHD_P2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2)
- },
- // In the future, we would like to represent encapsulated bitstreams as
- // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
- // specify the format of the encapsulated bitstream.
- {
- AUDIO_FORMAT_IEC61937,
- make_AudioFormatDescription(PcmType::INT_16_BIT, MEDIA_MIMETYPE_AUDIO_IEC61937)
- },
- {
- AUDIO_FORMAT_DOLBY_TRUEHD,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD)
- },
- {
- AUDIO_FORMAT_EVRC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRC)
- },
- {
- AUDIO_FORMAT_EVRCB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCB)
- },
- {
- AUDIO_FORMAT_EVRCWB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCWB)
- },
- {
- AUDIO_FORMAT_EVRCNW, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCNW)
- },
- {
- AUDIO_FORMAT_AAC_ADIF, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADIF)
- },
- {
- AUDIO_FORMAT_WMA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_WMA)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")
- },
- {
- AUDIO_FORMAT_AMR_WB_PLUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)
- },
- {
- AUDIO_FORMAT_MP2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)
- },
- {
- AUDIO_FORMAT_QCELP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_QCELP)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")
- },
- {
- AUDIO_FORMAT_FLAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_FLAC)
- },
- {
- AUDIO_FORMAT_ALAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_ALAC)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")
- },
- {
- AUDIO_FORMAT_AAC_ADTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_MAIN,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_SSR,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_LTP,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_HE_V1,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_SCALABLE,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_ERLC,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_LD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_HE_V2,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_ELD,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD)
- },
- {
- AUDIO_FORMAT_AAC_ADTS_XHE,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE)
- },
- {
- // Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
- AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")
- },
- {
- AUDIO_FORMAT_APTX, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_APTX)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")
- },
- {
- AUDIO_FORMAT_AC4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC4)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")
- },
- {
- AUDIO_FORMAT_MAT, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_MAT_1_0,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".1.0"))
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_MAT_2_0,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".2.0"))
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_MAT_2_1,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".2.1"))
- },
- {
- AUDIO_FORMAT_AAC_LATM, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC)
- },
- {
- AUDIO_FORMAT_AAC_LATM_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC)
- },
- {
- AUDIO_FORMAT_AAC_LATM_HE_V1,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1)
- },
- {
- AUDIO_FORMAT_AAC_LATM_HE_V2,
- make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APTX_ADAPTIVE, make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")
- },
- {
- AUDIO_FORMAT_MPEGH, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1)
- },
- {
- AUDIO_FORMAT_MPEGH_BL_L3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3)
- },
- {
- AUDIO_FORMAT_MPEGH_BL_L4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4)
- },
- {
- AUDIO_FORMAT_MPEGH_LC_L3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3)
- },
- {
- AUDIO_FORMAT_MPEGH_LC_L4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4)
- },
- {
- AUDIO_FORMAT_IEC60958,
- make_AudioFormatDescription(PcmType::INT_24_BIT, MEDIA_MIMETYPE_AUDIO_IEC60958)
- },
- {
- AUDIO_FORMAT_DRA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DRA)
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APTX_ADAPTIVE_QLEA,
- make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r3")
- },
- {
- // Note: not in the IANA registry.
- AUDIO_FORMAT_APTX_ADAPTIVE_R4,
- make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r4")
- },
- }};
- return pairs;
-}
-
-template<typename S, typename T>
-std::unordered_map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
- std::unordered_map<S, T> result(v.begin(), v.end());
- LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
- return result;
-}
-
-template<typename S, typename T>
-std::unordered_map<S, T> make_DirectMap(
- const std::vector<std::pair<S, T>>& v1, const std::vector<std::pair<S, T>>& v2) {
- std::unordered_map<S, T> result(v1.begin(), v1.end());
- LOG_ALWAYS_FATAL_IF(result.size() != v1.size(), "Duplicate key elements detected in v1");
- result.insert(v2.begin(), v2.end());
- LOG_ALWAYS_FATAL_IF(result.size() != v1.size() + v2.size(),
- "Duplicate key elements detected in v1+v2");
- return result;
-}
-
-template<typename S, typename T>
-std::unordered_map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
- std::unordered_map<T, S> result;
- std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
- [](const std::pair<S, T>& p) {
- return std::make_pair(p.second, p.first);
- });
- LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
- return result;
-}
-
-} // namespace
-
-audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
- int aidlLayout, bool isInput) {
- auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
- const int aidlLayoutInitial = aidlLayout; // for error message
- audio_channel_mask_t legacy = AUDIO_CHANNEL_NONE;
- for (const auto& bitPair : bitMapping) {
- if ((aidlLayout & bitPair.second) == bitPair.second) {
- legacy = static_cast<audio_channel_mask_t>(legacy | bitPair.first);
- aidlLayout &= ~bitPair.second;
- if (aidlLayout == 0) {
- return legacy;
- }
- }
- }
- ALOGE("%s: aidl layout 0x%x contains bits 0x%x that have no match to legacy %s bits",
- __func__, aidlLayoutInitial, aidlLayout, isInput ? "input" : "output");
- return AUDIO_CHANNEL_NONE;
-}
-
-ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
- const AudioChannelLayout& aidl, bool isInput) {
- using ReverseMap = std::unordered_map<AudioChannelLayout, audio_channel_mask_t>;
- using Tag = AudioChannelLayout::Tag;
- static const ReverseMap mIn = make_ReverseMap(getInAudioChannelPairs());
- static const ReverseMap mOut = make_ReverseMap(getOutAudioChannelPairs());
- static const ReverseMap mVoice = make_ReverseMap(getVoiceAudioChannelPairs());
-
- auto convert = [](const AudioChannelLayout& aidl, const ReverseMap& m,
- const char* func, const char* type) -> ConversionResult<audio_channel_mask_t> {
- if (auto it = m.find(aidl); it != m.end()) {
- return it->second;
- } else {
- ALOGW("%s: no legacy %s audio_channel_mask_t found for %s", func, type,
- aidl.toString().c_str());
- return unexpected(BAD_VALUE);
- }
- };
-
- switch (aidl.getTag()) {
- case Tag::none:
- return AUDIO_CHANNEL_NONE;
- case Tag::invalid:
- return AUDIO_CHANNEL_INVALID;
- case Tag::indexMask:
- // Index masks do not have pre-defined values.
- if (const int bits = aidl.get<Tag::indexMask>();
- __builtin_popcount(bits) != 0 &&
- __builtin_popcount(bits) <= AUDIO_CHANNEL_COUNT_MAX) {
- return audio_channel_mask_from_representation_and_bits(
- AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
- } else {
- ALOGE("%s: invalid indexMask value 0x%x in %s",
- __func__, bits, aidl.toString().c_str());
- return unexpected(BAD_VALUE);
- }
- case Tag::layoutMask:
- // The fast path is to find a direct match for some known layout mask.
- if (const auto layoutMatch = convert(aidl, isInput ? mIn : mOut, __func__,
- isInput ? "input" : "output");
- layoutMatch.ok()) {
- return layoutMatch;
- }
- // If a match for a predefined layout wasn't found, make a custom one from bits.
- if (audio_channel_mask_t bitMask =
- aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
- aidl.get<Tag::layoutMask>(), isInput);
- bitMask != AUDIO_CHANNEL_NONE) {
- return bitMask;
- }
- return unexpected(BAD_VALUE);
- case Tag::voiceMask:
- return convert(aidl, mVoice, __func__, "voice");
- }
- ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
- return unexpected(BAD_VALUE);
-}
-
-int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
- audio_channel_mask_t legacy, bool isInput) {
- auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
- const int legacyInitial = legacy; // for error message
- int aidlLayout = 0;
- for (const auto& bitPair : bitMapping) {
- if ((legacy & bitPair.first) == bitPair.first) {
- aidlLayout |= bitPair.second;
- legacy = static_cast<audio_channel_mask_t>(legacy & ~bitPair.first);
- if (legacy == 0) {
- return aidlLayout;
- }
- }
- }
- ALOGE("%s: legacy %s audio_channel_mask_t 0x%x contains unrecognized bits 0x%x",
- __func__, isInput ? "input" : "output", legacyInitial, legacy);
- return 0;
-}
-
-ConversionResult<AudioChannelLayout> legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
- audio_channel_mask_t legacy, bool isInput) {
- using DirectMap = std::unordered_map<audio_channel_mask_t, AudioChannelLayout>;
- using Tag = AudioChannelLayout::Tag;
- static const DirectMap mInAndVoice = make_DirectMap(
- getInAudioChannelPairs(), getVoiceAudioChannelPairs());
- static const DirectMap mOut = make_DirectMap(getOutAudioChannelPairs());
-
- auto convert = [](const audio_channel_mask_t legacy, const DirectMap& m,
- const char* func, const char* type) -> ConversionResult<AudioChannelLayout> {
- if (auto it = m.find(legacy); it != m.end()) {
- return it->second;
- } else {
- ALOGW("%s: no AudioChannelLayout found for legacy %s audio_channel_mask_t value 0x%x",
- func, type, legacy);
- return unexpected(BAD_VALUE);
- }
- };
-
- if (legacy == AUDIO_CHANNEL_NONE) {
- return AudioChannelLayout{};
- } else if (legacy == AUDIO_CHANNEL_INVALID) {
- return AudioChannelLayout::make<Tag::invalid>(0);
- }
-
- const audio_channel_representation_t repr = audio_channel_mask_get_representation(legacy);
- if (repr == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
- if (audio_channel_mask_is_valid(legacy)) {
- const int indexMask = VALUE_OR_RETURN(
- convertIntegral<int>(audio_channel_mask_get_bits(legacy)));
- return AudioChannelLayout::make<Tag::indexMask>(indexMask);
- } else {
- ALOGE("%s: legacy audio_channel_mask_t value 0x%x is invalid", __func__, legacy);
- return unexpected(BAD_VALUE);
- }
- } else if (repr == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
- // The fast path is to find a direct match for some known layout mask.
- if (const auto layoutMatch = convert(legacy, isInput ? mInAndVoice : mOut, __func__,
- isInput ? "input / voice" : "output");
- layoutMatch.ok()) {
- return layoutMatch;
- }
- // If a match for a predefined layout wasn't found, make a custom one from bits,
- // rejecting those with voice channel bits.
- if (!isInput ||
- (legacy & (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK)) == 0) {
- if (int bitMaskLayout =
- legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
- legacy, isInput);
- bitMaskLayout != 0) {
- return AudioChannelLayout::make<Tag::layoutMask>(bitMaskLayout);
- }
- } else {
- ALOGE("%s: legacy audio_channel_mask_t value 0x%x contains voice bits",
- __func__, legacy);
- }
- return unexpected(BAD_VALUE);
- }
-
- ALOGE("%s: unknown representation %d in audio_channel_mask_t value 0x%x",
- __func__, repr, legacy);
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
- const AudioDeviceDescription& aidl) {
- static const std::unordered_map<AudioDeviceDescription, audio_devices_t> m =
- make_ReverseMap(getAudioDevicePairs());
- if (auto it = m.find(aidl); it != m.end()) {
- return it->second;
- } else {
- ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
- return unexpected(BAD_VALUE);
- }
-}
-
-ConversionResult<AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
- audio_devices_t legacy) {
- static const std::unordered_map<audio_devices_t, AudioDeviceDescription> m =
- make_DirectMap(getAudioDevicePairs());
- if (auto it = m.find(legacy); it != m.end()) {
- return it->second;
- } else {
- ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
- __func__, legacy);
- return unexpected(BAD_VALUE);
- }
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
- const AudioDevice& aidl,
- audio_devices_t* legacyType, char* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- return aidl2legacy_string(
- aidl.address.get<AudioDeviceAddress::id>(),
- legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
- const AudioDevice& aidl,
- audio_devices_t* legacyType, String8* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
- aidl.address.get<AudioDeviceAddress::id>()));
- return OK;
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
- const AudioDevice& aidl,
- audio_devices_t* legacyType, std::string* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
- return OK;
-}
-
-ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
- audio_devices_t legacyType, const char* legacyAddress) {
- AudioDevice aidl;
- aidl.type = VALUE_OR_RETURN(
- legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
- const std::string aidl_id = VALUE_OR_RETURN(
- legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
- aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
- return aidl;
-}
-
-ConversionResult<AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
- audio_devices_t legacyType, const String8& legacyAddress) {
- AudioDevice aidl;
- aidl.type = VALUE_OR_RETURN(
- legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
- const std::string aidl_id = VALUE_OR_RETURN(
- legacy2aidl_String8_string(legacyAddress));
- aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
- return aidl;
-}
-
-ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
- const AudioFormatDescription& aidl) {
- static const std::unordered_map<AudioFormatDescription, audio_format_t> m =
- make_ReverseMap(getAudioFormatPairs());
- if (auto it = m.find(aidl); it != m.end()) {
- return it->second;
- } else {
- ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
- return unexpected(BAD_VALUE);
- }
-}
-
-ConversionResult<AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
- audio_format_t legacy) {
- static const std::unordered_map<audio_format_t, AudioFormatDescription> m =
- make_DirectMap(getAudioFormatPairs());
- if (auto it = m.find(legacy); it != m.end()) {
- return it->second;
- } else {
- ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
- __func__, legacy);
- return unexpected(BAD_VALUE);
- }
-}
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(
- AudioGainMode aidl) {
- switch (aidl) {
- case AudioGainMode::JOINT:
- return AUDIO_GAIN_MODE_JOINT;
- case AudioGainMode::CHANNELS:
- return AUDIO_GAIN_MODE_CHANNELS;
- case AudioGainMode::RAMP:
- return AUDIO_GAIN_MODE_RAMP;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(
- audio_gain_mode_t legacy) {
- switch (legacy) {
- case AUDIO_GAIN_MODE_JOINT:
- return AudioGainMode::JOINT;
- case AUDIO_GAIN_MODE_CHANNELS:
- return AudioGainMode::CHANNELS;
- case AUDIO_GAIN_MODE_RAMP:
- return AudioGainMode::RAMP;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
- return convertBitmask<audio_gain_mode_t, int32_t, audio_gain_mode_t, AudioGainMode>(
- aidl, aidl2legacy_AudioGainMode_audio_gain_mode_t,
- // AudioGainMode is index-based.
- indexToEnum_index<AudioGainMode>,
- // AUDIO_GAIN_MODE_* constants are mask-based.
- enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
- return convertBitmask<int32_t, audio_gain_mode_t, AudioGainMode, audio_gain_mode_t>(
- legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
- // AUDIO_GAIN_MODE_* constants are mask-based.
- indexToEnum_bitmask<audio_gain_mode_t>,
- // AudioGainMode is index-based.
- enumToMask_index<int32_t, AudioGainMode>);
-}
-
-ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
- const AudioGainConfig& aidl, bool isInput) {
- audio_gain_config legacy;
- legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
- legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
- legacy.channel_mask = VALUE_OR_RETURN(
- aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
- const bool isJoint = bitmaskIsSet(aidl.mode, AudioGainMode::JOINT);
- size_t numValues = isJoint ? 1
- : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
- : audio_channel_count_from_out_mask(legacy.channel_mask);
- if (aidl.values.size() != numValues || aidl.values.size() > std::size(legacy.values)) {
- return unexpected(BAD_VALUE);
- }
- for (size_t i = 0; i < numValues; ++i) {
- legacy.values[i] = VALUE_OR_RETURN(convertIntegral<int>(aidl.values[i]));
- }
- legacy.ramp_duration_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.rampDurationMs));
- return legacy;
-}
-
-ConversionResult<AudioGainConfig> legacy2aidl_audio_gain_config_AudioGainConfig(
- const audio_gain_config& legacy, bool isInput) {
- AudioGainConfig aidl;
- aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
- aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
- aidl.channelMask = VALUE_OR_RETURN(
- legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
- const bool isJoint = (legacy.mode & AUDIO_GAIN_MODE_JOINT) != 0;
- size_t numValues = isJoint ? 1
- : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
- : audio_channel_count_from_out_mask(legacy.channel_mask);
- aidl.values.resize(numValues);
- for (size_t i = 0; i < numValues; ++i) {
- aidl.values[i] = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.values[i]));
- }
- aidl.rampDurationMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.ramp_duration_ms));
- return aidl;
-}
-
-ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
- AudioInputFlags aidl) {
- switch (aidl) {
- case AudioInputFlags::FAST:
- return AUDIO_INPUT_FLAG_FAST;
- case AudioInputFlags::HW_HOTWORD:
- return AUDIO_INPUT_FLAG_HW_HOTWORD;
- case AudioInputFlags::RAW:
- return AUDIO_INPUT_FLAG_RAW;
- case AudioInputFlags::SYNC:
- return AUDIO_INPUT_FLAG_SYNC;
- case AudioInputFlags::MMAP_NOIRQ:
- return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
- case AudioInputFlags::VOIP_TX:
- return AUDIO_INPUT_FLAG_VOIP_TX;
- case AudioInputFlags::HW_AV_SYNC:
- return AUDIO_INPUT_FLAG_HW_AV_SYNC;
- case AudioInputFlags::DIRECT:
- return AUDIO_INPUT_FLAG_DIRECT;
- case AudioInputFlags::ULTRASOUND:
- return AUDIO_INPUT_FLAG_ULTRASOUND;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
- audio_input_flags_t legacy) {
- switch (legacy) {
- case AUDIO_INPUT_FLAG_NONE:
- break; // shouldn't get here. must be listed -Werror,-Wswitch
- case AUDIO_INPUT_FLAG_FAST:
- return AudioInputFlags::FAST;
- case AUDIO_INPUT_FLAG_HW_HOTWORD:
- return AudioInputFlags::HW_HOTWORD;
- case AUDIO_INPUT_FLAG_RAW:
- return AudioInputFlags::RAW;
- case AUDIO_INPUT_FLAG_SYNC:
- return AudioInputFlags::SYNC;
- case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
- return AudioInputFlags::MMAP_NOIRQ;
- case AUDIO_INPUT_FLAG_VOIP_TX:
- return AudioInputFlags::VOIP_TX;
- case AUDIO_INPUT_FLAG_HW_AV_SYNC:
- return AudioInputFlags::HW_AV_SYNC;
- case AUDIO_INPUT_FLAG_DIRECT:
- return AudioInputFlags::DIRECT;
- case AUDIO_INPUT_FLAG_ULTRASOUND:
- return AudioInputFlags::ULTRASOUND;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
- AudioOutputFlags aidl) {
- switch (aidl) {
- case AudioOutputFlags::DIRECT:
- return AUDIO_OUTPUT_FLAG_DIRECT;
- case AudioOutputFlags::PRIMARY:
- return AUDIO_OUTPUT_FLAG_PRIMARY;
- case AudioOutputFlags::FAST:
- return AUDIO_OUTPUT_FLAG_FAST;
- case AudioOutputFlags::DEEP_BUFFER:
- return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
- case AudioOutputFlags::COMPRESS_OFFLOAD:
- return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
- case AudioOutputFlags::NON_BLOCKING:
- return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
- case AudioOutputFlags::HW_AV_SYNC:
- return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
- case AudioOutputFlags::TTS:
- return AUDIO_OUTPUT_FLAG_TTS;
- case AudioOutputFlags::RAW:
- return AUDIO_OUTPUT_FLAG_RAW;
- case AudioOutputFlags::SYNC:
- return AUDIO_OUTPUT_FLAG_SYNC;
- case AudioOutputFlags::IEC958_NONAUDIO:
- return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
- case AudioOutputFlags::DIRECT_PCM:
- return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
- case AudioOutputFlags::MMAP_NOIRQ:
- return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
- case AudioOutputFlags::VOIP_RX:
- return AUDIO_OUTPUT_FLAG_VOIP_RX;
- case AudioOutputFlags::INCALL_MUSIC:
- return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
- case AudioOutputFlags::GAPLESS_OFFLOAD:
- return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
- case AudioOutputFlags::ULTRASOUND:
- return AUDIO_OUTPUT_FLAG_ULTRASOUND;
- case AudioOutputFlags::SPATIALIZER:
- return AUDIO_OUTPUT_FLAG_SPATIALIZER;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
- audio_output_flags_t legacy) {
- switch (legacy) {
- case AUDIO_OUTPUT_FLAG_NONE:
- break; // shouldn't get here. must be listed -Werror,-Wswitch
- case AUDIO_OUTPUT_FLAG_DIRECT:
- return AudioOutputFlags::DIRECT;
- case AUDIO_OUTPUT_FLAG_PRIMARY:
- return AudioOutputFlags::PRIMARY;
- case AUDIO_OUTPUT_FLAG_FAST:
- return AudioOutputFlags::FAST;
- case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
- return AudioOutputFlags::DEEP_BUFFER;
- case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
- return AudioOutputFlags::COMPRESS_OFFLOAD;
- case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
- return AudioOutputFlags::NON_BLOCKING;
- case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
- return AudioOutputFlags::HW_AV_SYNC;
- case AUDIO_OUTPUT_FLAG_TTS:
- return AudioOutputFlags::TTS;
- case AUDIO_OUTPUT_FLAG_RAW:
- return AudioOutputFlags::RAW;
- case AUDIO_OUTPUT_FLAG_SYNC:
- return AudioOutputFlags::SYNC;
- case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
- return AudioOutputFlags::IEC958_NONAUDIO;
- case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
- return AudioOutputFlags::DIRECT_PCM;
- case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
- return AudioOutputFlags::MMAP_NOIRQ;
- case AUDIO_OUTPUT_FLAG_VOIP_RX:
- return AudioOutputFlags::VOIP_RX;
- case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
- return AudioOutputFlags::INCALL_MUSIC;
- case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
- return AudioOutputFlags::GAPLESS_OFFLOAD;
- case AUDIO_OUTPUT_FLAG_ULTRASOUND:
- return AudioOutputFlags::ULTRASOUND;
- case AUDIO_OUTPUT_FLAG_SPATIALIZER:
- return AudioOutputFlags::SPATIALIZER;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
- int32_t aidl) {
- using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
-
- LegacyMask converted = VALUE_OR_RETURN(
- (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
- aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
- indexToEnum_index<AudioInputFlags>,
- enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
- return static_cast<audio_input_flags_t>(converted);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
- audio_input_flags_t legacy) {
- using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
-
- LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
- return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
- legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
- indexToEnum_bitmask<audio_input_flags_t>,
- enumToMask_index<int32_t, AudioInputFlags>);
-}
-
-ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
- int32_t aidl) {
- return convertBitmask<audio_output_flags_t,
- int32_t,
- audio_output_flags_t,
- AudioOutputFlags>(
- aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
- indexToEnum_index<AudioOutputFlags>,
- enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
- audio_output_flags_t legacy) {
- using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
-
- LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
- return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
- legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
- indexToEnum_bitmask<audio_output_flags_t>,
- enumToMask_index<int32_t, AudioOutputFlags>);
-}
-
-ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
- const AudioIoFlags& aidl, bool isInput) {
- audio_io_flags legacy;
- if (isInput) {
- legacy.input = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_input_flags_t_mask(
- VALUE_OR_RETURN(UNION_GET(aidl, input))));
- } else {
- legacy.output = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_output_flags_t_mask(
- VALUE_OR_RETURN(UNION_GET(aidl, output))));
- }
- return legacy;
-}
-
-ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
- const audio_io_flags& legacy, bool isInput) {
- AudioIoFlags aidl;
- if (isInput) {
- UNION_SET(aidl, input,
- VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
- } else {
- UNION_SET(aidl, output,
- VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
- }
- return aidl;
-}
-
-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;
- 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) {
- 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;
-}
-
-ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
- AudioStreamType aidl) {
- switch (aidl) {
- case AudioStreamType::INVALID:
- break; // return error
- case AudioStreamType::SYS_RESERVED_DEFAULT:
- return AUDIO_STREAM_DEFAULT;
- case AudioStreamType::VOICE_CALL:
- return AUDIO_STREAM_VOICE_CALL;
- case AudioStreamType::SYSTEM:
- return AUDIO_STREAM_SYSTEM;
- case AudioStreamType::RING:
- return AUDIO_STREAM_RING;
- case AudioStreamType::MUSIC:
- return AUDIO_STREAM_MUSIC;
- case AudioStreamType::ALARM:
- return AUDIO_STREAM_ALARM;
- case AudioStreamType::NOTIFICATION:
- return AUDIO_STREAM_NOTIFICATION;
- case AudioStreamType::BLUETOOTH_SCO:
- return AUDIO_STREAM_BLUETOOTH_SCO;
- case AudioStreamType::ENFORCED_AUDIBLE:
- return AUDIO_STREAM_ENFORCED_AUDIBLE;
- case AudioStreamType::DTMF:
- return AUDIO_STREAM_DTMF;
- case AudioStreamType::TTS:
- return AUDIO_STREAM_TTS;
- case AudioStreamType::ACCESSIBILITY:
- return AUDIO_STREAM_ACCESSIBILITY;
- case AudioStreamType::ASSISTANT:
- return AUDIO_STREAM_ASSISTANT;
- case AudioStreamType::SYS_RESERVED_REROUTING:
- return AUDIO_STREAM_REROUTING;
- case AudioStreamType::SYS_RESERVED_PATCH:
- return AUDIO_STREAM_PATCH;
- case AudioStreamType::CALL_ASSISTANT:
- return AUDIO_STREAM_CALL_ASSISTANT;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
- audio_stream_type_t legacy) {
- switch (legacy) {
- case AUDIO_STREAM_DEFAULT:
- return AudioStreamType::SYS_RESERVED_DEFAULT;
- case AUDIO_STREAM_VOICE_CALL:
- return AudioStreamType::VOICE_CALL;
- case AUDIO_STREAM_SYSTEM:
- return AudioStreamType::SYSTEM;
- case AUDIO_STREAM_RING:
- return AudioStreamType::RING;
- case AUDIO_STREAM_MUSIC:
- return AudioStreamType::MUSIC;
- case AUDIO_STREAM_ALARM:
- return AudioStreamType::ALARM;
- case AUDIO_STREAM_NOTIFICATION:
- return AudioStreamType::NOTIFICATION;
- case AUDIO_STREAM_BLUETOOTH_SCO:
- return AudioStreamType::BLUETOOTH_SCO;
- case AUDIO_STREAM_ENFORCED_AUDIBLE:
- return AudioStreamType::ENFORCED_AUDIBLE;
- case AUDIO_STREAM_DTMF:
- return AudioStreamType::DTMF;
- case AUDIO_STREAM_TTS:
- return AudioStreamType::TTS;
- case AUDIO_STREAM_ACCESSIBILITY:
- return AudioStreamType::ACCESSIBILITY;
- case AUDIO_STREAM_ASSISTANT:
- return AudioStreamType::ASSISTANT;
- case AUDIO_STREAM_REROUTING:
- return AudioStreamType::SYS_RESERVED_REROUTING;
- case AUDIO_STREAM_PATCH:
- return AudioStreamType::SYS_RESERVED_PATCH;
- case AUDIO_STREAM_CALL_ASSISTANT:
- return AudioStreamType::CALL_ASSISTANT;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
- AudioSource aidl) {
- switch (aidl) {
- case AudioSource::SYS_RESERVED_INVALID:
- return AUDIO_SOURCE_INVALID;
- case AudioSource::DEFAULT:
- return AUDIO_SOURCE_DEFAULT;
- case AudioSource::MIC:
- return AUDIO_SOURCE_MIC;
- case AudioSource::VOICE_UPLINK:
- return AUDIO_SOURCE_VOICE_UPLINK;
- case AudioSource::VOICE_DOWNLINK:
- return AUDIO_SOURCE_VOICE_DOWNLINK;
- case AudioSource::VOICE_CALL:
- return AUDIO_SOURCE_VOICE_CALL;
- case AudioSource::CAMCORDER:
- return AUDIO_SOURCE_CAMCORDER;
- case AudioSource::VOICE_RECOGNITION:
- return AUDIO_SOURCE_VOICE_RECOGNITION;
- case AudioSource::VOICE_COMMUNICATION:
- return AUDIO_SOURCE_VOICE_COMMUNICATION;
- case AudioSource::REMOTE_SUBMIX:
- return AUDIO_SOURCE_REMOTE_SUBMIX;
- case AudioSource::UNPROCESSED:
- return AUDIO_SOURCE_UNPROCESSED;
- case AudioSource::VOICE_PERFORMANCE:
- return AUDIO_SOURCE_VOICE_PERFORMANCE;
- case AudioSource::ULTRASOUND:
- return AUDIO_SOURCE_ULTRASOUND;
- case AudioSource::ECHO_REFERENCE:
- return AUDIO_SOURCE_ECHO_REFERENCE;
- case AudioSource::FM_TUNER:
- return AUDIO_SOURCE_FM_TUNER;
- case AudioSource::HOTWORD:
- return AUDIO_SOURCE_HOTWORD;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioSource> legacy2aidl_audio_source_t_AudioSource(
- audio_source_t legacy) {
- switch (legacy) {
- case AUDIO_SOURCE_INVALID:
- return AudioSource::SYS_RESERVED_INVALID;
- case AUDIO_SOURCE_DEFAULT:
- return AudioSource::DEFAULT;
- case AUDIO_SOURCE_MIC:
- return AudioSource::MIC;
- case AUDIO_SOURCE_VOICE_UPLINK:
- return AudioSource::VOICE_UPLINK;
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- return AudioSource::VOICE_DOWNLINK;
- case AUDIO_SOURCE_VOICE_CALL:
- return AudioSource::VOICE_CALL;
- case AUDIO_SOURCE_CAMCORDER:
- return AudioSource::CAMCORDER;
- case AUDIO_SOURCE_VOICE_RECOGNITION:
- return AudioSource::VOICE_RECOGNITION;
- case AUDIO_SOURCE_VOICE_COMMUNICATION:
- return AudioSource::VOICE_COMMUNICATION;
- case AUDIO_SOURCE_REMOTE_SUBMIX:
- return AudioSource::REMOTE_SUBMIX;
- case AUDIO_SOURCE_UNPROCESSED:
- return AudioSource::UNPROCESSED;
- case AUDIO_SOURCE_VOICE_PERFORMANCE:
- return AudioSource::VOICE_PERFORMANCE;
- case AUDIO_SOURCE_ULTRASOUND:
- return AudioSource::ULTRASOUND;
- case AUDIO_SOURCE_ECHO_REFERENCE:
- return AudioSource::ECHO_REFERENCE;
- case AUDIO_SOURCE_FM_TUNER:
- return AudioSource::FM_TUNER;
- case AUDIO_SOURCE_HOTWORD:
- return AudioSource::HOTWORD;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
- return convertReinterpret<audio_session_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
- return convertReinterpret<int32_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);
@@ -1921,6 +326,27 @@
return legacy2aidl_audio_session_t_int32_t(legacy.session);
}
+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;
+ 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) {
+ 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;
+}
+
// This type is unnamed in the original definition, thus we name it here.
using audio_port_config_ext = decltype(audio_port_config::ext);
@@ -2165,148 +591,6 @@
return aidl;
}
-ConversionResult<audio_content_type_t>
-aidl2legacy_AudioContentType_audio_content_type_t(AudioContentType aidl) {
- switch (aidl) {
- case AudioContentType::UNKNOWN:
- return AUDIO_CONTENT_TYPE_UNKNOWN;
- case AudioContentType::SPEECH:
- return AUDIO_CONTENT_TYPE_SPEECH;
- case AudioContentType::MUSIC:
- return AUDIO_CONTENT_TYPE_MUSIC;
- case AudioContentType::MOVIE:
- return AUDIO_CONTENT_TYPE_MOVIE;
- case AudioContentType::SONIFICATION:
- return AUDIO_CONTENT_TYPE_SONIFICATION;
- case AudioContentType::ULTRASOUND:
- return AUDIO_CONTENT_TYPE_ULTRASOUND;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioContentType>
-legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
- switch (legacy) {
- case AUDIO_CONTENT_TYPE_UNKNOWN:
- return AudioContentType::UNKNOWN;
- case AUDIO_CONTENT_TYPE_SPEECH:
- return AudioContentType::SPEECH;
- case AUDIO_CONTENT_TYPE_MUSIC:
- return AudioContentType::MUSIC;
- case AUDIO_CONTENT_TYPE_MOVIE:
- return AudioContentType::MOVIE;
- case AUDIO_CONTENT_TYPE_SONIFICATION:
- return AudioContentType::SONIFICATION;
- case AUDIO_CONTENT_TYPE_ULTRASOUND:
- return AudioContentType::ULTRASOUND;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_usage_t>
-aidl2legacy_AudioUsage_audio_usage_t(AudioUsage aidl) {
- switch (aidl) {
- case AudioUsage::INVALID:
- break; // return error
- case AudioUsage::UNKNOWN:
- return AUDIO_USAGE_UNKNOWN;
- case AudioUsage::MEDIA:
- return AUDIO_USAGE_MEDIA;
- case AudioUsage::VOICE_COMMUNICATION:
- return AUDIO_USAGE_VOICE_COMMUNICATION;
- case AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
- return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
- case AudioUsage::ALARM:
- return AUDIO_USAGE_ALARM;
- case AudioUsage::NOTIFICATION:
- return AUDIO_USAGE_NOTIFICATION;
- case AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
- return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
- case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
- return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
- case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
- return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
- case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
- return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
- case AudioUsage::NOTIFICATION_EVENT:
- return AUDIO_USAGE_NOTIFICATION_EVENT;
- case AudioUsage::ASSISTANCE_ACCESSIBILITY:
- return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
- case AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
- return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
- case AudioUsage::ASSISTANCE_SONIFICATION:
- return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
- case AudioUsage::GAME:
- return AUDIO_USAGE_GAME;
- case AudioUsage::VIRTUAL_SOURCE:
- return AUDIO_USAGE_VIRTUAL_SOURCE;
- case AudioUsage::ASSISTANT:
- return AUDIO_USAGE_ASSISTANT;
- case AudioUsage::CALL_ASSISTANT:
- return AUDIO_USAGE_CALL_ASSISTANT;
- case AudioUsage::EMERGENCY:
- return AUDIO_USAGE_EMERGENCY;
- case AudioUsage::SAFETY:
- return AUDIO_USAGE_SAFETY;
- case AudioUsage::VEHICLE_STATUS:
- return AUDIO_USAGE_VEHICLE_STATUS;
- case AudioUsage::ANNOUNCEMENT:
- return AUDIO_USAGE_ANNOUNCEMENT;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioUsage>
-legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
- switch (legacy) {
- case AUDIO_USAGE_UNKNOWN:
- return AudioUsage::UNKNOWN;
- case AUDIO_USAGE_MEDIA:
- return AudioUsage::MEDIA;
- case AUDIO_USAGE_VOICE_COMMUNICATION:
- return AudioUsage::VOICE_COMMUNICATION;
- case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
- return AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
- case AUDIO_USAGE_ALARM:
- return AudioUsage::ALARM;
- case AUDIO_USAGE_NOTIFICATION:
- return AudioUsage::NOTIFICATION;
- case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
- return AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
- case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
- return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST;
- case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
- return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT;
- case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
- return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED;
- case AUDIO_USAGE_NOTIFICATION_EVENT:
- return AudioUsage::NOTIFICATION_EVENT;
- case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
- return AudioUsage::ASSISTANCE_ACCESSIBILITY;
- case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
- return AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
- case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
- return AudioUsage::ASSISTANCE_SONIFICATION;
- case AUDIO_USAGE_GAME:
- return AudioUsage::GAME;
- case AUDIO_USAGE_VIRTUAL_SOURCE:
- return AudioUsage::VIRTUAL_SOURCE;
- case AUDIO_USAGE_ASSISTANT:
- return AudioUsage::ASSISTANT;
- case AUDIO_USAGE_CALL_ASSISTANT:
- return AudioUsage::CALL_ASSISTANT;
- case AUDIO_USAGE_EMERGENCY:
- return AudioUsage::EMERGENCY;
- case AUDIO_USAGE_SAFETY:
- return AudioUsage::SAFETY;
- case AUDIO_USAGE_VEHICLE_STATUS:
- return AudioUsage::VEHICLE_STATUS;
- case AUDIO_USAGE_ANNOUNCEMENT:
- return AudioUsage::ANNOUNCEMENT;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<audio_flags_mask_t>
aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl) {
switch (aidl) {
@@ -2430,140 +714,6 @@
return aidl;
}
-ConversionResult<audio_encapsulation_mode_t>
-aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
- switch (aidl) {
- case AudioEncapsulationMode::INVALID:
- break; // return error
- case AudioEncapsulationMode::NONE:
- return AUDIO_ENCAPSULATION_MODE_NONE;
- case AudioEncapsulationMode::ELEMENTARY_STREAM:
- return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
- case AudioEncapsulationMode::HANDLE:
- return AUDIO_ENCAPSULATION_MODE_HANDLE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationMode>
-legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy) {
- switch (legacy) {
- case AUDIO_ENCAPSULATION_MODE_NONE:
- return AudioEncapsulationMode::NONE;
- case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
- return AudioEncapsulationMode::ELEMENTARY_STREAM;
- case AUDIO_ENCAPSULATION_MODE_HANDLE:
- return AudioEncapsulationMode::HANDLE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_offload_info_t>
-aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const AudioOffloadInfo& aidl) {
- audio_offload_info_t legacy = AUDIO_INFO_INITIALIZER;
- audio_config_base_t base = VALUE_OR_RETURN(
- aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, false /*isInput*/));
- legacy.sample_rate = base.sample_rate;
- legacy.channel_mask = base.channel_mask;
- legacy.format = base.format;
- legacy.stream_type = VALUE_OR_RETURN(
- aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
- legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitRatePerSecond));
- legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
- legacy.has_video = aidl.hasVideo;
- legacy.is_streaming = aidl.isStreaming;
- legacy.bit_width = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitWidth));
- legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.offloadBufferSize));
- legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
- legacy.encapsulation_mode = VALUE_OR_RETURN(
- aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(aidl.encapsulationMode));
- legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
- legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
- return legacy;
-}
-
-ConversionResult<AudioOffloadInfo>
-legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
- AudioOffloadInfo aidl;
- // Version 0.1 fields.
- if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
- return unexpected(BAD_VALUE);
- }
- const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
- .channel_mask = legacy.channel_mask, .format = legacy.format };
- aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(
- base, false /*isInput*/));
- aidl.streamType = VALUE_OR_RETURN(
- legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
- aidl.bitRatePerSecond = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
- aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
- aidl.hasVideo = legacy.has_video;
- aidl.isStreaming = legacy.is_streaming;
- aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
- aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
- aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
-
- // Version 0.2 fields.
- if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
- if (legacy.size <
- offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
- return unexpected(BAD_VALUE);
- }
- aidl.encapsulationMode = VALUE_OR_RETURN(
- legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(
- legacy.encapsulation_mode));
- aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
- aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
- }
- return aidl;
-}
-
-ConversionResult<audio_config_t>
-aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
- const audio_config_base_t legacyBase = VALUE_OR_RETURN(
- aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, isInput));
- audio_config_t legacy = AUDIO_CONFIG_INITIALIZER;
- legacy.sample_rate = legacyBase.sample_rate;
- legacy.channel_mask = legacyBase.channel_mask;
- legacy.format = legacyBase.format;
- legacy.offload_info = VALUE_OR_RETURN(
- aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
- legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
- return legacy;
-}
-
-ConversionResult<AudioConfig>
-legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput) {
- const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
- .channel_mask = legacy.channel_mask, .format = legacy.format };
- AudioConfig aidl;
- aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(base, isInput));
- aidl.offloadInfo = VALUE_OR_RETURN(
- legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
- aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
- return aidl;
-}
-
-ConversionResult<audio_config_base_t>
-aidl2legacy_AudioConfigBase_audio_config_base_t(const AudioConfigBase& aidl, bool isInput) {
- audio_config_base_t legacy;
- legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
- legacy.channel_mask = VALUE_OR_RETURN(
- aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
- legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
- return legacy;
-}
-
-ConversionResult<AudioConfigBase>
-legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput) {
- AudioConfigBase aidl;
- aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
- aidl.channelMask = VALUE_OR_RETURN(
- legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
- aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
- return aidl;
-}
-
ConversionResult<sp<IMemory>>
aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) {
sp<IMemory> legacy;
@@ -2582,8 +732,8 @@
return aidl;
}
-ConversionResult<sp<IMemory>>
-aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl) {
+ConversionResult<sp<IMemory>> aidl2legacy_NullableSharedFileRegion_IMemory(
+ const std::optional<media::SharedFileRegion>& aidl) {
sp<IMemory> legacy;
if (!convertNullableSharedFileRegionToIMemory(aidl, &legacy)) {
return unexpected(BAD_VALUE);
@@ -2618,31 +768,6 @@
return aidl;
}
-ConversionResult<audio_uuid_t>
-aidl2legacy_AudioUuid_audio_uuid_t(const AudioUuid& aidl) {
- audio_uuid_t legacy;
- legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
- legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
- legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
- legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
- if (aidl.node.size() != std::size(legacy.node)) {
- return unexpected(BAD_VALUE);
- }
- std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
- return legacy;
-}
-
-ConversionResult<AudioUuid>
-legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
- AudioUuid aidl;
- aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
- aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
- aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
- aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
- std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
- return aidl;
-}
-
ConversionResult<effect_descriptor_t>
aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl) {
effect_descriptor_t legacy;
@@ -2673,76 +798,34 @@
return aidl;
}
-ConversionResult<audio_encapsulation_metadata_type_t>
-aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
- AudioEncapsulationMetadataType aidl) {
- switch (aidl) {
- case AudioEncapsulationMetadataType::NONE:
- return AUDIO_ENCAPSULATION_METADATA_TYPE_NONE;
- case AudioEncapsulationMetadataType::FRAMEWORK_TUNER:
- return AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER;
- case AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR:
- return AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR;
- }
- return unexpected(BAD_VALUE);
+ConversionResult<audio_port_mix_ext>
+aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+ const AudioPortMixExt& aidl, const media::AudioPortMixExtSys& aidlSys) {
+ audio_port_mix_ext legacy{};
+ 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;
}
-ConversionResult<AudioEncapsulationMetadataType>
-legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
- audio_encapsulation_metadata_type_t legacy) {
- switch (legacy) {
- case AUDIO_ENCAPSULATION_METADATA_TYPE_NONE:
- return AudioEncapsulationMetadataType::NONE;
- case AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER:
- return AudioEncapsulationMetadataType::FRAMEWORK_TUNER;
- case AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR:
- return AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR;
- }
- return unexpected(BAD_VALUE);
+status_t
+legacy2aidl_audio_port_mix_ext_AudioPortMixExt(const audio_port_mix_ext& legacy,
+ AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
+ 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;
}
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl) {
- return convertBitmask<uint32_t,
- int32_t,
- audio_encapsulation_mode_t,
- AudioEncapsulationMode>(
- aidl, aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t,
- indexToEnum_index<AudioEncapsulationMode>,
- enumToMask_index<uint32_t, audio_encapsulation_mode_t>);
+ConversionResult<audio_port_session_ext>
+aidl2legacy_int32_t_audio_port_session_ext(int32_t aidl) {
+ audio_port_session_ext legacy;
+ legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl));
+ return legacy;
}
ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy) {
- return convertBitmask<int32_t,
- uint32_t,
- AudioEncapsulationMode,
- audio_encapsulation_mode_t>(
- legacy, legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode,
- indexToEnum_index<audio_encapsulation_mode_t>,
- enumToMask_index<int32_t, AudioEncapsulationMode>);
-}
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl) {
- return convertBitmask<uint32_t,
- int32_t,
- audio_encapsulation_metadata_type_t,
- AudioEncapsulationMetadataType>(
- aidl, aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t,
- indexToEnum_index<AudioEncapsulationMetadataType>,
- enumToMask_index<uint32_t, audio_encapsulation_metadata_type_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy) {
- return convertBitmask<int32_t,
- uint32_t,
- AudioEncapsulationMetadataType,
- audio_encapsulation_metadata_type_t>(
- legacy, legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType,
- indexToEnum_index<audio_encapsulation_metadata_type_t>,
- enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
+legacy2aidl_audio_port_session_ext_int32_t(const audio_port_session_ext& legacy) {
+ return legacy2aidl_audio_session_t_int32_t(legacy.session);
}
ConversionResult<audio_port_device_ext>
@@ -2775,36 +858,6 @@
return OK;
}
-ConversionResult<audio_port_mix_ext>
-aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
- const AudioPortMixExt& aidl, const media::AudioPortMixExtSys& aidlSys) {
- audio_port_mix_ext legacy{};
- 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) {
- 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;
-}
-
-ConversionResult<audio_port_session_ext>
-aidl2legacy_int32_t_audio_port_session_ext(int32_t aidl) {
- audio_port_session_ext legacy;
- legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl));
- return legacy;
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_port_session_ext_int32_t(const audio_port_session_ext& legacy) {
- return legacy2aidl_audio_session_t_int32_t(legacy.session);
-}
-
// This type is unnamed in the original definition, thus we name it here.
using audio_port_v7_ext = decltype(audio_port_v7::ext);
@@ -2876,93 +929,6 @@
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
}
-ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
- audio_profile legacy;
- legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
-
- if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
- convertIntegral<int32_t, unsigned int>));
- legacy.num_sample_rates = aidl.sampleRates.size();
-
- if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(aidl.channelMasks.begin(), aidl.channelMasks.end(), legacy.channel_masks,
- [isInput](const AudioChannelLayout& l) {
- return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
- }));
- legacy.num_channel_masks = aidl.channelMasks.size();
-
- legacy.encapsulation_type = VALUE_OR_RETURN(
- aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(aidl.encapsulationType));
- return legacy;
-}
-
-ConversionResult<AudioProfile>
-legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
- AudioProfile aidl;
- aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
-
- if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
- std::back_inserter(aidl.sampleRates),
- convertIntegral<unsigned int, int32_t>));
-
- if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
- return unexpected(BAD_VALUE);
- }
- RETURN_IF_ERROR(
- convertRange(legacy.channel_masks, legacy.channel_masks + legacy.num_channel_masks,
- std::back_inserter(aidl.channelMasks),
- [isInput](audio_channel_mask_t m) {
- return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
- }));
-
- aidl.encapsulationType = VALUE_OR_RETURN(
- legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
- legacy.encapsulation_type));
- return aidl;
-}
-
-ConversionResult<audio_gain>
-aidl2legacy_AudioGain_audio_gain(const AudioGain& aidl, bool isInput) {
- audio_gain legacy;
- legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
- legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
- aidl.channelMask, isInput));
- legacy.min_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.minValue));
- legacy.max_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.maxValue));
- legacy.default_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.defaultValue));
- legacy.step_value = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.stepValue));
- legacy.min_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.minRampMs));
- legacy.max_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.maxRampMs));
- return legacy;
-}
-
-ConversionResult<AudioGain>
-legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput) {
- AudioGain aidl;
- aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
- aidl.channelMask = VALUE_OR_RETURN(
- legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
- aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
- aidl.maxValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_value));
- aidl.defaultValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.default_value));
- aidl.stepValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.step_value));
- aidl.minRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_ramp_ms));
- aidl.maxRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_ramp_ms));
- return aidl;
-}
-
ConversionResult<audio_port_v7>
aidl2legacy_AudioPort_audio_port_v7(const media::AudioPort& aidl) {
audio_port_v7 legacy;
@@ -3057,58 +1023,6 @@
return aidl;
}
-ConversionResult<audio_mode_t>
-aidl2legacy_AudioMode_audio_mode_t(AudioMode aidl) {
- switch (aidl) {
- case AudioMode::SYS_RESERVED_INVALID:
- return AUDIO_MODE_INVALID;
- case AudioMode::SYS_RESERVED_CURRENT:
- return AUDIO_MODE_CURRENT;
- case AudioMode::NORMAL:
- return AUDIO_MODE_NORMAL;
- case AudioMode::RINGTONE:
- return AUDIO_MODE_RINGTONE;
- case AudioMode::IN_CALL:
- return AUDIO_MODE_IN_CALL;
- case AudioMode::IN_COMMUNICATION:
- return AUDIO_MODE_IN_COMMUNICATION;
- case AudioMode::CALL_SCREEN:
- return AUDIO_MODE_CALL_SCREEN;
- case AudioMode::SYS_RESERVED_CALL_REDIRECT:
- return AUDIO_MODE_CALL_REDIRECT;
- case AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT:
- return AUDIO_MODE_COMMUNICATION_REDIRECT;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioMode>
-legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
- switch (legacy) {
- case AUDIO_MODE_INVALID:
- return AudioMode::SYS_RESERVED_INVALID;
- case AUDIO_MODE_CURRENT:
- return AudioMode::SYS_RESERVED_CURRENT;
- case AUDIO_MODE_NORMAL:
- return AudioMode::NORMAL;
- case AUDIO_MODE_RINGTONE:
- return AudioMode::RINGTONE;
- case AUDIO_MODE_IN_CALL:
- return AudioMode::IN_CALL;
- case AUDIO_MODE_IN_COMMUNICATION:
- return AudioMode::IN_COMMUNICATION;
- case AUDIO_MODE_CALL_SCREEN:
- return AudioMode::CALL_SCREEN;
- case AUDIO_MODE_CALL_REDIRECT:
- return AudioMode::SYS_RESERVED_CALL_REDIRECT;
- case AUDIO_MODE_COMMUNICATION_REDIRECT:
- return AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT;
- case AUDIO_MODE_CNT:
- break;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<audio_unique_id_use_t>
aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl) {
switch (aidl) {
@@ -3177,160 +1091,6 @@
return convertReinterpret<int32_t>(legacy);
}
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl) {
- switch (aidl) {
- case media::AudioDualMonoMode::OFF:
- return AUDIO_DUAL_MONO_MODE_OFF;
- case media::AudioDualMonoMode::LR:
- return AUDIO_DUAL_MONO_MODE_LR;
- case media::AudioDualMonoMode::LL:
- return AUDIO_DUAL_MONO_MODE_LL;
- case media::AudioDualMonoMode::RR:
- return AUDIO_DUAL_MONO_MODE_RR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
- switch (legacy) {
- case AUDIO_DUAL_MONO_MODE_OFF:
- return media::AudioDualMonoMode::OFF;
- case AUDIO_DUAL_MONO_MODE_LR:
- return media::AudioDualMonoMode::LR;
- case AUDIO_DUAL_MONO_MODE_LL:
- return media::AudioDualMonoMode::LL;
- case AUDIO_DUAL_MONO_MODE_RR:
- return media::AudioDualMonoMode::RR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl) {
- return convertReinterpret<audio_timestretch_fallback_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl) {
- return convertReinterpret<audio_timestretch_stretch_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl) {
- audio_playback_rate_t legacy;
- legacy.mSpeed = aidl.speed;
- legacy.mPitch = aidl.pitch;
- legacy.mFallbackMode = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(aidl.fallbackMode));
- legacy.mStretchMode = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(aidl.stretchMode));
- return legacy;
-}
-
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
- media::AudioPlaybackRate aidl;
- aidl.speed = legacy.mSpeed;
- aidl.pitch = legacy.mPitch;
- aidl.fallbackMode = VALUE_OR_RETURN(
- legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(legacy.mFallbackMode));
- aidl.stretchMode = VALUE_OR_RETURN(
- legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(legacy.mStretchMode));
- return aidl;
-}
-
-ConversionResult<audio_standard_t>
-aidl2legacy_AudioStandard_audio_standard_t(AudioStandard aidl) {
- switch (aidl) {
- case AudioStandard::NONE:
- return AUDIO_STANDARD_NONE;
- case AudioStandard::EDID:
- return AUDIO_STANDARD_EDID;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioStandard>
-legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy) {
- switch (legacy) {
- case AUDIO_STANDARD_NONE:
- return AudioStandard::NONE;
- case AUDIO_STANDARD_EDID:
- return AudioStandard::EDID;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_extra_audio_descriptor>
-aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
- const ExtraAudioDescriptor& aidl) {
- audio_extra_audio_descriptor legacy;
- legacy.standard = VALUE_OR_RETURN(aidl2legacy_AudioStandard_audio_standard_t(aidl.standard));
- if (aidl.audioDescriptor.size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
- return unexpected(BAD_VALUE);
- }
- legacy.descriptor_length = aidl.audioDescriptor.size();
- std::copy(aidl.audioDescriptor.begin(), aidl.audioDescriptor.end(),
- std::begin(legacy.descriptor));
- legacy.encapsulation_type =
- VALUE_OR_RETURN(aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
- aidl.encapsulationType));
- return legacy;
-}
-
-ConversionResult<ExtraAudioDescriptor>
-legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
- const audio_extra_audio_descriptor& legacy) {
- ExtraAudioDescriptor aidl;
- aidl.standard = VALUE_OR_RETURN(legacy2aidl_audio_standard_t_AudioStandard(legacy.standard));
- if (legacy.descriptor_length > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
- return unexpected(BAD_VALUE);
- }
- aidl.audioDescriptor.resize(legacy.descriptor_length);
- std::copy(legacy.descriptor, legacy.descriptor + legacy.descriptor_length,
- aidl.audioDescriptor.begin());
- aidl.encapsulationType =
- VALUE_OR_RETURN(legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
- legacy.encapsulation_type));
- return aidl;
-}
-
-ConversionResult<audio_encapsulation_type_t>
-aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
- const AudioEncapsulationType& aidl) {
- switch (aidl) {
- case AudioEncapsulationType::NONE:
- return AUDIO_ENCAPSULATION_TYPE_NONE;
- case AudioEncapsulationType::IEC61937:
- return AUDIO_ENCAPSULATION_TYPE_IEC61937;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationType>
-legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
- const audio_encapsulation_type_t & legacy) {
- switch (legacy) {
- case AUDIO_ENCAPSULATION_TYPE_NONE:
- return AudioEncapsulationType::NONE;
- case AUDIO_ENCAPSULATION_TYPE_IEC61937:
- return AudioEncapsulationType::IEC61937;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<TrackSecondaryOutputInfoPair>
aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
const media::TrackSecondaryOutputInfo& aidl) {
@@ -3403,25 +1163,4 @@
indexToEnum_bitmask<audio_direct_mode_t>,
enumToMask_index<int32_t, media::AudioDirectMode>);
}
-
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl) {
- switch (aidl) {
- case media::LatencyMode::FREE:
- return AUDIO_LATENCY_MODE_FREE;
- case media::LatencyMode::LOW:
- return AUDIO_LATENCY_MODE_LOW;
- }
- return unexpected(BAD_VALUE);
-}
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy) {
- switch (legacy) {
- case AUDIO_LATENCY_MODE_FREE:
- return media::LatencyMode::FREE;
- case AUDIO_LATENCY_MODE_LOW:
- return media::LatencyMode::LOW;
- }
- return unexpected(BAD_VALUE);
-}
} // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index e0a8571..d51fedb 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -193,88 +193,29 @@
},
}
-// This is intended for clients needing to include AidlConversionUtil.h, without dragging in a lot of extra
-// dependencies.
-cc_library_headers {
- name: "libaudioclient_aidl_conversion_util",
- host_supported: true,
- vendor_available: true,
- double_loadable: true,
- min_sdk_version: "29",
- export_include_dirs: [
- "include",
- ],
- header_libs: [
- "libbase_headers",
- "liberror_headers",
- ],
- export_header_lib_headers: [
- "libbase_headers",
- "liberror_headers",
- ],
- apex_available: [
- "//apex_available:platform",
- "com.android.btservices",
- "com.android.media",
- "com.android.media.swcodec",
- ],
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
-
cc_library {
name: "libaudioclient_aidl_conversion",
srcs: ["AidlConversion.cpp"],
- export_include_dirs: ["include"],
- host_supported: true,
- vendor_available: true,
- double_loadable: true,
- min_sdk_version: "29",
- header_libs: [
- "libaudioclient_aidl_conversion_util",
- "libaudio_system_headers",
- ],
- export_header_lib_headers: [
- "libaudioclient_aidl_conversion_util",
- ],
- defaults: [
- "latest_android_media_audio_common_types_cpp_export_shared",
- ],
shared_libs: [
"audioclient-types-aidl-cpp",
- "libbase",
- "libbinder",
- "liblog",
- "libshmemcompat",
- "libstagefright_foundation",
- "libutils",
- "shared-file-region-aidl-cpp",
- "framework-permission-aidl-cpp",
+ ],
+ static_libs: [
+ "libaudio_aidl_conversion_common_cpp",
+ ],
+ export_include_dirs: ["include"],
+ header_libs: [
+ "libaudio_aidl_conversion_common_util_cpp",
+ ],
+ export_header_lib_headers: [
+ "libaudio_aidl_conversion_common_util_cpp",
],
export_shared_lib_headers: [
"audioclient-types-aidl-cpp",
- "libbase",
- "shared-file-region-aidl-cpp",
],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-error=deprecated-declarations",
+ defaults: [
+ "audio_aidl_conversion_common_default",
+ "latest_android_media_audio_common_types_cpp_export_shared",
],
- sanitize: {
- misc_undefined: [
- "unsigned-integer-overflow",
- "signed-integer-overflow",
- ],
- },
- target: {
- darwin: {
- enabled: false,
- },
- },
}
// AIDL interface between libaudioclient and framework.jar
@@ -340,14 +281,12 @@
"aidl/android/media/AudioAttributesInternal.aidl",
"aidl/android/media/AudioClient.aidl",
"aidl/android/media/AudioDirectMode.aidl",
- "aidl/android/media/AudioDualMonoMode.aidl",
"aidl/android/media/AudioFlag.aidl",
"aidl/android/media/AudioGainSys.aidl",
"aidl/android/media/AudioHalVersion.aidl",
"aidl/android/media/AudioIoConfigEvent.aidl",
"aidl/android/media/AudioIoDescriptor.aidl",
"aidl/android/media/AudioPatch.aidl",
- "aidl/android/media/AudioPlaybackRate.aidl",
"aidl/android/media/AudioPort.aidl",
"aidl/android/media/AudioPortSys.aidl",
"aidl/android/media/AudioPortConfig.aidl",
@@ -362,7 +301,6 @@
"aidl/android/media/AudioUniqueIdUse.aidl",
"aidl/android/media/AudioVibratorInfo.aidl",
"aidl/android/media/EffectDescriptor.aidl",
- "aidl/android/media/LatencyMode.aidl",
"aidl/android/media/TrackSecondaryOutputInfo.aidl",
],
imports: [
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 141e1e3..2bbafa7 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -671,12 +671,12 @@
}
Status AudioSystem::AudioFlingerClient::onSupportedLatencyModesChanged(
- int output, const std::vector<media::LatencyMode>& latencyModes) {
+ int output, const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_io_handle_t(output));
std::vector<audio_latency_mode_t> modesLegacy = VALUE_OR_RETURN_BINDER_STATUS(
convertContainer<std::vector<audio_latency_mode_t>>(
- latencyModes, aidl2legacy_LatencyMode_audio_latency_mode_t));
+ latencyModes, aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
std::vector<sp<SupportedLatencyModesCallback>> callbacks;
{
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 96fc544..ff4b071 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1248,7 +1248,7 @@
status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
{
AutoMutex lock(mLock);
- media::AudioDualMonoMode mediaMode;
+ media::audio::common::AudioDualMonoMode mediaMode;
const status_t status = statusTFromBinderStatus(mAudioTrack->getDualMonoMode(&mediaMode));
if (status == NO_ERROR) {
*mode = VALUE_OR_RETURN_STATUS(
@@ -1363,7 +1363,7 @@
{
AutoMutex lock(mLock);
if (isOffloadedOrDirect_l()) {
- media::AudioPlaybackRate playbackRateTemp;
+ media::audio::common::AudioPlaybackRate playbackRateTemp;
const status_t status = statusTFromBinderStatus(
mAudioTrack->getPlaybackRateParameters(&playbackRateTemp));
if (status == NO_ERROR) { // update local version if changed.
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 6ad97d1..3dd1913 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -22,10 +22,10 @@
#include <stdint.h>
#include <sys/types.h>
-
+#include "IAudioFlinger.h"
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
-#include "IAudioFlinger.h"
+#include <system/thread_defs.h>
namespace android {
@@ -813,8 +813,8 @@
status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) {
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- media::LatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_latency_mode_t_LatencyMode(mode));
+ media::audio::common::AudioLatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
return statusTFromBinderStatus(mDelegate->setRequestedLatencyMode(outputAidl, modeAidl));
}
@@ -825,14 +825,14 @@
}
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- std::vector<media::LatencyMode> modesAidl;
+ std::vector<media::audio::common::AudioLatencyMode> modesAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mDelegate->getSupportedLatencyModes(outputAidl, &modesAidl)));
*modes = VALUE_OR_RETURN_STATUS(
convertContainer<std::vector<audio_latency_mode_t>>(modesAidl,
- aidl2legacy_LatencyMode_audio_latency_mode_t));
+ aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
return NO_ERROR;
}
@@ -840,7 +840,9 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// AudioFlingerServerAdapter
AudioFlingerServerAdapter::AudioFlingerServerAdapter(
- const sp<AudioFlingerServerAdapter::Delegate>& delegate) : mDelegate(delegate) {}
+ const sp<AudioFlingerServerAdapter::Delegate>& delegate) : mDelegate(delegate) {
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+}
status_t AudioFlingerServerAdapter::onTransact(uint32_t code,
const Parcel& data,
@@ -1332,17 +1334,17 @@
}
Status AudioFlingerServerAdapter::setRequestedLatencyMode(
- int32_t output, media::LatencyMode modeAidl) {
+ int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
audio_latency_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(
- aidl2legacy_LatencyMode_audio_latency_mode_t(modeAidl));
+ aidl2legacy_AudioLatencyMode_audio_latency_mode_t(modeAidl));
return Status::fromStatusT(mDelegate->setRequestedLatencyMode(
outputLegacy, modeLegacy));
}
Status AudioFlingerServerAdapter::getSupportedLatencyModes(
- int output, std::vector<media::LatencyMode>* _aidl_return) {
+ int output, std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
std::vector<audio_latency_mode_t> modesLegacy;
@@ -1350,8 +1352,8 @@
RETURN_BINDER_IF_ERROR(mDelegate->getSupportedLatencyModes(outputLegacy, &modesLegacy));
*_aidl_return = VALUE_OR_RETURN_BINDER(
- convertContainer<std::vector<media::LatencyMode>>(
- modesLegacy, legacy2aidl_audio_latency_mode_t_LatencyMode));
+ convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+ modesLegacy, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
return Status::ok();
}
diff --git a/media/libaudioclient/TEST_MAPPING b/media/libaudioclient/TEST_MAPPING
index 51080ef..10f9d9b 100644
--- a/media/libaudioclient/TEST_MAPPING
+++ b/media/libaudioclient/TEST_MAPPING
@@ -32,5 +32,10 @@
{
"name": "audiosystem_tests"
}
+ ],
+ "postsubmit": [
+ {
+ "name": "audioeffect_analysis"
+ }
]
}
diff --git a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
deleted file mode 100644
index f6220c2..0000000
--- a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-// TODO(b/175167149): Reconcile AudioDualMonoMode with framework-media-sources
-
-@Backing(type="int")
-enum AudioDualMonoMode {
- OFF = 0,
- LR = 1,
- LL = 2,
- RR = 3,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl b/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
deleted file mode 100644
index e29d398..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * The AudioPlaybackRate.
- *
- * See https://developer.android.com/reference/android/media/PlaybackParams.
- * TODO(b/175166815): Reconcile with framework-media-sources PlaybackParams.aidl.
- * As this is used for native wire serialization, no need to define
- * audio_timestretch_stretch_mode_t and audio_timestretch_fallback_mode_t enums
- * until we attempt to unify with PlaybackParams.
- *
- * {@hide}
- */
-parcelable AudioPlaybackRate {
- /** Speed of audio playback, >= 0.f, 1.f nominal (system limits are further restrictive) */
- float speed;
- /** Pitch of audio, >= 0.f, 1.f nominal (system limits are further restrictive) */
- float pitch;
- /** Interpreted as audio_timestretch_stretch_mode_t */
- int stretchMode;
- /** Interpreted as audio_timestretch_fallback_mode_t */
- int fallbackMode;
-}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
index a2bb024..f055cc4 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
@@ -18,7 +18,7 @@
import android.media.AudioIoConfigEvent;
import android.media.AudioIoDescriptor;
-import android.media.LatencyMode;
+import android.media.audio.common.AudioLatencyMode;
/**
* A callback interface for AudioFlinger.
@@ -31,7 +31,8 @@
/**
* Called when the latency modes supported on a given output stream change.
* output is the I/O handle of the output stream for which the change is signalled.
- * latencyModes is the new list of supported latency modes (See LatencyMode.aidl).
+ * latencyModes is the new list of supported latency modes (See AudioLatencyMode.aidl).
*/
- oneway void onSupportedLatencyModesChanged(int output, in LatencyMode[] latencyModes);
+ oneway void onSupportedLatencyModesChanged(
+ int output, in AudioLatencyMode[] latencyModes);
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 9b8a843..e19198b 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -35,12 +35,12 @@
import android.media.IAudioFlingerClient;
import android.media.IAudioRecord;
import android.media.IAudioTrack;
-import android.media.LatencyMode;
import android.media.MicrophoneInfoData;
import android.media.RenderPosition;
import android.media.TrackSecondaryOutputInfo;
import android.media.audio.common.AudioChannelLayout;
import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioLatencyMode;
import android.media.audio.common.AudioMMapPolicyInfo;
import android.media.audio.common.AudioMMapPolicyType;
import android.media.audio.common.AudioMode;
@@ -230,21 +230,21 @@
void setDeviceConnectedState(in AudioPort devicePort, boolean connected);
/**
- * Requests a given latency mode (See LatencyMode.aidl) on an output stream.
+ * Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
* This can be used when some use case on a given mixer/stream can only be enabled
* if a specific latency mode is selected on the audio path below the HAL.
* For instance spatial audio with head tracking.
* output is the I/O handle of the output stream for which the request is made.
* latencyMode is the requested latency mode.
*/
- void setRequestedLatencyMode(int output, LatencyMode latencyMode);
+ void setRequestedLatencyMode(int output, AudioLatencyMode latencyMode);
/**
* Queries the list of latency modes (See LatencyMode.aidl) supported by an output stream.
* output is the I/O handle of the output stream to which the query applies.
* returns the list of supported latency modes.
*/
- LatencyMode[] getSupportedLatencyModes(int output);
+ AudioLatencyMode[] getSupportedLatencyModes(int output);
// When adding a new method, please review and update
// IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
index ac58925..c3a2dbe 100644
--- a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
@@ -16,13 +16,13 @@
package android.media;
-import android.media.AudioDualMonoMode;
-import android.media.AudioPlaybackRate;
import android.media.AudioTimestampInternal;
import android.media.SharedFileRegion;
import android.media.VolumeShaperConfiguration;
import android.media.VolumeShaperOperation;
import android.media.VolumeShaperState;
+import android.media.audio.common.AudioDualMonoMode;
+import android.media.audio.common.AudioPlaybackRate;
/**
* Unless otherwise noted, methods returning int expect it to be interpreted as a status_t.
diff --git a/media/libaudioclient/aidl/android/media/LatencyMode.aidl b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
deleted file mode 100644
index 0b2a72b..0000000
--- a/media/libaudioclient/aidl/android/media/LatencyMode.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * The latency mode currently used by the spatializer mixer.
- * {@hide}
- */
-@Backing(type="byte")
-enum LatencyMode {
- /** No specific constraint on the latency */
- FREE = 0,
- /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
- LOW = 1,
-}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 1e66164..b0f84a4 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -24,46 +24,20 @@
#include <android/media/AudioAttributesInternal.h>
#include <android/media/AudioClient.h>
#include <android/media/AudioDirectMode.h>
-#include <android/media/AudioDualMonoMode.h>
#include <android/media/AudioFlag.h>
#include <android/media/AudioIoConfigEvent.h>
#include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioPlaybackRate.h>
#include <android/media/AudioPort.h>
#include <android/media/AudioPortConfig.h>
#include <android/media/AudioPortDeviceExtSys.h>
#include <android/media/AudioTimestampInternal.h>
#include <android/media/AudioUniqueIdUse.h>
#include <android/media/EffectDescriptor.h>
-#include <android/media/LatencyMode.h>
#include <android/media/TrackSecondaryOutputInfo.h>
-#include <android/media/audio/common/AudioChannelLayout.h>
-#include <android/media/audio/common/AudioConfig.h>
-#include <android/media/audio/common/AudioConfigBase.h>
-#include <android/media/audio/common/AudioContentType.h>
-#include <android/media/audio/common/AudioDeviceDescription.h>
-#include <android/media/audio/common/AudioEncapsulationMetadataType.h>
-#include <android/media/audio/common/AudioEncapsulationMode.h>
-#include <android/media/audio/common/AudioEncapsulationType.h>
-#include <android/media/audio/common/AudioFormatDescription.h>
-#include <android/media/audio/common/AudioGain.h>
-#include <android/media/audio/common/AudioGainConfig.h>
-#include <android/media/audio/common/AudioGainMode.h>
-#include <android/media/audio/common/AudioInputFlags.h>
-#include <android/media/audio/common/AudioMode.h>
-#include <android/media/audio/common/AudioOffloadInfo.h>
-#include <android/media/audio/common/AudioOutputFlags.h>
-#include <android/media/audio/common/AudioPortExt.h>
-#include <android/media/audio/common/AudioPortMixExt.h>
-#include <android/media/audio/common/AudioProfile.h>
-#include <android/media/audio/common/AudioSource.h>
-#include <android/media/audio/common/AudioStandard.h>
-#include <android/media/audio/common/AudioUsage.h>
-#include <android/media/audio/common/AudioUuid.h>
-#include <android/media/audio/common/ExtraAudioDescriptor.h>
#include <android/media/SharedFileRegion.h>
#include <binder/IMemory.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionUtil.h>
#include <media/AudioClient.h>
#include <media/AudioCommonTypes.h>
@@ -73,49 +47,6 @@
namespace android {
-// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
-// the string.
-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);
-ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
-
-ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
-
-ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
-
-ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
-
-ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
-
-ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy);
-
-ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
-
-ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
-
-ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
-
-ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl);
-ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy);
-
-ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl);
-ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy);
-
-ConversionResult<std::optional<String16>>
-aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl);
-ConversionResult<std::optional<std::string_view>>
-legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy);
-
ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
media::AudioIoConfigEvent aidl);
ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
@@ -131,75 +62,6 @@
ConversionResult<media::AudioPortType> legacy2aidl_audio_port_type_t_AudioPortType(
audio_port_type_t legacy);
-ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
- const media::audio::common::AudioChannelLayout& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioChannelLayout>
-legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
-
-ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
- const media::audio::common::AudioDeviceDescription& aidl);
-ConversionResult<media::audio::common::AudioDeviceDescription>
-legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
-
-status_t aidl2legacy_AudioDevice_audio_device(
- const media::audio::common::AudioDevice& aidl,
- audio_devices_t* legacyType, char* legacyAddress);
-status_t aidl2legacy_AudioDevice_audio_device(
- const media::audio::common::AudioDevice& aidl,
- audio_devices_t* legacyType, String8* legacyAddress);
-status_t aidl2legacy_AudioDevice_audio_device(
- const media::audio::common::AudioDevice& aidl,
- audio_devices_t* legacyType, std::string* legacyAddress);
-ConversionResult<media::audio::common::AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
- audio_devices_t legacyType, const char* legacyAddress);
-ConversionResult<media::audio::common::AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
- audio_devices_t legacyType, const String8& legacyAddress);
-
-ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
- const media::audio::common::AudioFormatDescription& aidl);
-ConversionResult<media::audio::common::AudioFormatDescription>
-legacy2aidl_audio_format_t_AudioFormatDescription(audio_format_t legacy);
-
-ConversionResult<audio_gain_mode_t>
-aidl2legacy_AudioGainMode_audio_gain_mode_t(media::audio::common::AudioGainMode aidl);
-ConversionResult<media::audio::common::AudioGainMode>
-legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy);
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
-
-ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
- const media::audio::common::AudioGainConfig& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioGainConfig>
-legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
-
-ConversionResult<audio_input_flags_t>
-aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
-ConversionResult<media::audio::common::AudioInputFlags>
-legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
-
-ConversionResult<audio_output_flags_t>
-aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
-ConversionResult<media::audio::common::AudioOutputFlags>
-legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
-
-ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
- int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
- audio_input_flags_t legacy);
-
-ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
- int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
- audio_output_flags_t legacy);
-
-ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
- const media::audio::common::AudioIoFlags& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
- const audio_io_flags& legacy, bool isInput);
-
ConversionResult<audio_port_config_device_ext>
aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
const media::audio::common::AudioPortDeviceExt& aidl,
@@ -214,15 +76,6 @@
ConversionResult<media::audio::common::AudioStreamType>
legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
-ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
- media::audio::common::AudioSource aidl);
-ConversionResult<media::audio::common::AudioSource>
- legacy2aidl_audio_source_t_AudioSource(
- audio_source_t legacy);
-
-ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
-
ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
const media::audio::common::AudioPortMixExt& aidl, media::AudioPortRole role,
const media::AudioPortMixExtSys& aidlMixExt);
@@ -255,17 +108,6 @@
ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
const AudioClient& legacy);
-ConversionResult<audio_content_type_t>
-aidl2legacy_AudioContentType_audio_content_type_t(
- media::audio::common::AudioContentType aidl);
-ConversionResult<media::audio::common::AudioContentType>
-legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
-
-ConversionResult<audio_usage_t>
-aidl2legacy_AudioUsage_audio_usage_t(media::audio::common::AudioUsage aidl);
-ConversionResult<media::audio::common::AudioUsage>
-legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy);
-
ConversionResult<audio_flags_mask_t>
aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl);
ConversionResult<media::AudioFlag>
@@ -281,36 +123,13 @@
ConversionResult<media::AudioAttributesInternal>
legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy);
-ConversionResult<audio_encapsulation_mode_t>
-aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(
- media::audio::common::AudioEncapsulationMode aidl);
-ConversionResult<media::audio::common::AudioEncapsulationMode>
-legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy);
-
-ConversionResult<audio_offload_info_t>
-aidl2legacy_AudioOffloadInfo_audio_offload_info_t(
- const media::audio::common::AudioOffloadInfo& aidl);
-ConversionResult<media::audio::common::AudioOffloadInfo>
-legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
-
-ConversionResult<audio_config_t>
-aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfig>
-legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput);
-
-ConversionResult<audio_config_base_t>
-aidl2legacy_AudioConfigBase_audio_config_base_t(
- const media::audio::common::AudioConfigBase& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfigBase>
-legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput);
-
ConversionResult<sp<IMemory>>
aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl);
ConversionResult<media::SharedFileRegion>
legacy2aidl_IMemory_SharedFileRegion(const sp<IMemory>& legacy);
-ConversionResult<sp<IMemory>>
-aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl);
+ConversionResult<sp<::android::IMemory>> aidl2legacy_NullableSharedFileRegion_IMemory(
+ const std::optional<media::SharedFileRegion>& aidl);
ConversionResult<std::optional<media::SharedFileRegion>>
legacy2aidl_NullableIMemory_SharedFileRegion(const sp<IMemory>& legacy);
@@ -319,32 +138,10 @@
ConversionResult<media::AudioTimestampInternal>
legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy);
-ConversionResult<audio_uuid_t>
-aidl2legacy_AudioUuid_audio_uuid_t(const media::audio::common::AudioUuid& aidl);
-ConversionResult<media::audio::common::AudioUuid>
-legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy);
-
ConversionResult<effect_descriptor_t>
aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl);
-ConversionResult<media::EffectDescriptor>
-legacy2aidl_effect_descriptor_t_EffectDescriptor(const effect_descriptor_t& legacy);
-
-ConversionResult<audio_encapsulation_metadata_type_t>
-aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
- media::audio::common::AudioEncapsulationMetadataType aidl);
-ConversionResult<media::audio::common::AudioEncapsulationMetadataType>
-legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
- audio_encapsulation_metadata_type_t legacy);
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy);
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
+ConversionResult<media::EffectDescriptor> legacy2aidl_effect_descriptor_t_EffectDescriptor(
+ const effect_descriptor_t& legacy);
ConversionResult<audio_port_device_ext>
aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
@@ -369,27 +166,11 @@
ConversionResult<int32_t>
legacy2aidl_audio_port_session_ext_int32_t(const audio_port_session_ext& legacy);
-ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(
- const media::audio::common::AudioProfile& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioProfile>
-legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput);
-
-ConversionResult<audio_gain>
-aidl2legacy_AudioGain_audio_gain(const media::audio::common::AudioGain& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioGain>
-legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput);
-
ConversionResult<audio_port_v7>
aidl2legacy_AudioPort_audio_port_v7(const media::AudioPort& aidl);
ConversionResult<media::AudioPort>
legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy);
-ConversionResult<audio_mode_t>
-aidl2legacy_AudioMode_audio_mode_t(media::audio::common::AudioMode aidl);
-ConversionResult<media::audio::common::AudioMode>
-legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
-
ConversionResult<audio_unique_id_use_t>
aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl);
ConversionResult<media::AudioUniqueIdUse>
@@ -400,45 +181,6 @@
ConversionResult<int32_t>
legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl);
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy);
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy);
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl);
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
-
-ConversionResult<audio_standard_t>
-aidl2legacy_AudioStandard_audio_standard_t(media::audio::common::AudioStandard aidl);
-ConversionResult<media::audio::common::AudioStandard>
-legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy);
-
-ConversionResult<audio_extra_audio_descriptor>
-aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
- const media::audio::common::ExtraAudioDescriptor& aidl);
-ConversionResult<media::audio::common::ExtraAudioDescriptor>
-legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
- const audio_extra_audio_descriptor& legacy);
-
-ConversionResult<audio_encapsulation_type_t>
-aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
- const media::audio::common::AudioEncapsulationType& aidl);
-ConversionResult<media::audio::common::AudioEncapsulationType>
-legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
- const audio_encapsulation_type_t & legacy);
-
using TrackSecondaryOutputInfoPair = std::pair<audio_port_handle_t, std::vector<audio_io_handle_t>>;
ConversionResult<TrackSecondaryOutputInfoPair>
aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
@@ -455,9 +197,4 @@
ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl);
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy);
-
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 9411f46..beb9a77 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -705,7 +705,8 @@
const media::AudioIoDescriptor& ioDesc) override;
binder::Status onSupportedLatencyModesChanged(
- int output, const std::vector<media::LatencyMode>& latencyModes) override;
+ int output,
+ const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) override;
status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index c891ae6..71f724d 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -685,9 +685,10 @@
Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
Status setDeviceConnectedState(const media::AudioPort& port, bool connected) override;
- Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
+ Status setRequestedLatencyMode(
+ int output, media::audio::common::AudioLatencyMode mode) override;
Status getSupportedLatencyModes(int output,
- std::vector<media::LatencyMode>* _aidl_return) override;
+ std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) override;
private:
const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
};
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 1b09173..cbcef12 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -36,8 +36,9 @@
"libutils",
],
static_libs: [
- "audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
+ "audioclient-types-aidl-cpp",
"libstagefright_foundation",
],
}
@@ -108,6 +109,7 @@
shared_libs: [
"capture_state_listener-aidl-cpp",
"framework-permission-aidl-cpp",
+ "libaudioclient_aidl_conversion",
"libbase",
"libbinder",
"libcgrouprc",
@@ -137,7 +139,6 @@
"av-types-aidl-cpp",
"effect-aidl-cpp",
"libaudioclient",
- "libaudioclient_aidl_conversion",
"libaudiofoundation",
"libaudiomanager",
"libaudiopolicy",
@@ -176,6 +177,22 @@
}
cc_test {
+ name: "audioeffect_analysis",
+ defaults: ["libaudioclient_gtests_defaults"],
+ // flag needed for pfft/pffft.hpp
+ cflags: [
+ "-Wno-error=unused-parameter",
+ ],
+ srcs: [
+ "audioeffect_analyser.cpp",
+ "audio_test_utils.cpp",
+ ],
+ static_libs: [
+ "libpffft",
+ ],
+}
+
+cc_test {
name: "audiorouting_tests",
defaults: ["libaudioclient_gtests_defaults"],
srcs: [
diff --git a/media/libaudioclient/tests/audio_test_utils.cpp b/media/libaudioclient/tests/audio_test_utils.cpp
index 850eb34..1e26ff6 100644
--- a/media/libaudioclient/tests/audio_test_utils.cpp
+++ b/media/libaudioclient/tests/audio_test_utils.cpp
@@ -17,11 +17,15 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "AudioTestUtils"
+#include <android-base/file.h>
#include <system/audio_config.h>
#include <utils/Log.h>
#include "audio_test_utils.h"
+#define WAIT_PERIOD_MS 10 // from AudioTrack.cpp
+#define MAX_WAIT_TIME_MS 5000
+
template <class T>
constexpr void (*xmlDeleter)(T* t);
template <>
@@ -37,12 +41,6 @@
return std::unique_ptr<T, decltype(deleter)>{t, deleter};
}
-// Generates a random string.
-void CreateRandomFile(int& fd) {
- std::string filename = "/data/local/tmp/record-XXXXXX";
- fd = mkstemp(filename.data());
-}
-
void OnAudioDeviceUpdateNotifier::onAudioDeviceUpdate(audio_io_handle_t audioIo,
audio_port_handle_t deviceId) {
std::unique_lock<std::mutex> lock{mMutex};
@@ -52,11 +50,14 @@
mCondition.notify_all();
}
-status_t OnAudioDeviceUpdateNotifier::waitForAudioDeviceCb() {
+status_t OnAudioDeviceUpdateNotifier::waitForAudioDeviceCb(audio_port_handle_t expDeviceId) {
std::unique_lock<std::mutex> lock{mMutex};
- if (mAudioIo == AUDIO_IO_HANDLE_NONE) {
+ if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
+ (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId)) {
mCondition.wait_for(lock, std::chrono::milliseconds(500));
- if (mAudioIo == AUDIO_IO_HANDLE_NONE) return TIMED_OUT;
+ if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
+ (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId))
+ return TIMED_OUT;
}
return OK;
}
@@ -167,15 +168,16 @@
}
status_t AudioPlayback::fillBuffer() {
- if (PLAY_STARTED != mState && PLAY_STOPPED != mState) return INVALID_OPERATION;
- int retry = 25;
+ if (PLAY_STARTED != mState) return INVALID_OPERATION;
+ const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+ int counter = 0;
uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mMemory->unsecurePointer()));
size_t nonContig = 0;
size_t bytesAvailable = mMemCapacity - mBytesUsedSoFar;
while (bytesAvailable > 0) {
AudioTrack::Buffer trackBuffer;
trackBuffer.frameCount = mTrack->frameCount() * 2;
- status_t status = mTrack->obtainBuffer(&trackBuffer, retry, &nonContig);
+ status_t status = mTrack->obtainBuffer(&trackBuffer, 1, &nonContig);
if (OK == status) {
size_t bytesToCopy = std::min(bytesAvailable, trackBuffer.size());
if (bytesToCopy > 0) {
@@ -184,14 +186,11 @@
mTrack->releaseBuffer(&trackBuffer);
mBytesUsedSoFar += bytesToCopy;
bytesAvailable = mMemCapacity - mBytesUsedSoFar;
- if (bytesAvailable == 0) {
- stop();
- }
+ counter = 0;
} else if (WOULD_BLOCK == status) {
- if (mStopPlaying)
- return OK;
- else
- return TIMED_OUT;
+ // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
+ if (counter == maxTries) return TIMED_OUT;
+ counter++;
}
}
return OK;
@@ -199,14 +198,15 @@
status_t AudioPlayback::waitForConsumption(bool testSeek) {
if (PLAY_STARTED != mState) return INVALID_OPERATION;
- // in static buffer mode, lets not play clips with duration > 30 sec
- int retry = 300;
- // Total number of frames in the input file.
+
+ const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+ int counter = 0;
size_t totalFrameCount = mMemCapacity / mTrack->frameSize();
- while (!mStopPlaying && retry > 0) {
- // Get the total numbers of frames played.
+ while (!mStopPlaying && counter < maxTries) {
uint32_t currPosition;
mTrack->getPosition(&currPosition);
+ if (currPosition >= totalFrameCount) counter++;
+
if (testSeek && (currPosition > totalFrameCount * 0.6)) {
testSeek = false;
if (!mTrack->hasStarted()) return BAD_VALUE;
@@ -227,10 +227,9 @@
if (bufferPosition != setPosition) return BAD_VALUE;
mTrack->start();
}
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- retry--;
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_PERIOD_MS));
}
- if (!mStopPlaying) return TIMED_OUT;
+ if (!mStopPlaying && counter == maxTries) return TIMED_OUT;
return OK;
}
@@ -246,7 +245,7 @@
void AudioPlayback::stop() {
std::unique_lock<std::mutex> lock{mMutex};
mStopPlaying = true;
- if (mState != PLAY_STOPPED) {
+ if (mState != PLAY_STOPPED && mState != PLAY_NO_INIT) {
int32_t msec = 0;
(void)mTrack->pendingDuration(&msec);
mTrack->stopAndJoinCallbacks();
@@ -274,7 +273,7 @@
}
// no more frames to read
- if (mNumFramesReceived > mNumFramesToRecord || mStopRecording) {
+ if (mNumFramesReceived >= mNumFramesToRecord || mStopRecording) {
mStopRecording = true;
return 0;
}
@@ -369,14 +368,16 @@
AudioCapture::AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format,
audio_channel_mask_t channelMask, audio_input_flags_t flags,
- audio_session_t sessionId, AudioRecord::transfer_type transferType)
+ audio_session_t sessionId, AudioRecord::transfer_type transferType,
+ const audio_attributes_t* attributes)
: mInputSource(inputSource),
mSampleRate(sampleRate),
mFormat(format),
mChannelMask(channelMask),
mFlags(flags),
mSessionId(sessionId),
- mTransferType(transferType) {
+ mTransferType(transferType),
+ mAttributes(attributes) {
mFrameCount = 0;
mNotificationFrames = 0;
mNumFramesToRecord = 0;
@@ -389,9 +390,6 @@
mReceivedCbMarkerCount = 0;
mState = REC_NO_INIT;
mStopRecording = false;
-#if RECORD_TO_FILE
- CreateRandomFile(mOutFileFd);
-#endif
}
AudioCapture::~AudioCapture() {
@@ -431,19 +429,20 @@
if (mSampleRate == 48000) { // test all available constructors
mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
attributionSource, mFrameCount, nullptr /* callback */,
- mNotificationFrames, mSessionId, mTransferType, mFlags);
+ mNotificationFrames, mSessionId, mTransferType, mFlags,
+ mAttributes);
} else {
mRecord = new AudioRecord(attributionSource);
status = mRecord->set(mInputSource, mSampleRate, mFormat, mChannelMask, mFrameCount,
nullptr /* callback */, 0 /* notificationFrames */,
false /* canCallJava */, mSessionId, mTransferType, mFlags,
- attributionSource.uid, attributionSource.pid);
+ attributionSource.uid, attributionSource.pid, mAttributes);
}
if (NO_ERROR != status) return status;
} else if (mTransferType == AudioRecord::TRANSFER_CALLBACK) {
mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
attributionSource, mFrameCount, this, mNotificationFrames,
- mSessionId, mTransferType, mFlags);
+ mSessionId, mTransferType, mFlags, mAttributes);
} else {
ALOGE("Test application is not handling transfer type %s",
AudioRecord::convertTransferToText(mTransferType));
@@ -460,6 +459,26 @@
return status;
}
+status_t AudioCapture::setRecordDuration(float durationInSec) {
+ if (REC_READY != mState) {
+ return INVALID_OPERATION;
+ }
+ uint32_t sampleRate = mSampleRate == 0 ? mRecord->getSampleRate() : mSampleRate;
+ mNumFramesToRecord = (sampleRate * durationInSec);
+ return OK;
+}
+
+status_t AudioCapture::enableRecordDump() {
+ if (mOutFileFd != -1) {
+ return INVALID_OPERATION;
+ }
+ TemporaryFile tf("/data/local/tmp");
+ tf.DoNotRemove();
+ mOutFileFd = tf.release();
+ mFileName = std::string{tf.path};
+ return OK;
+}
+
sp<AudioRecord> AudioCapture::getAudioRecordHandle() {
return (REC_NO_INIT == mState) ? nullptr : mRecord;
}
@@ -481,7 +500,7 @@
status_t AudioCapture::stop() {
status_t status = OK;
mStopRecording = true;
- if (mState != REC_STOPPED) {
+ if (mState != REC_STOPPED && mState != REC_NO_INIT) {
if (mInputSource != AUDIO_SOURCE_DEFAULT) {
bool state = false;
status = AudioSystem::isSourceActive(mInputSource, &state);
@@ -495,81 +514,66 @@
}
status_t AudioCapture::obtainBuffer(RawBuffer& buffer) {
- if (REC_STARTED != mState && REC_STOPPED != mState) return INVALID_OPERATION;
- int retry = 25;
- AudioRecord::Buffer recordBuffer;
- recordBuffer.frameCount = mNotificationFrames;
+ if (REC_STARTED != mState) return INVALID_OPERATION;
+ const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+ int counter = 0;
size_t nonContig = 0;
- status_t status = mRecord->obtainBuffer(&recordBuffer, retry, &nonContig);
- if (OK == status) {
- const int64_t timestampUs =
- ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
- mRecord->getSampleRate();
- RawBuffer buff{-1, timestampUs, static_cast<int32_t>(recordBuffer.size())};
- memcpy(buff.mData.get(), recordBuffer.data(), recordBuffer.size());
- buffer = std::move(buff);
- mNumFramesReceived += recordBuffer.size() / mRecord->frameSize();
- mRecord->releaseBuffer(&recordBuffer);
- if (mNumFramesReceived > mNumFramesToRecord) {
- stop();
+ while (mNumFramesReceived < mNumFramesToRecord) {
+ AudioRecord::Buffer recordBuffer;
+ recordBuffer.frameCount = mNotificationFrames;
+ status_t status = mRecord->obtainBuffer(&recordBuffer, 1, &nonContig);
+ if (OK == status) {
+ const int64_t timestampUs =
+ ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
+ mRecord->getSampleRate();
+ RawBuffer buff{-1, timestampUs, static_cast<int32_t>(recordBuffer.size())};
+ memcpy(buff.mData.get(), recordBuffer.data(), recordBuffer.size());
+ buffer = std::move(buff);
+ mNumFramesReceived += recordBuffer.size() / mRecord->frameSize();
+ mRecord->releaseBuffer(&recordBuffer);
+ counter = 0;
+ } else if (WOULD_BLOCK == status) {
+ // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
+ if (counter == maxTries) return TIMED_OUT;
+ counter++;
}
- } else if (status == WOULD_BLOCK) {
- if (mStopRecording)
- return WOULD_BLOCK;
- else
- return TIMED_OUT;
}
return OK;
}
status_t AudioCapture::obtainBufferCb(RawBuffer& buffer) {
if (REC_STARTED != mState) return INVALID_OPERATION;
- int retry = 10;
+ const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+ int counter = 0;
std::unique_lock<std::mutex> lock{mMutex};
- while (mBuffersReceived.empty() && !mStopRecording && retry > 0) {
- mCondition.wait_for(lock, std::chrono::milliseconds(100));
- retry--;
+ while (mBuffersReceived.empty() && !mStopRecording && counter < maxTries) {
+ mCondition.wait_for(lock, std::chrono::milliseconds(WAIT_PERIOD_MS));
+ counter++;
}
if (!mBuffersReceived.empty()) {
auto it = mBuffersReceived.begin();
buffer = std::move(*it);
mBuffersReceived.erase(it);
} else {
- if (retry == 0) return TIMED_OUT;
- if (mStopRecording)
- return WOULD_BLOCK;
- else
- return UNKNOWN_ERROR;
+ if (!mStopRecording && counter == maxTries) return TIMED_OUT;
}
return OK;
}
status_t AudioCapture::audioProcess() {
RawBuffer buffer;
- while (true) {
- status_t status;
+ status_t status = OK;
+ while (mNumFramesReceived < mNumFramesToRecord && status == OK) {
if (mTransferType == AudioRecord::TRANSFER_CALLBACK)
status = obtainBufferCb(buffer);
else
status = obtainBuffer(buffer);
- switch (status) {
- case OK:
- if (mOutFileFd > 0) {
- const char* ptr =
- static_cast<const char*>(static_cast<void*>(buffer.mData.get()));
- write(mOutFileFd, ptr, buffer.mCapacity);
- }
- break;
- case WOULD_BLOCK:
- return OK;
- case TIMED_OUT: // "recorder application timed out from receiving buffers"
- case NO_INIT: // "recorder not initialized"
- case INVALID_OPERATION: // "recorder not started"
- case UNKNOWN_ERROR: // "Unknown error"
- default:
- return status;
+ if (OK == status && mOutFileFd > 0) {
+ const char* ptr = static_cast<const char*>(static_cast<void*>(buffer.mData.get()));
+ write(mOutFileFd, ptr, buffer.mCapacity);
}
}
+ return OK;
}
status_t listAudioPorts(std::vector<audio_port_v7>& portsVec) {
@@ -613,13 +617,15 @@
}
status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
- audio_devices_t deviceType, audio_port_v7& port) {
+ audio_devices_t deviceType, const std::string& address,
+ audio_port_v7& port) {
std::vector<struct audio_port_v7> ports;
status_t status = listAudioPorts(ports);
if (status != OK) return status;
for (auto i = 0; i < ports.size(); i++) {
if (ports[i].role == role && ports[i].type == type &&
- ports[i].ext.device.type == deviceType) {
+ ports[i].ext.device.type == deviceType &&
+ !strncmp(ports[i].ext.device.address, address.c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN)) {
port = ports[i];
return OK;
}
diff --git a/media/libaudioclient/tests/audio_test_utils.h b/media/libaudioclient/tests/audio_test_utils.h
index f35b65d..90c30c2 100644
--- a/media/libaudioclient/tests/audio_test_utils.h
+++ b/media/libaudioclient/tests/audio_test_utils.h
@@ -34,8 +34,6 @@
#include <media/AudioRecord.h>
#include <media/AudioTrack.h>
-#define RECORD_TO_FILE 0
-
using namespace android;
struct MixPort {
@@ -53,11 +51,11 @@
status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
std::vector<MixPort>& mixPorts,
std::vector<Route>& routes);
-void CreateRandomFile(int& fd);
status_t listAudioPorts(std::vector<audio_port_v7>& portsVec);
status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec);
status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
- audio_devices_t deviceType, audio_port_v7& port);
+ audio_devices_t deviceType, const std::string& address,
+ audio_port_v7& port);
status_t getPatchForOutputMix(audio_io_handle_t audioIo, audio_patch& patch);
status_t getPatchForInputMix(audio_io_handle_t audioIo, audio_patch& patch);
bool patchContainsOutputDevice(audio_port_handle_t deviceId, audio_patch patch);
@@ -76,7 +74,7 @@
std::condition_variable mCondition;
void onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId);
- status_t waitForAudioDeviceCb();
+ status_t waitForAudioDeviceCb(audio_port_handle_t expDeviceId = AUDIO_PORT_HANDLE_NONE);
};
// Simple AudioPlayback class.
@@ -148,7 +146,8 @@
audio_channel_mask_t channelMask,
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
- AudioRecord::transfer_type transferType = AudioRecord::TRANSFER_CALLBACK);
+ AudioRecord::transfer_type transferType = AudioRecord::TRANSFER_CALLBACK,
+ const audio_attributes_t* attributes = nullptr);
~AudioCapture();
size_t onMoreData(const AudioRecord::Buffer& buffer) override;
void onOverrun() override;
@@ -156,6 +155,9 @@
void onNewPos(uint32_t newPos) override;
void onNewIAudioRecord() override;
status_t create();
+ status_t setRecordDuration(float durationInSec);
+ status_t enableRecordDump();
+ std::string getRecordDumpFileName() const { return mFileName; }
sp<AudioRecord> getAudioRecordHandle();
status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
audio_session_t triggerSession = AUDIO_SESSION_NONE);
@@ -190,11 +192,13 @@
const audio_input_flags_t mFlags;
const audio_session_t mSessionId;
const AudioRecord::transfer_type mTransferType;
+ const audio_attributes_t* mAttributes;
size_t mMaxBytesPerCallback = 2048;
sp<AudioRecord> mRecord;
State mState;
bool mStopRecording;
+ std::string mFileName;
int mOutFileFd = -1;
std::mutex mMutex;
diff --git a/media/libaudioclient/tests/audioeffect_analyser.cpp b/media/libaudioclient/tests/audioeffect_analyser.cpp
new file mode 100644
index 0000000..94accae
--- /dev/null
+++ b/media/libaudioclient/tests/audioeffect_analyser.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2022 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 "AudioEffectAnalyser"
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <media/AudioEffect.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_equalizer.h>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "audio_test_utils.h"
+#include "pffft.hpp"
+
+#define CHECK_OK(expr, msg) \
+ mStatus = (expr); \
+ if (OK != mStatus) { \
+ mMsg = (msg); \
+ return; \
+ }
+
+using namespace android;
+
+constexpr float kDefAmplitude = 0.60f;
+
+constexpr float kPlayBackDurationSec = 1.5;
+constexpr float kCaptureDurationSec = 1.0;
+constexpr float kPrimeDurationInSec = 0.5;
+
+// chosen to safely sample largest center freq of eq bands
+constexpr uint32_t kSamplingFrequency = 48000;
+
+// allows no fmt conversion before fft
+constexpr audio_format_t kFormat = AUDIO_FORMAT_PCM_FLOAT;
+
+// playback and capture are done with channel mask configured to mono.
+// effect analysis should not depend on mask, mono makes it easier.
+
+constexpr int kNPointFFT = 16384;
+constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
+
+const char* gPackageName = "AudioEffectAnalyser";
+
+static_assert(kPrimeDurationInSec + 2 * kNPointFFT / kSamplingFrequency < kCaptureDurationSec,
+ "capture at least, prime, pad, nPointFft size of samples");
+static_assert(kPrimeDurationInSec + 2 * kNPointFFT / kSamplingFrequency < kPlayBackDurationSec,
+ "playback needs to be active during capture");
+
+struct CaptureEnv {
+ // input args
+ uint32_t mSampleRate{kSamplingFrequency};
+ audio_format_t mFormat{kFormat};
+ audio_channel_mask_t mChannelMask{AUDIO_CHANNEL_IN_MONO};
+ float mCaptureDuration{kCaptureDurationSec};
+ // output val
+ status_t mStatus{OK};
+ std::string mMsg;
+ std::string mDumpFileName;
+
+ ~CaptureEnv();
+ void capture();
+};
+
+CaptureEnv::~CaptureEnv() {
+ if (!mDumpFileName.empty()) {
+ std::ifstream f(mDumpFileName);
+ if (f.good()) {
+ f.close();
+ remove(mDumpFileName.c_str());
+ }
+ }
+}
+
+void CaptureEnv::capture() {
+ audio_port_v7 port;
+ CHECK_OK(getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port),
+ "Could not find port")
+ const auto capture =
+ sp<AudioCapture>::make(AUDIO_SOURCE_REMOTE_SUBMIX, mSampleRate, mFormat, mChannelMask);
+ CHECK_OK(capture->create(), "record creation failed")
+ CHECK_OK(capture->setRecordDuration(mCaptureDuration), "set record duration failed")
+ CHECK_OK(capture->enableRecordDump(), "enable record dump failed")
+ auto cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
+ CHECK_OK(capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture),
+ "addAudioDeviceCallback failed")
+ CHECK_OK(capture->start(), "start recording failed")
+ CHECK_OK(capture->audioProcess(), "recording process failed")
+ CHECK_OK(cbCapture->waitForAudioDeviceCb(), "audio device callback notification timed out");
+ if (port.id != capture->getAudioRecordHandle()->getRoutedDeviceId()) {
+ CHECK_OK(BAD_VALUE, "Capture NOT routed on expected port")
+ }
+ CHECK_OK(getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port),
+ "Could not find port")
+ CHECK_OK(capture->stop(), "record stop failed")
+ mDumpFileName = capture->getRecordDumpFileName();
+}
+
+struct PlaybackEnv {
+ // input args
+ uint32_t mSampleRate{kSamplingFrequency};
+ audio_format_t mFormat{kFormat};
+ audio_channel_mask_t mChannelMask{AUDIO_CHANNEL_OUT_MONO};
+ audio_session_t mSessionId{AUDIO_SESSION_NONE};
+ std::string mRes;
+ // output val
+ status_t mStatus{OK};
+ std::string mMsg;
+
+ void play();
+};
+
+void PlaybackEnv::play() {
+ const auto ap =
+ sp<AudioPlayback>::make(mSampleRate, mFormat, mChannelMask, AUDIO_OUTPUT_FLAG_NONE,
+ mSessionId, AudioTrack::TRANSFER_OBTAIN);
+ CHECK_OK(ap->loadResource(mRes.c_str()), "Unable to open Resource")
+ const auto cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+ CHECK_OK(ap->create(), "track creation failed")
+ ap->getAudioTrackHandle()->setVolume(1.0f);
+ CHECK_OK(ap->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback),
+ "addAudioDeviceCallback failed")
+ CHECK_OK(ap->start(), "audio track start failed")
+ CHECK_OK(cbPlayback->waitForAudioDeviceCb(), "audio device callback notification timed out")
+ CHECK_OK(ap->onProcess(), "playback process failed")
+ ap->stop();
+}
+
+void generateMultiTone(const std::vector<int>& toneFrequencies, float samplingFrequency,
+ float duration, float amplitude, float* buffer, int numSamples) {
+ int totalFrameCount = (samplingFrequency * duration);
+ int limit = std::min(totalFrameCount, numSamples);
+
+ for (auto i = 0; i < limit; i++) {
+ buffer[i] = 0;
+ for (auto j = 0; j < toneFrequencies.size(); j++) {
+ buffer[i] += sin(2 * M_PI * toneFrequencies[j] * i / samplingFrequency);
+ }
+ buffer[i] *= (amplitude / toneFrequencies.size());
+ }
+}
+
+sp<AudioEffect> createEffect(const effect_uuid_t* type,
+ audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX) {
+ std::string packageName{gPackageName};
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = packageName;
+ attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+ attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+ attributionSource.token = sp<BBinder>::make();
+ sp<AudioEffect> effect = sp<AudioEffect>::make(attributionSource);
+ effect->set(type, nullptr, 0, nullptr, sessionId, AUDIO_IO_HANDLE_NONE, {}, false, false);
+ return effect;
+}
+
+void computeFilterGainsAtTones(float captureDuration, int nPointFft, std::vector<int>& binOffsets,
+ float* inputMag, float* gaindB, const char* res,
+ audio_session_t sessionId) {
+ int totalFrameCount = captureDuration * kSamplingFrequency;
+ auto output = pffft::AlignedVector<float>(totalFrameCount);
+ auto fftOutput = pffft::AlignedVector<float>(nPointFft);
+ PlaybackEnv argsP;
+ argsP.mRes = std::string{res};
+ argsP.mSessionId = sessionId;
+ CaptureEnv argsR;
+ argsR.mCaptureDuration = captureDuration;
+ std::thread playbackThread(&PlaybackEnv::play, &argsP);
+ std::thread captureThread(&CaptureEnv::capture, &argsR);
+ captureThread.join();
+ playbackThread.join();
+ ASSERT_EQ(OK, argsR.mStatus) << argsR.mMsg;
+ ASSERT_EQ(OK, argsP.mStatus) << argsP.mMsg;
+ ASSERT_FALSE(argsR.mDumpFileName.empty()) << "recorded not written to file";
+ std::ifstream fin(argsR.mDumpFileName, std::ios::in | std::ios::binary);
+ fin.read((char*)output.data(), totalFrameCount * sizeof(output[0]));
+ fin.close();
+ PFFFT_Setup* handle = pffft_new_setup(nPointFft, PFFFT_REAL);
+ // ignore first few samples. This is to not analyse until audio track is re-routed to remote
+ // submix source, also for the effect filter response to reach steady-state (priming / pruning
+ // samples).
+ int rerouteOffset = kPrimeDurationInSec * kSamplingFrequency;
+ pffft_transform_ordered(handle, output.data() + rerouteOffset, fftOutput.data(), nullptr,
+ PFFFT_FORWARD);
+ pffft_destroy_setup(handle);
+ for (auto i = 0; i < binOffsets.size(); i++) {
+ auto k = binOffsets[i];
+ auto outputMag = sqrt((fftOutput[k * 2] * fftOutput[k * 2]) +
+ (fftOutput[k * 2 + 1] * fftOutput[k * 2 + 1]));
+ gaindB[i] = 20 * log10(outputMag / inputMag[i]);
+ }
+}
+
+std::tuple<int, int> roundToFreqCenteredToFftBin(float binWidth, float freq) {
+ int bin_index = std::round(freq / binWidth);
+ int cfreq = std::round(bin_index * binWidth);
+ return std::make_tuple(bin_index, cfreq);
+}
+
+TEST(AudioEffectTest, CheckEqualizerEffect) {
+ audio_session_t sessionId =
+ (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ sp<AudioEffect> equalizer = createEffect(SL_IID_EQUALIZER, sessionId);
+ ASSERT_EQ(OK, equalizer->initCheck());
+ ASSERT_EQ(NO_ERROR, equalizer->setEnabled(true));
+ if ((equalizer->descriptor().flags & EFFECT_FLAG_HW_ACC_MASK) != 0) {
+ GTEST_SKIP() << "effect processed output inaccessible, skipping test";
+ }
+#define MAX_PARAMS 64
+ uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + MAX_PARAMS];
+ effect_param_t* eqParam = (effect_param_t*)(&buf32);
+
+ // get num of presets
+ eqParam->psize = sizeof(uint32_t);
+ eqParam->vsize = sizeof(uint16_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_GET_NUM_OF_PRESETS;
+ EXPECT_EQ(0, equalizer->getParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ int numPresets = *((uint16_t*)((int32_t*)eqParam->data + 1));
+
+ // get num of bands
+ eqParam->psize = sizeof(uint32_t);
+ eqParam->vsize = sizeof(uint16_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_NUM_BANDS;
+ EXPECT_EQ(0, equalizer->getParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ int numBands = *((uint16_t*)((int32_t*)eqParam->data + 1));
+
+ const int totalFrameCount = kSamplingFrequency * kPlayBackDurationSec;
+
+ // get band center frequencies
+ std::vector<int> centerFrequencies;
+ std::vector<int> binOffsets;
+ for (auto i = 0; i < numBands; i++) {
+ eqParam->psize = sizeof(uint32_t) * 2;
+ eqParam->vsize = sizeof(uint32_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_CENTER_FREQ;
+ *((uint16_t*)((int32_t*)eqParam->data + 1)) = i;
+ EXPECT_EQ(0, equalizer->getParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ float cfreq = *((int32_t*)eqParam->data + 2) / 1000; // milli hz
+ // pick frequency close to bin center frequency
+ auto [bin_index, bin_freq] = roundToFreqCenteredToFftBin(kBinWidth, cfreq);
+ centerFrequencies.push_back(bin_freq);
+ binOffsets.push_back(bin_index);
+ }
+
+ // input for effect module
+ auto input = pffft::AlignedVector<float>(totalFrameCount);
+ generateMultiTone(centerFrequencies, kSamplingFrequency, kPlayBackDurationSec, kDefAmplitude,
+ input.data(), totalFrameCount);
+ auto fftInput = pffft::AlignedVector<float>(kNPointFFT);
+ PFFFT_Setup* handle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
+ pffft_transform_ordered(handle, input.data(), fftInput.data(), nullptr, PFFFT_FORWARD);
+ pffft_destroy_setup(handle);
+ float inputMag[numBands];
+ for (auto i = 0; i < numBands; i++) {
+ auto k = binOffsets[i];
+ inputMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
+ (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
+ }
+ TemporaryFile tf("/data/local/tmp");
+ close(tf.release());
+ std::ofstream fout(tf.path, std::ios::out | std::ios::binary);
+ fout.write((char*)input.data(), input.size() * sizeof(input[0]));
+ fout.close();
+
+ float expGaindB[numBands], actGaindB[numBands];
+
+ std::string msg = "";
+ int numPresetsOk = 0;
+ for (auto preset = 0; preset < numPresets; preset++) {
+ // set preset
+ eqParam->psize = sizeof(uint32_t);
+ eqParam->vsize = sizeof(uint32_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_CUR_PRESET;
+ *((uint16_t*)((int32_t*)eqParam->data + 1)) = preset;
+ EXPECT_EQ(0, equalizer->setParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ // get preset gains
+ eqParam->psize = sizeof(uint32_t);
+ eqParam->vsize = (numBands + 1) * sizeof(uint32_t);
+ *(int32_t*)eqParam->data = EQ_PARAM_PROPERTIES;
+ EXPECT_EQ(0, equalizer->getParameter(eqParam));
+ EXPECT_EQ(0, eqParam->status);
+ t_equalizer_settings* settings =
+ reinterpret_cast<t_equalizer_settings*>((int32_t*)eqParam->data + 1);
+ EXPECT_EQ(preset, settings->curPreset);
+ EXPECT_EQ(numBands, settings->numBands);
+ for (auto i = 0; i < numBands; i++) {
+ expGaindB[i] = ((int16_t)settings->bandLevels[i]) / 100.0f; // gain in milli bels
+ }
+ memset(actGaindB, 0, sizeof(actGaindB));
+ ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT,
+ binOffsets, inputMag, actGaindB, tf.path,
+ sessionId));
+ bool isOk = true;
+ for (auto i = 0; i < numBands - 1; i++) {
+ auto diffA = expGaindB[i] - expGaindB[i + 1];
+ auto diffB = actGaindB[i] - actGaindB[i + 1];
+ if (diffA == 0 && fabs(diffA - diffB) > 1.0f) {
+ msg += (android::base::StringPrintf(
+ "For eq preset : %d, between bands %d and %d, expected relative gain is : "
+ "%f, got relative gain is : %f, error : %f \n",
+ preset, i, i + 1, diffA, diffB, diffA - diffB));
+ isOk = false;
+ } else if (diffA * diffB < 0) {
+ msg += (android::base::StringPrintf(
+ "For eq preset : %d, between bands %d and %d, expected relative gain and "
+ "seen relative gain are of opposite signs \n. Expected relative gain is : "
+ "%f, seen relative gain is : %f \n",
+ preset, i, i + 1, diffA, diffB));
+ isOk = false;
+ }
+ }
+ if (isOk) numPresetsOk++;
+ }
+ EXPECT_EQ(numPresetsOk, numPresets) << msg;
+}
+
+TEST(AudioEffectTest, CheckBassBoostEffect) {
+ audio_session_t sessionId =
+ (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ sp<AudioEffect> bassboost = createEffect(SL_IID_BASSBOOST, sessionId);
+ ASSERT_EQ(OK, bassboost->initCheck());
+ ASSERT_EQ(NO_ERROR, bassboost->setEnabled(true));
+ if ((bassboost->descriptor().flags & EFFECT_FLAG_HW_ACC_MASK) != 0) {
+ GTEST_SKIP() << "effect processed output inaccessible, skipping test";
+ }
+ int32_t buf32[sizeof(effect_param_t) / sizeof(int32_t) + MAX_PARAMS];
+ effect_param_t* bbParam = (effect_param_t*)(&buf32);
+
+ bbParam->psize = sizeof(int32_t);
+ bbParam->vsize = sizeof(int32_t);
+ *(int32_t*)bbParam->data = BASSBOOST_PARAM_STRENGTH_SUPPORTED;
+ EXPECT_EQ(0, bassboost->getParameter(bbParam));
+ EXPECT_EQ(0, bbParam->status);
+ bool strengthSupported = *((int32_t*)bbParam->data + 1);
+
+ const int totalFrameCount = kSamplingFrequency * kPlayBackDurationSec;
+
+ // selecting bass frequency, speech tone (for relative gain)
+ std::vector<int> testFrequencies{100, 1200};
+ std::vector<int> binOffsets;
+ for (auto i = 0; i < testFrequencies.size(); i++) {
+ // pick frequency close to bin center frequency
+ auto [bin_index, bin_freq] = roundToFreqCenteredToFftBin(kBinWidth, testFrequencies[i]);
+ testFrequencies[i] = bin_freq;
+ binOffsets.push_back(bin_index);
+ }
+
+ // input for effect module
+ auto input = pffft::AlignedVector<float>(totalFrameCount);
+ generateMultiTone(testFrequencies, kSamplingFrequency, kPlayBackDurationSec, kDefAmplitude,
+ input.data(), totalFrameCount);
+ auto fftInput = pffft::AlignedVector<float>(kNPointFFT);
+ PFFFT_Setup* handle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
+ pffft_transform_ordered(handle, input.data(), fftInput.data(), nullptr, PFFFT_FORWARD);
+ pffft_destroy_setup(handle);
+ float inputMag[testFrequencies.size()];
+ for (auto i = 0; i < testFrequencies.size(); i++) {
+ auto k = binOffsets[i];
+ inputMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
+ (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
+ }
+ TemporaryFile tf("/data/local/tmp");
+ close(tf.release());
+ std::ofstream fout(tf.path, std::ios::out | std::ios::binary);
+ fout.write((char*)input.data(), input.size() * sizeof(input[0]));
+ fout.close();
+
+ float gainWithOutFilter[testFrequencies.size()];
+ memset(gainWithOutFilter, 0, sizeof(gainWithOutFilter));
+ ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT, binOffsets,
+ inputMag, gainWithOutFilter, tf.path,
+ AUDIO_SESSION_OUTPUT_MIX));
+ float diffA = gainWithOutFilter[0] - gainWithOutFilter[1];
+ float prevGain = -100.f;
+ for (auto strength = 150; strength < 1000; strength += strengthSupported ? 150 : 1000) {
+ // configure filter strength
+ if (strengthSupported) {
+ bbParam->psize = sizeof(int32_t);
+ bbParam->vsize = sizeof(int16_t);
+ *(int32_t*)bbParam->data = BASSBOOST_PARAM_STRENGTH;
+ *((int16_t*)((int32_t*)bbParam->data + 1)) = strength;
+ EXPECT_EQ(0, bassboost->setParameter(bbParam));
+ EXPECT_EQ(0, bbParam->status);
+ }
+ float gainWithFilter[testFrequencies.size()];
+ memset(gainWithFilter, 0, sizeof(gainWithFilter));
+ ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT,
+ binOffsets, inputMag, gainWithFilter,
+ tf.path, sessionId));
+ float diffB = gainWithFilter[0] - gainWithFilter[1];
+ EXPECT_GT(diffB, diffA) << "bassboost effect not seen";
+ EXPECT_GE(diffB, prevGain) << "increase in boost strength causing fall in gain";
+ prevGain = diffB;
+ }
+}
diff --git a/media/libaudioclient/tests/audiorouting_tests.cpp b/media/libaudioclient/tests/audiorouting_tests.cpp
index 4bd81c8..2c5fcd7 100644
--- a/media/libaudioclient/tests/audiorouting_tests.cpp
+++ b/media/libaudioclient/tests/audiorouting_tests.cpp
@@ -46,10 +46,10 @@
attributes.usage = AUDIO_USAGE_MEDIA;
attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
attributes.flags = flags[i];
- sp<AudioPlayback> ap = sp<AudioPlayback>::make(
- 0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
- AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN,
- &attributes);
+ sp<AudioPlayback> ap = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+ AudioTrack::TRANSFER_OBTAIN, &attributes);
ASSERT_NE(nullptr, ap);
ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
<< "Unable to open Resource";
@@ -77,46 +77,186 @@
}
}
-TEST(AudioTrackTest, TestRemoteSubmix) {
- std::vector<std::string> attachedDevices;
- std::vector<MixPort> mixPorts;
- std::vector<Route> routes;
- EXPECT_EQ(OK, parse_audio_policy_configuration_xml(attachedDevices, mixPorts, routes));
- bool hasFlag = false;
- for (int j = 0; j < attachedDevices.size() && !hasFlag; j++) {
- if (attachedDevices[j].find("Remote Submix") != -1) hasFlag = true;
+TEST(AudioTrackTest, DefaultRoutingTest) {
+ audio_port_v7 port;
+ if (OK != getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port)) {
+ GTEST_SKIP() << "remote submix in device not connected";
}
- if (!hasFlag) GTEST_SKIP() << " Device does not have Remote Submix port.";
- sp<AudioCapture> capture = new AudioCapture(AUDIO_SOURCE_REMOTE_SUBMIX, 48000,
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
- ASSERT_NE(nullptr, capture);
- ASSERT_EQ(OK, capture->create()) << "record creation failed";
+ // create record instance
+ sp<AudioCapture> capture = sp<AudioCapture>::make(
+ AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
+ ASSERT_NE(nullptr, capture);
+ EXPECT_EQ(OK, capture->create()) << "record creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture));
+
+ // create playback instance
sp<AudioPlayback> playback = sp<AudioPlayback>::make(
48000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE);
ASSERT_NE(nullptr, playback);
ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
<< "Unable to open Resource";
- ASSERT_EQ(OK, playback->create()) << "track creation failed";
+ EXPECT_EQ(OK, playback->create()) << "track creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
- audio_port_v7 port;
- status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX, port);
- EXPECT_EQ(OK, status) << "Could not find port";
-
+ // capture should be routed to submix in port
EXPECT_EQ(OK, capture->start()) << "start recording failed";
+ EXPECT_EQ(OK, cbCapture->waitForAudioDeviceCb());
EXPECT_EQ(port.id, capture->getAudioRecordHandle()->getRoutedDeviceId())
<< "Capture NOT routed on expected port";
- status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, port);
+ // capture start should create submix out port
+ status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
EXPECT_EQ(OK, status) << "Could not find port";
+ // playback should be routed to submix out as long as capture is active
EXPECT_EQ(OK, playback->start()) << "audio track start failed";
- EXPECT_EQ(OK, playback->onProcess());
- ASSERT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+ EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb());
+ EXPECT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
<< "Playback NOT routed on expected port";
+
capture->stop();
playback->stop();
}
+
+class AudioRoutingTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ audio_port_v7 port;
+ if (OK != getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port)) {
+ GTEST_SKIP() << "remote submix in device not connected";
+ }
+ uint32_t mixType = MIX_TYPE_PLAYERS;
+ uint32_t mixFlag = MIX_ROUTE_FLAG_LOOP_BACK;
+ audio_devices_t deviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ AudioMixMatchCriterion criterion(AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
+ RULE_MATCH_ATTRIBUTE_USAGE);
+ std::vector<AudioMixMatchCriterion> criteria{criterion};
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ config.format = AUDIO_FORMAT_PCM_16_BIT;
+ config.sample_rate = 48000;
+ AudioMix mix(criteria, mixType, config, mixFlag, String8{mAddress.c_str()}, 0);
+ mix.mDeviceType = deviceType;
+ mMixes.push(mix);
+ if (OK == AudioSystem::registerPolicyMixes(mMixes, true)) {
+ mPolicyMixRegistered = true;
+ }
+ ASSERT_TRUE(mPolicyMixRegistered) << "register policy mix failed";
+ }
+
+ void TearDown() override {
+ if (mPolicyMixRegistered) {
+ EXPECT_EQ(OK, AudioSystem::registerPolicyMixes(mMixes, false));
+ }
+ }
+
+ bool mPolicyMixRegistered{false};
+ std::string mAddress{"mix_1"};
+ Vector<AudioMix> mMixes;
+};
+
+TEST_F(AudioRoutingTest, ConcurrentDynamicRoutingTest) {
+ audio_port_v7 port, port_mix;
+ // expect legacy submix in port to be connected
+ status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port);
+ EXPECT_EQ(OK, status) << "Could not find port";
+
+ // as policy mix is registered, expect submix in port with mAddress to be connected
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, mAddress, port_mix);
+ EXPECT_EQ(OK, status) << "Could not find port";
+
+ // create playback instance
+ sp<AudioPlayback> playback = sp<AudioPlayback>::make(
+ 48000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN);
+ ASSERT_NE(nullptr, playback);
+ ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+ << "Unable to open Resource";
+ EXPECT_EQ(OK, playback->create()) << "track creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
+
+ // create capture instances on different ports
+ sp<AudioCapture> captureA = sp<AudioCapture>::make(
+ AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
+ ASSERT_NE(nullptr, captureA);
+ EXPECT_EQ(OK, captureA->create()) << "record creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbCaptureA = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, captureA->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureA));
+
+ audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+ attr.source = AUDIO_SOURCE_REMOTE_SUBMIX;
+ sprintf(attr.tags, "addr=%s", mAddress.c_str());
+ sp<AudioCapture> captureB = sp<AudioCapture>::make(
+ AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+ AUDIO_INPUT_FLAG_NONE, AUDIO_SESSION_ALLOCATE, AudioRecord::TRANSFER_CALLBACK, &attr);
+ ASSERT_NE(nullptr, captureB);
+ EXPECT_EQ(OK, captureB->create()) << "record creation failed";
+ sp<OnAudioDeviceUpdateNotifier> cbCaptureB = sp<OnAudioDeviceUpdateNotifier>::make();
+ EXPECT_EQ(OK, captureB->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureB));
+
+ // launch
+ EXPECT_EQ(OK, captureA->start()) << "start recording failed";
+ EXPECT_EQ(OK, cbCaptureA->waitForAudioDeviceCb());
+ EXPECT_EQ(port.id, captureA->getAudioRecordHandle()->getRoutedDeviceId())
+ << "Capture NOT routed on expected port";
+
+ EXPECT_EQ(OK, captureB->start()) << "start recording failed";
+ EXPECT_EQ(OK, cbCaptureB->waitForAudioDeviceCb());
+ EXPECT_EQ(port_mix.id, captureB->getAudioRecordHandle()->getRoutedDeviceId())
+ << "Capture NOT routed on expected port";
+
+ // as record started, expect submix out ports to be connected
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+ EXPECT_EQ(OK, status) << "unexpected submix out port found";
+
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mAddress, port_mix);
+ EXPECT_EQ(OK, status) << "Could not find port";
+
+ // check if playback routed to desired port
+ EXPECT_EQ(OK, playback->start());
+ EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb());
+ EXPECT_EQ(port_mix.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+ << "Playback NOT routed on expected port";
+
+ captureB->stop();
+
+ // check if mAddress submix out is disconnected as capture session is stopped
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mAddress, port_mix);
+ EXPECT_NE(OK, status) << "unexpected submix in port found";
+
+ // check if legacy submix out is connected
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+ EXPECT_EQ(OK, status) << "port not found";
+
+ // unregister policy
+ EXPECT_EQ(OK, AudioSystem::registerPolicyMixes(mMixes, false));
+ mPolicyMixRegistered = false;
+
+ // as policy mix is unregistered, expect submix in port with mAddress to be disconnected
+ status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, mAddress, port_mix);
+ EXPECT_NE(OK, status) << "unexpected submix in port found";
+
+ playback->onProcess();
+ // as captureA is active, it should re route to legacy submix
+ EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb(port.id));
+ EXPECT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+ << "Playback NOT routed on expected port";
+
+ captureA->stop();
+ playback->stop();
+}
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index a456a2a..c758fcd 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -18,12 +18,12 @@
export_include_dirs: ["include"],
header_libs: [
- "libaudioclient_aidl_conversion_util",
+ "libaudio_aidl_conversion_common_util_cpp",
"libaudio_system_headers",
"libmedia_helper_headers",
],
export_header_lib_headers: [
- "libaudioclient_aidl_conversion_util",
+ "libaudio_aidl_conversion_common_util_cpp",
"libaudio_system_headers",
"libmedia_helper_headers",
],
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index b6e6c84..6c01e29 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -66,6 +66,9 @@
for (const auto &channel : channelMasks) {
if (audio_channel_mask_out_to_in(channel) != AUDIO_CHANNEL_INVALID) {
inMaskSet.insert(audio_channel_mask_out_to_in(channel));
+ } else if (audio_channel_mask_get_representation(channel)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+ inMaskSet.insert(channel);
}
}
return inMaskSet;
@@ -76,6 +79,9 @@
for (const auto &channel : channelMasks) {
if (audio_channel_mask_in_to_out(channel) != AUDIO_CHANNEL_INVALID) {
outMaskSet.insert(audio_channel_mask_in_to_out(channel));
+ } else if (audio_channel_mask_get_representation(channel)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+ outMaskSet.insert(channel);
}
}
return outMaskSet;
diff --git a/media/libaudiofoundation/tests/Android.bp b/media/libaudiofoundation/tests/Android.bp
index 0e733d3..2f4aee0 100644
--- a/media/libaudiofoundation/tests/Android.bp
+++ b/media/libaudiofoundation/tests/Android.bp
@@ -23,6 +23,7 @@
static_libs: [
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
"libaudiofoundation",
"libstagefright_foundation",
],
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index 8743c04..3956a6c 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -17,11 +17,16 @@
#define LOG_TAG "EffectHalHidl"
//#define LOG_NDEBUG 0
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android-base/stringprintf.h>
#include <common/all-versions/VersionUtils.h>
#include <cutils/native_handle.h>
+#include <cutils/properties.h>
#include <hwbinder/IPCThreadState.h>
#include <media/EffectsFactoryApi.h>
+#include <mediautils/SchedulingPolicyService.h>
#include <mediautils/TimeCheck.h>
+#include <system/audio_effects/effect_spatializer.h>
#include <utils/Log.h>
#include <util/EffectUtils.h>
@@ -50,6 +55,18 @@
effect_descriptor_t halDescriptor{};
if (EffectHalHidl::getDescriptor(&halDescriptor) == NO_ERROR) {
mIsInput = (halDescriptor.flags & EFFECT_FLAG_TYPE_PRE_PROC) == EFFECT_FLAG_TYPE_PRE_PROC;
+ const bool isSpatializer =
+ memcmp(&halDescriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0;
+ if (isSpatializer) {
+ constexpr int32_t kRTPriorityMin = 1;
+ constexpr int32_t kRTPriorityMax = 3;
+ const int32_t priorityBoost = property_get_int32("audio.spatializer.priority", 1);
+ if (priorityBoost >= kRTPriorityMin && priorityBoost <= kRTPriorityMax) {
+ ALOGD("%s: audio.spatializer.priority %d on effect %lld",
+ __func__, priorityBoost, (long long)effectId);
+ mHalThreadPriority = priorityBoost;
+ }
+ }
}
}
@@ -127,6 +144,8 @@
ALOGE_IF(!mEfGroup, "Event flag creation for effects failed");
return NO_INIT;
}
+
+ (void)checkHalThreadPriority();
mStatusMQ = std::move(tempStatusMQ);
return OK;
}
@@ -317,5 +336,67 @@
return result;
}
+status_t EffectHalHidl::getHalPid(pid_t *pid) const {
+ using ::android::hidl::base::V1_0::DebugInfo;
+ using ::android::hidl::manager::V1_0::IServiceManager;
+ DebugInfo debugInfo;
+ const auto ret = mEffect->getDebugInfo([&] (const auto &info) {
+ debugInfo = info;
+ });
+ if (!ret.isOk()) {
+ ALOGW("%s: cannot get effect debug info", __func__);
+ return INVALID_OPERATION;
+ }
+ if (debugInfo.pid != (int)IServiceManager::PidConstant::NO_PID) {
+ *pid = debugInfo.pid;
+ return NO_ERROR;
+ }
+ ALOGW("%s: effect debug info does not contain pid", __func__);
+ return NAME_NOT_FOUND;
+}
+
+status_t EffectHalHidl::getHalWorkerTid(pid_t *tid) {
+ int32_t reply = -1;
+ uint32_t replySize = sizeof(reply);
+ const status_t status =
+ command('gtid', 0 /* cmdSize */, nullptr /* pCmdData */, &replySize, &reply);
+ if (status == OK) {
+ *tid = (pid_t)reply;
+ } else {
+ ALOGW("%s: failed with status:%d", __func__, status);
+ }
+ return status;
+}
+
+bool EffectHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
+ if (mHalThreadPriority == kRTPriorityDisabled) {
+ return true;
+ }
+ const int err = requestPriority(
+ threadPid, threadId,
+ mHalThreadPriority, false /*isForApp*/, true /*asynchronous*/);
+ ALOGW_IF(err, "%s: failed to set RT priority %d for pid %d tid %d; error %d",
+ __func__, mHalThreadPriority, threadPid, threadId, err);
+ // Audio will still work, but may be more susceptible to glitches.
+ return err == 0;
+}
+
+status_t EffectHalHidl::checkHalThreadPriority() {
+ if (mHalThreadPriority == kRTPriorityDisabled) return OK;
+ if (mHalThreadPriority < kRTPriorityMin
+ || mHalThreadPriority > kRTPriorityMax) return BAD_VALUE;
+
+ pid_t halPid, halWorkerTid;
+ const status_t status = getHalPid(&halPid) ?: getHalWorkerTid(&halWorkerTid);
+ const bool success = status == OK && requestHalThreadPriority(halPid, halWorkerTid);
+ ALOGD("%s: effectId %lld RT priority(%d) request %s%s",
+ __func__, (long long)mEffectId, mHalThreadPriority,
+ success ? "succeeded" : "failed",
+ status == OK
+ ? base::StringPrintf(" for pid:%d tid:%d", halPid, halWorkerTid).c_str()
+ : " (pid / tid cannot be read)");
+ return success ? OK : status != OK ? status : INVALID_OPERATION /* request failed */;
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectHalHidl.h b/media/libaudiohal/impl/EffectHalHidl.h
index e139768..94dcd7e 100644
--- a/media/libaudiohal/impl/EffectHalHidl.h
+++ b/media/libaudiohal/impl/EffectHalHidl.h
@@ -78,6 +78,11 @@
std::unique_ptr<StatusMQ> mStatusMQ;
EventFlag* mEfGroup;
bool mIsInput = false;
+ static constexpr int32_t kRTPriorityMin = 1;
+ static constexpr int32_t kRTPriorityMax = 3;
+ static constexpr int kRTPriorityDisabled = 0;
+ // Typical RealTime mHalThreadPriority ranges from 1 (low) to 3 (high).
+ int mHalThreadPriority = kRTPriorityDisabled;
// Can not be constructed directly by clients.
EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId);
@@ -93,6 +98,10 @@
uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
uint32_t *replySize, void *pReplyData);
status_t setProcessBuffers();
+ status_t getHalPid(pid_t *pid) const;
+ status_t getHalWorkerTid(pid_t *tid);
+ bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
+ status_t checkHalThreadPriority();
};
} // namespace effect
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index abe622d..742626c 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -47,3 +47,29 @@
"libhardware_headers",
],
}
+
+cc_library_shared {
+ name: "libdownmixaidl",
+ srcs: [
+ "aidl/EffectDownmix.cpp",
+ "aidl/DownmixContext.cpp",
+ ":effectCommonFile",
+ ],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers"
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "libcutils",
+ "liblog",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/downmix/aidl/DownmixContext.cpp b/media/libeffects/downmix/aidl/DownmixContext.cpp
new file mode 100644
index 0000000..6869689
--- /dev/null
+++ b/media/libeffects/downmix/aidl/DownmixContext.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2022 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_TAG "AHAL_DownmixContext"
+
+#include <android-base/logging.h>
+
+#include "DownmixContext.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using ::android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::effect {
+
+DownmixContext::DownmixContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ mState = DOWNMIX_STATE_UNINITIALIZED;
+ init_params(common);
+}
+
+DownmixContext::~DownmixContext() {
+ LOG(DEBUG) << __func__;
+ mState = DOWNMIX_STATE_UNINITIALIZED;
+}
+
+RetCode DownmixContext::enable() {
+ LOG(DEBUG) << __func__;
+ if (mState != DOWNMIX_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = DOWNMIX_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode DownmixContext::disable() {
+ LOG(DEBUG) << __func__;
+ if (mState != DOWNMIX_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = DOWNMIX_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void DownmixContext::reset() {
+ LOG(DEBUG) << __func__;
+ disable();
+ resetBuffer();
+}
+
+IEffect::Status DownmixContext::lvmProcess(float* in, float* out, int samples) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+ IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
+
+ if (in == nullptr || out == nullptr || getInputFrameSize() != getOutputFrameSize() ||
+ getInputFrameSize() == 0) {
+ return status;
+ }
+
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ if (mState == DOWNMIX_STATE_UNINITIALIZED) {
+ LOG(ERROR) << __func__ << "Trying to use an uninitialized downmixer";
+ return status;
+ } else if (mState == DOWNMIX_STATE_INITIALIZED) {
+ LOG(ERROR) << __func__ << "Trying to use a non-configured downmixer";
+ return status;
+ }
+
+ LOG(DEBUG) << __func__ << " start processing";
+ bool accumulate = false;
+ int frames = samples * sizeof(float) / getInputFrameSize();
+ if (mType == Downmix::Type::STRIP) {
+ int inputChannelCount = getChannelCount(mChMask);
+ while (frames) {
+ if (accumulate) {
+ out[0] = std::clamp(out[0] + in[0], -1.f, 1.f);
+ out[1] = std::clamp(out[1] + in[1], -1.f, 1.f);
+ } else {
+ out[0] = in[0];
+ out[1] = in[1];
+ }
+ in += inputChannelCount;
+ out += 2;
+ frames--;
+ }
+ } else {
+ int chMask = mChMask.get<AudioChannelLayout::layoutMask>();
+ if (!mChannelMix.process(in, out, frames, accumulate, (audio_channel_mask_t)chMask)) {
+ LOG(ERROR) << "Multichannel configuration " << mChMask.toString()
+ << " is not supported";
+ return status;
+ }
+ }
+ LOG(DEBUG) << __func__ << " done processing";
+ return {STATUS_OK, samples, samples};
+}
+
+void DownmixContext::init_params(const Parameter::Common& common) {
+ // when configuring the effect, do not allow a blank or unsupported channel mask
+ AudioChannelLayout channelMask = common.input.base.channelMask;
+ if (isChannelMaskValid(channelMask)) {
+ LOG(ERROR) << "Downmix_Configure error: input channel mask " << channelMask.toString()
+ << " not supported";
+ } else {
+ mType = Downmix::Type::FOLD;
+ mChMask = channelMask;
+ mState = DOWNMIX_STATE_INITIALIZED;
+ }
+}
+
+bool DownmixContext::isChannelMaskValid(AudioChannelLayout channelMask) {
+ if (channelMask.getTag() == AudioChannelLayout::layoutMask) return false;
+ int chMask = channelMask.get<AudioChannelLayout::layoutMask>();
+ // check against unsupported channels (up to FCC_26)
+ constexpr uint32_t MAXIMUM_CHANNEL_MASK = AudioChannelLayout::LAYOUT_22POINT2 |
+ AudioChannelLayout::CHANNEL_FRONT_WIDE_LEFT |
+ AudioChannelLayout::CHANNEL_FRONT_WIDE_RIGHT;
+ if (chMask & ~MAXIMUM_CHANNEL_MASK) {
+ LOG(ERROR) << "Unsupported channels in " << (chMask & ~MAXIMUM_CHANNEL_MASK);
+ return false;
+ }
+ return true;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/DownmixContext.h b/media/libeffects/downmix/aidl/DownmixContext.h
new file mode 100644
index 0000000..8a244ac
--- /dev/null
+++ b/media/libeffects/downmix/aidl/DownmixContext.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 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 "effect-impl/EffectContext.h"
+
+#include <audio_utils/ChannelMix.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioDeviceDescription;
+
+enum DownmixState {
+ DOWNMIX_STATE_UNINITIALIZED,
+ DOWNMIX_STATE_INITIALIZED,
+ DOWNMIX_STATE_ACTIVE,
+};
+
+class DownmixContext final : public EffectContext {
+ public:
+ DownmixContext(int statusDepth, const Parameter::Common& common);
+ ~DownmixContext();
+ RetCode enable();
+ RetCode disable();
+ void reset();
+
+ RetCode setDmType(Downmix::Type type) {
+ mType = type;
+ return RetCode::SUCCESS;
+ }
+ Downmix::Type getDmType() const { return mType; }
+
+ RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override {
+ // FIXME change volume
+ mVolumeStereo = volumeStereo;
+ return RetCode::SUCCESS;
+ }
+ Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+
+ RetCode setOutputDevice(const AudioDeviceDescription& device) override {
+ // FIXME change type if playing on headset vs speaker
+ mOutputDevice = device;
+ return RetCode::SUCCESS;
+ }
+ AudioDeviceDescription getOutputDevice() { return mOutputDevice; }
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ DownmixState mState;
+ Downmix::Type mType;
+ AudioChannelLayout mChMask;
+ ::android::audio_utils::channels::ChannelMix mChannelMix;
+
+ // Common Params
+ AudioDeviceDescription mOutputDevice;
+ Parameter::VolumeStereo mVolumeStereo;
+
+ void init_params(const Parameter::Common& common);
+ bool isChannelMaskValid(AudioChannelLayout channelMask);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.cpp b/media/libeffects/downmix/aidl/EffectDownmix.cpp
new file mode 100644
index 0000000..17d0736
--- /dev/null
+++ b/media/libeffects/downmix/aidl/EffectDownmix.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2022 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_TAG "AHAL_DownmixImpl"
+
+#include <android-base/logging.h>
+
+#include "EffectDownmix.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DownmixImpl;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kDownmixImplUUID;
+using aidl::android::hardware::audio::effect::kDownmixTypeUUID;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kDownmixImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<DownmixImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != kDownmixImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = DownmixImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string DownmixImpl::kEffectName = "Multichannel Downmix To Stereo";
+const Descriptor DownmixImpl::kDescriptor = {
+ .common = {
+ .id = {.type = kDownmixTypeUUID, .uuid = kDownmixImplUUID, .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+ .name = DownmixImpl::kEffectName,
+ .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus DownmixImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::setParameterCommon(const Parameter& param) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto tag = param.getTag();
+ switch (tag) {
+ case Parameter::common:
+ RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setCommFailed");
+ break;
+ case Parameter::deviceDescription:
+ RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+ break;
+ case Parameter::mode:
+ RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setModeFailed");
+ break;
+ case Parameter::source:
+ RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setSourceFailed");
+ break;
+ case Parameter::volumeStereo:
+ RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
+ break;
+ default: {
+ LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commonParamNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->reset();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::downmix != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& dmParam = specific.get<Parameter::Specific::downmix>();
+ auto tag = dmParam.getTag();
+
+ switch (tag) {
+ case Downmix::type: {
+ RETURN_IF(mContext->setDmType(dmParam.get<Downmix::type>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setTypeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus DownmixImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::downmixTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto dmId = id.get<Parameter::Id::downmixTag>();
+ auto dmIdTag = dmId.getTag();
+ switch (dmIdTag) {
+ case Downmix::Id::commonTag:
+ return getParameterDownmix(dmId.get<Downmix::Id::commonTag>(), specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(dmIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus DownmixImpl::getParameterDownmix(const Downmix::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ Downmix dmParam;
+ switch (tag) {
+ case Downmix::type: {
+ dmParam.set<Downmix::type>(mContext->getDmType());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "DownmixTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::downmix>(dmParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> DownmixImpl::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<DownmixContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode DownmixImpl::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DownmixImpl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+ if (!mContext) {
+ LOG(ERROR) << __func__ << " nullContext";
+ return {EX_NULL_POINTER, 0, 0};
+ }
+ return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.h b/media/libeffects/downmix/aidl/EffectDownmix.h
new file mode 100644
index 0000000..d590133
--- /dev/null
+++ b/media/libeffects/downmix/aidl/EffectDownmix.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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/BnEffect.h>
+#include <audio_effects/effect_downmix.h>
+
+#include "DownmixContext.h"
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class DownmixImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Descriptor kDescriptor;
+ DownmixImpl() { LOG(DEBUG) << __func__; }
+ ~DownmixImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ std::shared_ptr<DownmixContext> mContext;
+ ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/Android.bp b/media/libeffects/hapticgenerator/Android.bp
index ba511fe..07ba492 100644
--- a/media/libeffects/hapticgenerator/Android.bp
+++ b/media/libeffects/hapticgenerator/Android.bp
@@ -22,6 +22,23 @@
default_applicable_licenses: ["frameworks_av_license"],
}
+cc_defaults {
+ name : "hapticgeneratordefaults",
+ srcs: [
+ "Processors.cpp",
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "libbase",
+ "liblog",
+ "libutils",
+ "libvibratorutils",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ ],
+}
+
cc_library_shared {
name: "libhapticgenerator",
@@ -29,7 +46,10 @@
srcs: [
"EffectHapticGenerator.cpp",
- "Processors.cpp",
+ ],
+
+ defaults: [
+ "hapticgeneratordefaults",
],
cflags: [
@@ -43,17 +63,30 @@
"-fvisibility=hidden",
],
- shared_libs: [
- "libaudioutils",
- "libbase",
- "liblog",
- "libutils",
- "libvibratorutils",
+ relative_install_path: "soundfx",
+}
+
+cc_library_shared {
+ name: "libhapticgeneratoraidl",
+
+ srcs: [
+ "aidl/EffectHapticGenerator.cpp",
+ "aidl/HapticGeneratorContext.cpp",
+ ":effectCommonFile",
],
- relative_install_path: "soundfx",
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "hapticgeneratordefaults",
+ ],
- header_libs: [
- "libaudioeffects",
+ cflags: [
+ "-Wthread-safety",
+ ],
+
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
],
}
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
new file mode 100644
index 0000000..7e22482
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 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_TAG "AHAL_HapticGeneratorImpl"
+
+#include "EffectHapticGenerator.h"
+
+#include <android-base/logging.h>
+#include <audio_effects/effect_hapticgenerator.h>
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::HapticGeneratorImpl;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kHapticGeneratorImplUUID;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kHapticGeneratorImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<HapticGeneratorImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != kHapticGeneratorImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = HapticGeneratorImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string HapticGeneratorImpl::kEffectName = "Haptic Generator";
+const Descriptor HapticGeneratorImpl::kDescriptor = {
+ .common = {.id = {.type = kHapticGeneratorTypeUUID,
+ .uuid = kHapticGeneratorImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+ .name = HapticGeneratorImpl::kEffectName,
+ .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus HapticGeneratorImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->reset();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& hgParam = specific.get<Parameter::Specific::hapticGenerator>();
+ auto tag = hgParam.getTag();
+
+ switch (tag) {
+ case HapticGenerator::hapticScales: {
+ RETURN_IF(mContext->setHgHapticScales(hgParam.get<HapticGenerator::hapticScales>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setHapticScaleFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case HapticGenerator::vibratorInfo: {
+ RETURN_IF(mContext->setHgVibratorInformation(
+ hgParam.get<HapticGenerator::vibratorInfo>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setVibratorInfoFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto hgId = id.get<Parameter::Id::hapticGeneratorTag>();
+ auto hgIdTag = hgId.getTag();
+ switch (hgIdTag) {
+ case HapticGenerator::Id::commonTag:
+ return getParameterHapticGenerator(hgId.get<HapticGenerator::Id::commonTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(hgIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ HapticGenerator hgParam;
+ switch (tag) {
+ case HapticGenerator::hapticScales: {
+ hgParam.set<HapticGenerator::hapticScales>(mContext->getHgHapticScales());
+ break;
+ }
+ case HapticGenerator::vibratorInfo: {
+ hgParam.set<HapticGenerator::vibratorInfo>(mContext->getHgVibratorInformation());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::hapticGenerator>(hgParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> HapticGeneratorImpl::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<HapticGeneratorContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode HapticGeneratorImpl::releaseContext() {
+ if (mContext) {
+ mContext->reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status HapticGeneratorImpl::effectProcessImpl(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, samples);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
new file mode 100644
index 0000000..02ca392
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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/BnEffect.h>
+
+#include "HapticGeneratorContext.h"
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class HapticGeneratorImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Descriptor kDescriptor;
+ HapticGeneratorImpl() { LOG(DEBUG) << __func__; }
+ ~HapticGeneratorImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ std::shared_ptr<HapticGeneratorContext> mContext;
+ ndk::ScopedAStatus getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
new file mode 100644
index 0000000..64f51c3
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2022 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_TAG "AHAL_HapticGeneratorContext"
+
+#include <Utils.h>
+#include <android-base/parsedouble.h>
+#include <android-base/properties.h>
+
+#include "HapticGeneratorContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+HapticGeneratorContext::HapticGeneratorContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ mState = HAPTIC_GENERATOR_STATE_UNINITIALIZED;
+ mSampleRate = common.input.base.sampleRate;
+ mFrameCount = common.input.frameCount;
+ init_params(common.input.base.channelMask, common.output.base.channelMask);
+}
+
+HapticGeneratorContext::~HapticGeneratorContext() {
+ LOG(DEBUG) << __func__;
+ mState = HAPTIC_GENERATOR_STATE_UNINITIALIZED;
+}
+
+RetCode HapticGeneratorContext::enable() {
+ if (mState != HAPTIC_GENERATOR_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = HAPTIC_GENERATOR_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode HapticGeneratorContext::disable() {
+ if (mState != HAPTIC_GENERATOR_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = HAPTIC_GENERATOR_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void HapticGeneratorContext::reset() {
+ for (auto& filter : mProcessorsRecord.filters) {
+ filter->clear();
+ }
+ for (auto& slowEnv : mProcessorsRecord.slowEnvs) {
+ slowEnv->clear();
+ }
+ for (auto& distortion : mProcessorsRecord.distortions) {
+ distortion->clear();
+ }
+}
+
+RetCode HapticGeneratorContext::setHgHapticScales(
+ const std::vector<HapticGenerator::HapticScale> hapticScales) {
+ std::lock_guard lg(mMutex);
+ for (auto hapticScale : hapticScales) {
+ mParams.mHapticScales.insert_or_assign(hapticScale.id, hapticScale.scale);
+ }
+ mParams.mMaxVibratorScale = HapticGenerator::VibratorScale::MUTE;
+ for (const auto& [id, vibratorScale] : mParams.mHapticScales) {
+ mParams.mMaxVibratorScale = std::max(mParams.mMaxVibratorScale, vibratorScale);
+ }
+ return RetCode::SUCCESS;
+}
+
+HapticGenerator::VibratorInformation HapticGeneratorContext::getHgVibratorInformation() {
+ std::lock_guard lg(mMutex);
+ return mParams.mVibratorInfo;
+}
+
+std::vector<HapticGenerator::HapticScale> HapticGeneratorContext::getHgHapticScales() {
+ std::vector<HapticGenerator::HapticScale> result;
+ std::lock_guard lg(mMutex);
+ for (const auto& [id, vibratorScale] : mParams.mHapticScales) {
+ result.push_back({id, vibratorScale});
+ }
+ return result;
+}
+
+RetCode HapticGeneratorContext::setHgVibratorInformation(
+ const HapticGenerator::VibratorInformation& vibratorInfo) {
+ {
+ std::lock_guard lg(mMutex);
+ mParams.mVibratorInfo = vibratorInfo;
+
+ if (mProcessorsRecord.bpf != nullptr) {
+ mProcessorsRecord.bpf->setCoefficients(
+ ::android::audio_effect::haptic_generator::bpfCoefs(
+ mParams.mVibratorInfo.resonantFrequencyHz, DEFAULT_BPF_Q, mSampleRate));
+ }
+ if (mProcessorsRecord.bsf != nullptr) {
+ mProcessorsRecord.bsf->setCoefficients(
+ ::android::audio_effect::haptic_generator::bsfCoefs(
+ mParams.mVibratorInfo.resonantFrequencyHz,
+ mParams.mVibratorInfo.qFactor, mParams.mVibratorInfo.qFactor / 2.0f,
+ mSampleRate));
+ }
+ }
+ configure();
+ return RetCode::SUCCESS;
+}
+
+IEffect::Status HapticGeneratorContext::lvmProcess(float* in, float* out, int samples) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
+ auto frameSize = getInputFrameSize();
+ RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+ LOG(DEBUG) << __func__ << " start processing";
+ // The audio data must not be modified but just written to
+ // output buffer according the access mode.
+ bool accumulate = false;
+ if (in != out) {
+ for (int i = 0; i < samples; i++) {
+ if (accumulate) {
+ out[i] += in[i];
+ } else {
+ out[i] = in[i];
+ }
+ }
+ }
+
+ if (mState != HAPTIC_GENERATOR_STATE_ACTIVE) {
+ return status;
+ }
+
+ std::lock_guard lg(mMutex);
+ if (mParams.mMaxVibratorScale == HapticGenerator::VibratorScale::MUTE) {
+ // Haptic channels are muted, not need to generate haptic data.
+ return {STATUS_OK, samples, samples};
+ }
+
+ // Resize buffer if the haptic sample count is greater than buffer size.
+ size_t hapticSampleCount = mFrameCount * mParams.mHapticChannelCount;
+ if (hapticSampleCount > mInputBuffer.size()) {
+ // The inputBuffer and outputBuffer must have the same size, which must be at least
+ // the haptic sample count.
+ mInputBuffer.resize(hapticSampleCount);
+ mOutputBuffer.resize(hapticSampleCount);
+ }
+
+ // Construct input buffer according to haptic channel source
+ for (size_t i = 0; i < mFrameCount; ++i) {
+ for (size_t j = 0; j < mParams.mHapticChannelCount; ++j) {
+ mInputBuffer[i * mParams.mHapticChannelCount + j] =
+ in[i * mParams.mAudioChannelCount + mParams.mHapticChannelSource[j]];
+ }
+ }
+
+ float* hapticOutBuffer =
+ runProcessingChain(mInputBuffer.data(), mOutputBuffer.data(), mFrameCount);
+ ::android::os::scaleHapticData(
+ hapticOutBuffer, hapticSampleCount,
+ static_cast<::android::os::HapticScale>(mParams.mMaxVibratorScale),
+ mParams.mVibratorInfo.qFactor);
+
+ // For haptic data, the haptic playback thread will copy the data from effect input
+ // buffer, which contains haptic data at the end of the buffer, directly to sink buffer.
+ // In that case, copy haptic data to input buffer instead of output buffer.
+ // Note: this may not work with rpc/binder calls
+ int offset = samples;
+ for (int i = 0; i < hapticSampleCount; ++i) {
+ in[samples + i] = hapticOutBuffer[i];
+ }
+ return {STATUS_OK, samples, static_cast<int32_t>(samples + hapticSampleCount)};
+}
+
+void HapticGeneratorContext::init_params(media::audio::common::AudioChannelLayout inputChMask,
+ media::audio::common::AudioChannelLayout outputChMask) {
+ std::lock_guard lg(mMutex);
+ mParams.mMaxVibratorScale = HapticGenerator::VibratorScale::MUTE;
+ mParams.mVibratorInfo.resonantFrequencyHz = DEFAULT_RESONANT_FREQUENCY;
+ mParams.mVibratorInfo.qFactor = DEFAULT_BSF_ZERO_Q;
+
+ mParams.mAudioChannelCount = ::android::hardware::audio::common::getChannelCount(
+ inputChMask, ~media::audio::common::AudioChannelLayout::LAYOUT_HAPTIC_AB);
+ mParams.mHapticChannelCount = ::android::hardware::audio::common::getChannelCount(
+ outputChMask, media::audio::common::AudioChannelLayout::LAYOUT_HAPTIC_AB);
+ LOG_ALWAYS_FATAL_IF(mParams.mHapticChannelCount > 2, "haptic channel count is too large");
+ for (size_t i = 0; i < mParams.mHapticChannelCount; ++i) {
+ // By default, use the first audio channel to generate haptic channels.
+ mParams.mHapticChannelSource[i] = 0;
+ }
+
+ mState = HAPTIC_GENERATOR_STATE_INITIALIZED;
+}
+
+float HapticGeneratorContext::getDistortionOutputGain() {
+ float distortionOutputGain = getFloatProperty(
+ "vendor.audio.hapticgenerator.distortion.output.gain", DEFAULT_DISTORTION_OUTPUT_GAIN);
+ LOG(DEBUG) << "Using distortion output gain as " << distortionOutputGain;
+ return distortionOutputGain;
+}
+
+float HapticGeneratorContext::getFloatProperty(const std::string& key, float defaultValue) {
+ float result;
+ std::string value = ::android::base::GetProperty(key, "");
+ if (!value.empty() && ::android::base::ParseFloat(value, &result)) {
+ return result;
+ }
+ return defaultValue;
+}
+
+void HapticGeneratorContext::addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter) {
+ // The process chain captures the shared pointer of the filter in lambda.
+ // The process record will keep a shared pointer to the filter so that it is possible to
+ // access the filter outside of the process chain.
+ mProcessorsRecord.filters.push_back(filter);
+ mProcessingChain.push_back([filter](float* out, const float* in, size_t frameCount) {
+ filter->process(out, in, frameCount);
+ });
+}
+
+/**
+ * Build haptic generator processing chain.
+ */
+void HapticGeneratorContext::buildProcessingChain() {
+ std::lock_guard lg(mMutex);
+ const size_t channelCount = mParams.mHapticChannelCount;
+ float highPassCornerFrequency = 50.0f;
+ auto hpf = ::android::audio_effect::haptic_generator::createHPF2(highPassCornerFrequency,
+ mSampleRate, channelCount);
+ addBiquadFilter(hpf);
+ float lowPassCornerFrequency = 9000.0f;
+ auto lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency,
+ mSampleRate, channelCount);
+ addBiquadFilter(lpf);
+
+ auto ramp = std::make_shared<::android::audio_effect::haptic_generator::Ramp>(
+ channelCount); // ramp = half-wave rectifier.
+ // The process chain captures the shared pointer of the ramp in lambda. It will be the only
+ // reference to the ramp.
+ // The process record will keep a weak pointer to the ramp so that it is possible to access
+ // the ramp outside of the process chain.
+ mProcessorsRecord.ramps.push_back(ramp);
+ mProcessingChain.push_back([ramp](float* out, const float* in, size_t frameCount) {
+ ramp->process(out, in, frameCount);
+ });
+
+ highPassCornerFrequency = 60.0f;
+ hpf = ::android::audio_effect::haptic_generator::createHPF2(highPassCornerFrequency,
+ mSampleRate, channelCount);
+ addBiquadFilter(hpf);
+ lowPassCornerFrequency = 700.0f;
+ lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+ channelCount);
+ addBiquadFilter(lpf);
+
+ lowPassCornerFrequency = 400.0f;
+ lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+ channelCount);
+ addBiquadFilter(lpf);
+ lowPassCornerFrequency = 500.0f;
+ lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+ channelCount);
+ addBiquadFilter(lpf);
+
+ auto bpf = ::android::audio_effect::haptic_generator::createBPF(
+ mParams.mVibratorInfo.resonantFrequencyHz, DEFAULT_BPF_Q, mSampleRate, channelCount);
+ mProcessorsRecord.bpf = bpf;
+ addBiquadFilter(bpf);
+
+ float normalizationPower = DEFAULT_SLOW_ENV_NORMALIZATION_POWER;
+ // The process chain captures the shared pointer of the slow envelope in lambda. It will
+ // be the only reference to the slow envelope.
+ // The process record will keep a weak pointer to the slow envelope so that it is possible
+ // to access the slow envelope outside of the process chain.
+ // SlowEnvelope = partial normalizer, or AGC.
+ auto slowEnv = std::make_shared<::android::audio_effect::haptic_generator::SlowEnvelope>(
+ 5.0f /*envCornerFrequency*/, mSampleRate, normalizationPower, 0.01f /*envOffset*/,
+ channelCount);
+ mProcessorsRecord.slowEnvs.push_back(slowEnv);
+ mProcessingChain.push_back([slowEnv](float* out, const float* in, size_t frameCount) {
+ slowEnv->process(out, in, frameCount);
+ });
+
+ auto bsf = ::android::audio_effect::haptic_generator::createBSF(
+ mParams.mVibratorInfo.resonantFrequencyHz, mParams.mVibratorInfo.qFactor,
+ mParams.mVibratorInfo.qFactor / 2.0f, mSampleRate, channelCount);
+ mProcessorsRecord.bsf = bsf;
+ addBiquadFilter(bsf);
+
+ // The process chain captures the shared pointer of the Distortion in lambda. It will
+ // be the only reference to the Distortion.
+ // The process record will keep a weak pointer to the Distortion so that it is possible
+ // to access the Distortion outside of the process chain.
+ auto distortion = std::make_shared<::android::audio_effect::haptic_generator::Distortion>(
+ DEFAULT_DISTORTION_CORNER_FREQUENCY, mSampleRate, DEFAULT_DISTORTION_INPUT_GAIN,
+ DEFAULT_DISTORTION_CUBE_THRESHOLD, getDistortionOutputGain(), channelCount);
+ mProcessorsRecord.distortions.push_back(distortion);
+ mProcessingChain.push_back([distortion](float* out, const float* in, size_t frameCount) {
+ distortion->process(out, in, frameCount);
+ });
+}
+
+void HapticGeneratorContext::configure() {
+ mProcessingChain.clear();
+ mProcessorsRecord.filters.clear();
+ mProcessorsRecord.ramps.clear();
+ mProcessorsRecord.slowEnvs.clear();
+ mProcessorsRecord.distortions.clear();
+
+ buildProcessingChain();
+}
+
+/**
+ * Run the processing chain to generate haptic data from audio data
+ *
+ * @param buf1 a buffer contains raw audio data
+ * @param buf2 a buffer that is large enough to keep all the data
+ * @param frameCount frame count of the data
+ *
+ * @return a pointer to the output buffer
+ */
+float* HapticGeneratorContext::runProcessingChain(float* buf1, float* buf2, size_t frameCount) {
+ float* in = buf1;
+ float* out = buf2;
+ for (const auto processingFunc : mProcessingChain) {
+ processingFunc(out, in, frameCount);
+ std::swap(in, out);
+ }
+ return in;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
new file mode 100644
index 0000000..dc43feb
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <vibrator/ExternalVibrationUtils.h>
+#include <map>
+
+#include "Processors.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum HapticGeneratorState {
+ HAPTIC_GENERATOR_STATE_UNINITIALIZED,
+ HAPTIC_GENERATOR_STATE_INITIALIZED,
+ HAPTIC_GENERATOR_STATE_ACTIVE,
+};
+
+struct HapticGeneratorParam {
+ // The audio channels used to generate haptic channels. The first channel will be used to
+ // generate HAPTIC_A, The second channel will be used to generate HAPTIC_B.
+ // The value will be offset of audio channel
+ int mHapticChannelSource[2];
+
+ int mHapticChannelCount;
+ int mAudioChannelCount;
+
+ HapticGenerator::HapticScale mHapticScale;
+ std::map<int, HapticGenerator::VibratorScale> mHapticScales;
+ // max intensity will be used to scale haptic data.
+ HapticGenerator::VibratorScale mMaxVibratorScale;
+
+ HapticGenerator::VibratorInformation mVibratorInfo;
+};
+
+// A structure to keep all shared pointers for all processors in HapticGenerator.
+struct HapticGeneratorProcessorsRecord {
+ std::vector<std::shared_ptr<HapticBiquadFilter>> filters;
+ std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Ramp>> ramps;
+ std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::SlowEnvelope>> slowEnvs;
+ std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Distortion>> distortions;
+
+ // Cache band-pass filter and band-stop filter for updating parameters
+ // according to vibrator info
+ std::shared_ptr<HapticBiquadFilter> bpf;
+ std::shared_ptr<HapticBiquadFilter> bsf;
+};
+
+class HapticGeneratorContext final : public EffectContext {
+ public:
+ HapticGeneratorContext(int statusDepth, const Parameter::Common& common);
+ ~HapticGeneratorContext();
+ RetCode enable();
+ RetCode disable();
+ void reset();
+
+ RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale> hapticScales);
+ std::vector<HapticGenerator::HapticScale> getHgHapticScales();
+
+ RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo);
+ HapticGenerator::VibratorInformation getHgVibratorInformation();
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
+ static constexpr float DEFAULT_BSF_ZERO_Q = 8.0f;
+ static constexpr float DEFAULT_BSF_POLE_Q = 4.0f;
+ static constexpr float DEFAULT_DISTORTION_OUTPUT_GAIN = 1.5f;
+ static constexpr float DEFAULT_BPF_Q = 1.0f;
+ static constexpr float DEFAULT_SLOW_ENV_NORMALIZATION_POWER = -0.8f;
+ static constexpr float DEFAULT_DISTORTION_CORNER_FREQUENCY = 300.0f;
+ static constexpr float DEFAULT_DISTORTION_INPUT_GAIN = 0.3f;
+ static constexpr float DEFAULT_DISTORTION_CUBE_THRESHOLD = 0.1f;
+
+ std::mutex mMutex;
+ HapticGeneratorState mState;
+ HapticGeneratorParam mParams GUARDED_BY(mMutex);
+ int mSampleRate;
+ int mFrameCount = 0;
+
+ // A cache for all shared pointers of the HapticGenerator
+ struct HapticGeneratorProcessorsRecord mProcessorsRecord;
+
+ // Using a vector of functions to record the processing chain for haptic-generating algorithm.
+ // The three parameters of the processing functions are pointer to output buffer, pointer to
+ // input buffer and frame count.
+ std::vector<std::function<void(float*, const float*, size_t)>> mProcessingChain;
+
+ // inputBuffer is where to keep input buffer for the generating algorithm. It will be
+ // constructed according to hapticChannelSource.
+ std::vector<float> mInputBuffer;
+
+ // outputBuffer is a buffer having the same length as inputBuffer. It can be used as
+ // intermediate buffer in the generating algorithm.
+ std::vector<float> mOutputBuffer;
+
+ void init_params(media::audio::common::AudioChannelLayout inputChMask,
+ media::audio::common::AudioChannelLayout outputChMask);
+ void configure();
+
+ float getDistortionOutputGain();
+ float getFloatProperty(const std::string& key, float defaultValue);
+ void addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter);
+ void buildProcessingChain();
+ float* runProcessingChain(float* buf1, float* buf2, size_t frameCount);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/Android.bp b/media/libeffects/loudness/Android.bp
index bcd6947..fc0217b 100644
--- a/media/libeffects/loudness/Android.bp
+++ b/media/libeffects/loudness/Android.bp
@@ -44,3 +44,32 @@
header_libs: ["libaudioeffects"],
}
+
+cc_library_shared {
+ name: "libloudnessenhanceraidl",
+ srcs: [
+ "aidl/EffectLoudnessEnhancer.cpp",
+ "aidl/LoudnessEnhancerContext.cpp",
+ "dsp/core/dynamic_range_compression.cpp",
+ ":effectCommonFile",
+ ],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ ],
+ shared_libs: [
+ "libcutils",
+ "liblog",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
new file mode 100644
index 0000000..9d8bc80
--- /dev/null
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2022 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_TAG "AHAL_LoudnessEnhancerImpl"
+
+#include <android-base/logging.h>
+
+#include "EffectLoudnessEnhancer.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kLoudnessEnhancerImplUUID;
+using aidl::android::hardware::audio::effect::LoudnessEnhancerImpl;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kLoudnessEnhancerImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<LoudnessEnhancerImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != kLoudnessEnhancerImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = LoudnessEnhancerImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string LoudnessEnhancerImpl::kEffectName = "Loudness Enhancer";
+const Descriptor LoudnessEnhancerImpl::kDescriptor = {
+ .common = {.id = {.type = kLoudnessEnhancerTypeUUID,
+ .uuid = kLoudnessEnhancerImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+ .name = LoudnessEnhancerImpl::kEffectName,
+ .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& leParam = specific.get<Parameter::Specific::loudnessEnhancer>();
+ auto tag = leParam.getTag();
+
+ switch (tag) {
+ case LoudnessEnhancer::gainMb: {
+ RETURN_IF(mContext->setLeGain(leParam.get<LoudnessEnhancer::gainMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setGainMbFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::loudnessEnhancerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto leId = id.get<Parameter::Id::loudnessEnhancerTag>();
+ auto leIdTag = leId.getTag();
+ switch (leIdTag) {
+ case LoudnessEnhancer::Id::commonTag:
+ return getParameterLoudnessEnhancer(leId.get<LoudnessEnhancer::Id::commonTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(leIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getParameterLoudnessEnhancer(
+ const LoudnessEnhancer::Tag& tag, Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ LoudnessEnhancer leParam;
+ switch (tag) {
+ case LoudnessEnhancer::gainMb: {
+ leParam.set<LoudnessEnhancer::gainMb>(mContext->getLeGain());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::loudnessEnhancer>(leParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> LoudnessEnhancerImpl::createContext(
+ const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<LoudnessEnhancerContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode LoudnessEnhancerImpl::releaseContext() {
+ if (mContext) {
+ mContext->disable();
+ mContext->resetBuffer();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status LoudnessEnhancerImpl::effectProcessImpl(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, samples);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
new file mode 100644
index 0000000..6402fd2
--- /dev/null
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+#include "LoudnessEnhancerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class LoudnessEnhancerImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Descriptor kDescriptor;
+ LoudnessEnhancerImpl() { LOG(DEBUG) << __func__; }
+ ~LoudnessEnhancerImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ std::shared_ptr<LoudnessEnhancerContext> mContext;
+ ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
new file mode 100644
index 0000000..033b222
--- /dev/null
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2022 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 "LoudnessEnhancerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+LoudnessEnhancerContext::LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ mState = LOUDNESS_ENHANCER_STATE_UNINITIALIZED;
+ mSampleRate = common.input.base.sampleRate;
+ init_params();
+}
+
+LoudnessEnhancerContext::~LoudnessEnhancerContext() {
+ LOG(DEBUG) << __func__;
+ mState = LOUDNESS_ENHANCER_STATE_UNINITIALIZED;
+}
+
+RetCode LoudnessEnhancerContext::enable() {
+ if (mState != LOUDNESS_ENHANCER_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = LOUDNESS_ENHANCER_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode LoudnessEnhancerContext::disable() {
+ if (mState != LOUDNESS_ENHANCER_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void LoudnessEnhancerContext::reset() {
+ float targetAmp = pow(10, mGain / 2000.0f); // mB to linear amplification
+ {
+ std::lock_guard lg(mMutex);
+ if (mCompressor != nullptr) {
+ // Get samplingRate from input
+ mCompressor->Initialize(targetAmp, mSampleRate);
+ }
+ }
+}
+
+RetCode LoudnessEnhancerContext::setLeGain(int gainMb) {
+ mGain = gainMb;
+ reset(); // apply parameter update
+ return RetCode::SUCCESS;
+}
+
+IEffect::Status LoudnessEnhancerContext::lvmProcess(float* in, float* out, int samples) {
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
+ auto frameSize = getInputFrameSize();
+ RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+ LOG(DEBUG) << __func__ << " start processing";
+ {
+ std::lock_guard lg(mMutex);
+ // PcmType is always expected to be Float 32 bit.
+ constexpr float scale = 1 << 15; // power of 2 is lossless conversion to int16_t range
+ constexpr float inverseScale = 1.f / scale;
+ const float inputAmp = pow(10, mGain / 2000.0f) * scale;
+ float leftSample, rightSample;
+ if (mCompressor != nullptr) {
+ for (int inIdx = 0; inIdx < samples; inIdx += 2) {
+ // makeup gain is applied on the input of the compressor
+ leftSample = inputAmp * in[inIdx];
+ rightSample = inputAmp * in[inIdx + 1];
+ mCompressor->Compress(&leftSample, &rightSample);
+ in[inIdx] = leftSample * inverseScale;
+ in[inIdx + 1] = rightSample * inverseScale;
+ }
+ } else {
+ for (int inIdx = 0; inIdx < samples; inIdx += 2) {
+ leftSample = inputAmp * in[inIdx];
+ rightSample = inputAmp * in[inIdx + 1];
+ in[inIdx] = leftSample * inverseScale;
+ in[inIdx + 1] = rightSample * inverseScale;
+ }
+ }
+ bool accumulate = false;
+ if (in != out) {
+ for (int i = 0; i < samples; i++) {
+ if (accumulate) {
+ out[i] += in[i];
+ } else {
+ out[i] = in[i];
+ }
+ }
+ }
+ }
+ return {STATUS_OK, samples, samples};
+}
+
+void LoudnessEnhancerContext::init_params() {
+ mGain = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
+ float targetAmp = pow(10, mGain / 2000.0f); // mB to linear amplification
+ LOG(DEBUG) << __func__ << "Target gain = " << mGain << "mB <=> factor = " << targetAmp;
+
+ {
+ std::lock_guard lg(mMutex);
+ mCompressor = std::make_unique<le_fx::AdaptiveDynamicRangeCompression>();
+ mCompressor->Initialize(targetAmp, mSampleRate);
+ }
+ mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
new file mode 100644
index 0000000..b478b27
--- /dev/null
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <audio_effects/effect_loudnessenhancer.h>
+
+#include "dsp/core/dynamic_range_compression.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum LoudnessEnhancerState {
+ LOUDNESS_ENHANCER_STATE_UNINITIALIZED,
+ LOUDNESS_ENHANCER_STATE_INITIALIZED,
+ LOUDNESS_ENHANCER_STATE_ACTIVE,
+};
+
+class LoudnessEnhancerContext final : public EffectContext {
+ public:
+ LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common);
+ ~LoudnessEnhancerContext();
+
+ RetCode enable();
+ RetCode disable();
+ void reset();
+
+ RetCode setLeGain(int gainMb);
+ int getLeGain() const { return mGain; }
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ std::mutex mMutex;
+ LoudnessEnhancerState mState;
+ int mSampleRate;
+ int mGain;
+ // In this implementation, there is no coupling between the compression on the left and right
+ // channels
+ std::unique_ptr<le_fx::AdaptiveDynamicRangeCompression> mCompressor GUARDED_BY(mMutex);
+
+ void init_params();
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index fa26e60..3aee721 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -20,9 +20,13 @@
#include "BundleContext.h"
#include "BundleTypes.h"
+#include "math.h"
namespace aidl::android::hardware::audio::effect {
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+
RetCode BundleContext::init() {
std::lock_guard lg(mMutex);
// init with pre-defined preset NORMAL
@@ -67,38 +71,280 @@
}
RetCode BundleContext::enable() {
+ if (mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+ // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due to
+ // their nature.
+ bool tempDisabled = false;
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle EQ";
+ if (mSamplesToExitCountEq <= 0) mNumberEffectsEnabled++;
+ mSamplesToExitCountEq = (mSamplesPerSecond * 0.1);
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ LOG(DEBUG) << __func__ << " enable bundle BB";
+ if (mSamplesToExitCountBb <= 0) mNumberEffectsEnabled++;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+ mSamplesToExitCountBb = (mSamplesPerSecond * 0.1);
+ tempDisabled = mBassTempDisabled;
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle VR";
+ if (mSamplesToExitCountVirt <= 0) mNumberEffectsEnabled++;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ mSamplesToExitCountVirt = (mSamplesPerSecond * 0.1);
+ tempDisabled = mVirtualizerTempDisabled;
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ LOG(DEBUG) << __func__ << " enable bundle VOL";
+ if ((mEffectInDrain & (1 << int(lvm::BundleEffectType::VOLUME))) == 0)
+ mNumberEffectsEnabled++;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+ break;
+ }
+ mEnabled = true;
+ return (tempDisabled ? RetCode::SUCCESS : enableOperatingMode());
+}
+
+RetCode BundleContext::enableOperatingMode() {
LVM_ControlParams_t params;
{
std::lock_guard lg(mMutex);
RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
- if (mType == lvm::BundleEffectType::EQUALIZER) {
- LOG(DEBUG) << __func__ << " enable bundle EQ";
- params.EQNB_OperatingMode = LVM_EQNB_ON;
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle EQ";
+ params.EQNB_OperatingMode = LVM_EQNB_ON;
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ LOG(DEBUG) << __func__ << " enable bundle BB";
+ params.BE_OperatingMode = LVM_BE_ON;
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle VR";
+ params.VirtualizerOperatingMode = LVM_MODE_ON;
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ LOG(DEBUG) << __func__ << " enable bundle VOL";
+ break;
}
RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
}
- mEnabled = true;
- // LvmEffect_limitLevel(pContext);
- return RetCode::SUCCESS;
+ return limitLevel();
}
RetCode BundleContext::disable() {
+ if (!mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle EQ";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::EQUALIZER);
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ LOG(DEBUG) << __func__ << " disable bundle BB";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::BASS_BOOST);
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle VR";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::VIRTUALIZER);
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ LOG(DEBUG) << __func__ << " disable bundle VOL";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::VOLUME);
+ break;
+ }
+ mEnabled = false;
+ return disableOperatingMode();
+}
+
+RetCode BundleContext::disableOperatingMode() {
LVM_ControlParams_t params;
{
std::lock_guard lg(mMutex);
RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
- if (mType == lvm::BundleEffectType::EQUALIZER) {
- LOG(DEBUG) << __func__ << " disable bundle EQ";
- params.EQNB_OperatingMode = LVM_EQNB_OFF;
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle EQ";
+ params.EQNB_OperatingMode = LVM_EQNB_OFF;
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ LOG(DEBUG) << __func__ << " disable bundle BB";
+ params.BE_OperatingMode = LVM_BE_OFF;
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle VR";
+ params.VirtualizerOperatingMode = LVM_MODE_OFF;
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ LOG(DEBUG) << __func__ << " disable bundle VOL";
+ break;
}
RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
}
mEnabled = false;
- // LvmEffect_limitLevel(pContext);
+ return limitLevel();
+}
+
+RetCode BundleContext::limitLevel() {
+ int gainCorrection = 0;
+ // Count the energy contribution per band for EQ and BassBoost only if they are active.
+ float energyContribution = 0;
+ float energyCross = 0;
+ float energyBassBoost = 0;
+ float crossCorrection = 0;
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ bool eqEnabled = params.EQNB_OperatingMode == LVM_EQNB_ON;
+ bool bbEnabled = params.BE_OperatingMode == LVM_BE_ON;
+ bool viEnabled = params.VirtualizerOperatingMode == LVM_MODE_ON;
+
+ if (eqEnabled) {
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ float bandFactor = mBandGaindB[i] / 15.0;
+ float bandCoefficient = lvm::kBandEnergyCoefficient[i];
+ float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
+ if (bandEnergy > 0) energyContribution += bandEnergy;
+ }
+
+ // cross EQ coefficients
+ float bandFactorSum = 0;
+ for (int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
+ float bandFactor1 = mBandGaindB[i] / 15.0;
+ float bandFactor2 = mBandGaindB[i + 1] / 15.0;
+
+ if (bandFactor1 > 0 && bandFactor2 > 0) {
+ float crossEnergy =
+ bandFactor1 * bandFactor2 * lvm::kBandEnergyCrossCoefficient[i];
+ bandFactorSum += bandFactor1 * bandFactor2;
+
+ if (crossEnergy > 0) energyCross += crossEnergy;
+ }
+ }
+ bandFactorSum -= 1.0;
+ if (bandFactorSum > 0) crossCorrection = bandFactorSum * 0.7;
+ }
+ // BassBoost contribution
+ if (bbEnabled) {
+ float boostFactor = mBassStrengthSaved / 1000.0;
+ float boostCoefficient = lvm::kBassBoostEnergyCoefficient;
+
+ energyContribution += boostFactor * boostCoefficient * boostCoefficient;
+
+ if (eqEnabled) {
+ for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ float bandFactor = mBandGaindB[i] / 15.0;
+ float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
+ float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
+ if (bandEnergy > 0) energyBassBoost += bandEnergy;
+ }
+ }
+ }
+ // Virtualizer contribution
+ if (viEnabled) {
+ energyContribution += lvm::kVirtualizerContribution * lvm::kVirtualizerContribution;
+ }
+
+ double totalEnergyEstimation =
+ sqrt(energyContribution + energyCross + energyBassBoost) - crossCorrection;
+ LOG(INFO) << " TOTAL energy estimation: " << totalEnergyEstimation << " dB";
+
+ // roundoff
+ int maxLevelRound = (int)(totalEnergyEstimation + 0.99);
+ if (maxLevelRound + mVolume > 0) {
+ gainCorrection = maxLevelRound + mVolume;
+ }
+
+ params.VC_EffectLevel = mVolume - gainCorrection;
+ if (params.VC_EffectLevel < -96) {
+ params.VC_EffectLevel = -96;
+ }
+ LOG(INFO) << "\tVol: " << mVolume << ", GainCorrection: " << gainCorrection
+ << ", Actual vol: " << params.VC_EffectLevel;
+
+ /* Activate the initial settings */
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+
+ if (mFirstVolume) {
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetVolumeNoSmoothing(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setVolumeNoSmoothingFailed");
+ LOG(INFO) << "\tLVM_VOLUME: Disabling Smoothing for first volume change to remove "
+ "spikes/clicks";
+ mFirstVolume = false;
+ }
+ }
+
+ return RetCode::SUCCESS;
+}
+
+bool BundleContext::isDeviceSupportedBassBoost(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+ return (device == AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER, ""} ||
+ device == AudioDeviceDescription{AudioDeviceType::OUT_CARKIT,
+ AudioDeviceDescription::CONNECTION_BT_SCO} ||
+ device == AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER,
+ AudioDeviceDescription::CONNECTION_BT_A2DP});
+}
+
+bool BundleContext::isDeviceSupportedVirtualizer(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+ return (device == AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_ANALOG} ||
+ device == AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+ AudioDeviceDescription::CONNECTION_ANALOG} ||
+ device == AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+ AudioDeviceDescription::CONNECTION_BT_A2DP} ||
+ device == AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_USB});
+}
+
+RetCode BundleContext::setOutputDevice(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+ mOutputDevice = device;
+ switch (mType) {
+ case lvm::BundleEffectType::BASS_BOOST:
+ if (isDeviceSupportedBassBoost(device)) {
+ // If a device doesn't support bass boost, the effect must be temporarily disabled.
+ // The effect must still report its original state as this can only be changed by
+ // the start/stop commands.
+ if (mEnabled) {
+ disableOperatingMode();
+ }
+ mBassTempDisabled = true;
+ } else {
+ // If a device supports bass boost and the effect has been temporarily disabled
+ // previously then re-enable it
+ if (!mEnabled) {
+ enableOperatingMode();
+ }
+ mBassTempDisabled = false;
+ }
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ if (isDeviceSupportedVirtualizer(device)) {
+ if (mEnabled) {
+ disableOperatingMode();
+ }
+ mVirtualizerTempDisabled = true;
+ } else {
+ if (!mEnabled) {
+ enableOperatingMode();
+ }
+ mVirtualizerTempDisabled = false;
+ }
+ break;
+ default:
+ break;
+ }
return RetCode::SUCCESS;
}
@@ -153,8 +399,7 @@
int rightdB = VolToDb(volume.right);
int maxdB = std::max(leftdB, rightdB);
int pandB = rightdB - leftdB;
- // TODO: add volume effect implementation here:
- // android::VolumeSetVolumeLevel(pContext, (int16_t)(maxdB * 100));
+ setVolumeLevel(maxdB * 100);
LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
{
@@ -252,6 +497,82 @@
return RetCode::SUCCESS;
}
+RetCode BundleContext::setBassBoostStrength(int strength) {
+ if (strength < 0 || strength > lvm::kBassBoostCap.maxStrengthPm) {
+ LOG(ERROR) << __func__ << " invalid strength: " << strength;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+
+ // Update Control Parameter
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.BE_EffectLevel = (LVM_INT16)((15 * strength) / 1000);
+ params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+ mBassStrengthSaved = strength;
+ LOG(INFO) << __func__ << " success with strength " << strength;
+ return limitLevel();
+}
+
+RetCode BundleContext::setVolumeLevel(int level) {
+ if (level < lvm::kVolumeCap.minLevelDb || level > lvm::kVolumeCap.maxLevelDb) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+
+ if (mMuteEnabled) {
+ mLevelSaved = level / 100;
+ } else {
+ mVolume = level / 100;
+ }
+ LOG(INFO) << __func__ << " success with level " << level;
+ return limitLevel();
+}
+
+int BundleContext::getVolumeLevel() const {
+ return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100);
+}
+
+RetCode BundleContext::setVolumeMute(bool mute) {
+ mMuteEnabled = mute;
+ if (mMuteEnabled) {
+ mLevelSaved = mVolume;
+ mVolume = -96;
+ } else {
+ mVolume = mLevelSaved;
+ }
+ return limitLevel();
+}
+
+RetCode BundleContext::setVirtualizerStrength(int strength) {
+ if (strength < 0 || strength > lvm::kVirtualizerCap.maxStrengthPm) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+
+ // Update Control Parameter
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.CS_EffectLevel = ((strength * 32767) / 1000);
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+
+ mVirtStrengthSaved = strength;
+ LOG(INFO) << __func__ << " success with strength " << strength;
+ return limitLevel();
+}
+
void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
/* General parameters */
params.OperatingMode = LVM_MODE_ON;
@@ -339,21 +660,136 @@
IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ int64_t inputFrameCount = getCommon().input.frameCount;
+ int64_t outputFrameCount = getCommon().output.frameCount;
+ RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+ int isDataAvailable = true;
auto frameSize = getInputFrameSize();
- RETURN_VALUE_IF(0== frameSize, status, "nullContext");
+ RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
LOG(DEBUG) << __func__ << " start processing";
- LVM_UINT16 frames = samples * sizeof(float) / frameSize;
- LVM_ReturnStatus_en lvmStatus;
- {
- std::lock_guard lg(mMutex);
- lvmStatus = LVM_Process(mInstance, in, out, frames, 0);
+ if ((mEffectProcessCalled & 1 << int(mType)) != 0) {
+ const int undrainedEffects = mEffectInDrain & ~mEffectProcessCalled;
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
+ LOG(DEBUG) << "Draining EQUALIZER";
+ mSamplesToExitCountEq = 0;
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+ }
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
+ LOG(DEBUG) << "Draining BASS_BOOST";
+ mSamplesToExitCountBb = 0;
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+ }
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+ LOG(DEBUG) << "Draining VIRTUALIZER";
+ mSamplesToExitCountVirt = 0;
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ }
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
+ LOG(DEBUG) << "Draining VOLUME";
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+ }
}
-
- if (lvmStatus != LVM_SUCCESS) {
- LOG(ERROR) << __func__ << lvmStatus;
- return {EX_UNSUPPORTED_OPERATION, 0, 0};
+ mEffectProcessCalled |= 1 << int(mType);
+ if (!mEnabled) {
+ switch (mType) {
+ case lvm::BundleEffectType::EQUALIZER:
+ if (mSamplesToExitCountEq > 0) {
+ mSamplesToExitCountEq -= samples;
+ }
+ if (mSamplesToExitCountEq <= 0) {
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+ }
+ LOG(DEBUG) << "Effect_process() this is the last frame for EQUALIZER";
+ }
+ break;
+ case lvm::BundleEffectType::BASS_BOOST:
+ if (mSamplesToExitCountBb > 0) {
+ mSamplesToExitCountBb -= samples;
+ }
+ if (mSamplesToExitCountBb <= 0) {
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+ }
+ LOG(DEBUG) << "Effect_process() this is the last frame for BASS_BOOST";
+ }
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ if (mSamplesToExitCountVirt > 0) {
+ mSamplesToExitCountVirt -= samples;
+ }
+ if (mSamplesToExitCountVirt <= 0) {
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ }
+ LOG(DEBUG) << "Effect_process() this is the last frame for VIRTUALIZER";
+ }
+ break;
+ case lvm::BundleEffectType::VOLUME:
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+ }
+ LOG(DEBUG) << "Effect_process() LVM_VOLUME Effect is not enabled";
+ break;
+ }
+ }
+ if (isDataAvailable) {
+ mNumberEffectsCalled++;
+ }
+ bool accumulate = false;
+ if (mNumberEffectsCalled >= mNumberEffectsEnabled) {
+ // We expect the # effects called to be equal to # effects enabled in sequence (including
+ // draining effects). Warn if this is not the case due to inconsistent calls.
+ ALOGW_IF(mNumberEffectsCalled > mNumberEffectsEnabled,
+ "%s Number of effects called %d is greater than number of effects enabled %d",
+ __func__, mNumberEffectsCalled, mNumberEffectsEnabled);
+ mEffectProcessCalled = 0; // reset our consistency check.
+ if (!isDataAvailable) {
+ LOG(DEBUG) << "Effect_process() processing last frame";
+ }
+ mNumberEffectsCalled = 0;
+ LVM_UINT16 frames = samples * sizeof(float) / frameSize;
+ float* outTmp = (accumulate ? getWorkBuffer() : out);
+ /* Process the samples */
+ LVM_ReturnStatus_en lvmStatus;
+ {
+ std::lock_guard lg(mMutex);
+ lvmStatus = LVM_Process(mInstance, in, outTmp, frames, 0);
+ if (lvmStatus != LVM_SUCCESS) {
+ LOG(ERROR) << __func__ << lvmStatus;
+ return {EX_UNSUPPORTED_OPERATION, 0, 0};
+ }
+ if (accumulate) {
+ for (int i = 0; i < samples; i++) {
+ out[i] += outTmp[i];
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < samples; i++) {
+ if (accumulate) {
+ out[i] += in[i];
+ } else {
+ out[i] = in[i];
+ }
+ }
}
LOG(DEBUG) << __func__ << " done processing";
return {STATUS_OK, samples, samples};
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index 7b38e66..be723f7 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -43,9 +43,11 @@
lvm::BundleEffectType getBundleType() const { return mType; }
RetCode enable();
+ RetCode enableOperatingMode();
RetCode disable();
+ RetCode disableOperatingMode();
- void setSampleRate (const int sampleRate) { mSampleRate = sampleRate; }
+ void setSampleRate(const int sampleRate) { mSampleRate = sampleRate; }
int getSampleRate() const { return mSampleRate; }
void setChannelMask(const aidl::android::media::audio::common::AudioChannelLayout& chMask) {
@@ -54,17 +56,37 @@
aidl::android::media::audio::common::AudioChannelLayout getChannelMask() const {
return mChMask;
}
+ bool isDeviceSupportedBassBoost(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device);
+ bool isDeviceSupportedVirtualizer(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device);
+ RetCode setOutputDevice(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device) override;
RetCode setEqualizerPreset(const std::size_t presetIdx);
int getEqualizerPreset() const { return mCurPresetIdx; }
RetCode setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels);
std::vector<Equalizer::BandLevel> getEqualizerBandLevels() const;
+ RetCode setBassBoostStrength(int strength);
+ int getBassBoostStrength() const { return mBassStrengthSaved; }
+
+ RetCode setVolumeLevel(int level);
+ int getVolumeLevel() const;
+
+ RetCode setVolumeMute(bool mute);
+ int getVolumeMute() const { return mMuteEnabled; }
+
+ RetCode setVirtualizerStrength(int strength);
+ int getVirtualizerStrength() const { return mVirtStrengthSaved; }
+
RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
IEffect::Status lvmProcess(float* in, float* out, int samples);
+ IEffect::Status processEffect(float* in, float* out, int sampleToProcess);
+
private:
std::mutex mMutex;
const lvm::BundleEffectType mType;
@@ -90,7 +112,7 @@
int mEffectProcessCalled = 0;
int mNumberEffectsEnabled = 0;
int mNumberEffectsCalled = 0;
- bool mFirstVolume = false;
+ bool mFirstVolume = true;
// Bass
bool mBassTempDisabled = false;
int mBassStrengthSaved = 0;
@@ -102,10 +124,12 @@
bool mVirtualizerTempDisabled = false;
// Volume
int mLevelSaved = 0; /* for when mute is set, level must be saved */
+ int mVolume = 0;
bool mMuteEnabled = false; /* Must store as mute = -96dB level */
void initControlParameter(LVM_ControlParams_t& params) const;
void initHeadroomParameter(LVM_HeadroomParams_t& params) const;
+ RetCode limitLevel();
int16_t VolToDb(uint32_t vol) const;
LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const;
RetCode updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels);
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index 97f08a0..1996240 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -70,6 +70,8 @@
static const Equalizer::Capability kEqCap = {.bandFrequencies = kEqBandFrequency,
.presets = kEqPresets};
+static const std::string kEqualizerEffectName = "EqualizerBundle";
+
static const Descriptor kEqualizerDesc = {
.common = {.id = {.type = kEqualizerTypeUUID,
.uuid = kEqualizerBundleImplUUID,
@@ -77,14 +79,66 @@
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
- .name = "EqualizerBundle",
+ .name = kEqualizerEffectName,
.implementor = "NXP Software Ltd."},
.capability = Capability::make<Capability::equalizer>(kEqCap)};
-// TODO: add descriptors for other bundle effect types here.
-static const Descriptor kVirtualizerDesc;
-static const Descriptor kBassBoostDesc;
-static const Descriptor kVolumeDesc;
+static const bool mStrengthSupported = true;
+
+static const BassBoost::Capability kBassBoostCap = {.maxStrengthPm = 1000,
+ .strengthSupported = mStrengthSupported};
+
+static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
+
+static const Descriptor kBassBoostDesc = {
+ .common = {.id = {.type = kBassBoostTypeUUID,
+ .uuid = kBassBoostBundleImplUUID,
+ .proxy = kBassBoostProxyUUID},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL,
+ .deviceIndication = true},
+ .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kBassBoostEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = Capability::make<Capability::bassBoost>(kBassBoostCap)};
+
+static const Virtualizer::Capability kVirtualizerCap = {.maxStrengthPm = 1000,
+ .strengthSupported = mStrengthSupported};
+
+static const std::string kVirtualizerEffectName = "Virtualizer";
+
+static const Descriptor kVirtualizerDesc = {
+ .common = {.id = {.type = kVirtualizerTypeUUID,
+ .uuid = kVirtualizerBundleImplUUID,
+ .proxy = kVirtualizerProxyUUID},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::LAST,
+ .volume = Flags::Volume::CTRL,
+ .deviceIndication = true},
+ .cpuLoad = VIRTUALIZER_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kVirtualizerEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = Capability::make<Capability::virtualizer>(kVirtualizerCap)};
+
+static const Volume::Capability kVolumeCap = {.minLevelDb = -9600, .maxLevelDb = 0};
+
+static const std::string kVolumeEffectName = "Volume";
+
+static const Descriptor kVolumeDesc = {
+ .common = {.id = {.type = kVolumeTypeUUID,
+ .uuid = kVolumeBundleImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::LAST,
+ .volume = Flags::Volume::CTRL},
+ .cpuLoad = VOLUME_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kVolumeEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = Capability::make<Capability::volume>(kVolumeCap)};
/* The following tables have been computed using the actual levels measured by the output of
* white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index b1bf04c..81b8aca 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -29,15 +29,24 @@
#include <LVM.h>
#include <limits.h>
+using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::EffectBundleAidl;
-using aidl::android::hardware::audio::effect::kEqualizerBundleImplUUID;
using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kBassBoostBundleImplUUID;
+using aidl::android::hardware::audio::effect::kEqualizerBundleImplUUID;
+using aidl::android::hardware::audio::effect::kVirtualizerBundleImplUUID;
+using aidl::android::hardware::audio::effect::kVolumeBundleImplUUID;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::AudioUuid;
+bool isUuidSupported(const AudioUuid* uuid) {
+ return (*uuid == kEqualizerBundleImplUUID || *uuid == kBassBoostBundleImplUUID ||
+ *uuid == kVirtualizerBundleImplUUID || *uuid == kVolumeBundleImplUUID);
+}
+
extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
std::shared_ptr<IEffect>* instanceSpp) {
- if (uuid == nullptr || *uuid != kEqualizerBundleImplUUID) {
+ if (uuid == nullptr || !isUuidSupported(uuid)) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
@@ -51,19 +60,20 @@
}
}
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
- if (!instanceSp) {
- LOG(ERROR) << __func__ << "nullInstance";
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || !isUuidSupported(in_impl_uuid)) {
+ LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
- State state;
- ndk::ScopedAStatus status = instanceSp->getState(&state);
- if (!status.isOk() || State::INIT != state) {
- LOG(ERROR) << __func__ << " instance " << instanceSp.get()
- << " in state: " << toString(state) << ", status: " << status.getDescription();
- return EX_ILLEGAL_STATE;
+ if (*in_impl_uuid == kEqualizerBundleImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kEqualizerDesc;
+ } else if (*in_impl_uuid == kBassBoostBundleImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm:: kBassBoostDesc;
+ } else if (*in_impl_uuid == kVirtualizerBundleImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVirtualizerDesc;
+ } else if (*in_impl_uuid == kVolumeBundleImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVolumeDesc;
}
- LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
return EX_NONE;
}
@@ -74,9 +84,21 @@
if (uuid == kEqualizerBundleImplUUID) {
mType = lvm::BundleEffectType::EQUALIZER;
mDescriptor = &lvm::kEqualizerDesc;
+ mEffectName = &lvm::kEqualizerEffectName;
+ } else if (uuid == kBassBoostBundleImplUUID) {
+ mType = lvm::BundleEffectType::BASS_BOOST;
+ mDescriptor = &lvm::kBassBoostDesc;
+ mEffectName = &lvm::kBassBoostEffectName;
+ } else if (uuid == kVirtualizerBundleImplUUID) {
+ mType = lvm::BundleEffectType::VIRTUALIZER;
+ mDescriptor = &lvm::kVirtualizerDesc;
+ mEffectName = &lvm::kVirtualizerEffectName;
+ } else if (uuid == kVolumeBundleImplUUID) {
+ mType = lvm::BundleEffectType::VOLUME;
+ mDescriptor = &lvm::kVolumeDesc;
+ mEffectName = &lvm::kVolumeEffectName;
} else {
- // TODO: add other bundle effect types here.
- LOG(ERROR) << __func__ << uuid.toString() << " not supported yet!";
+ LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
}
}
@@ -130,52 +152,128 @@
ndk::ScopedAStatus EffectBundleAidl::setParameterSpecific(const Parameter::Specific& specific) {
LOG(DEBUG) << __func__ << " specific " << specific.toString();
- auto tag = specific.getTag();
- RETURN_IF(tag != Parameter::Specific::equalizer, EX_ILLEGAL_ARGUMENT,
- "specificParamNotSupported");
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ auto tag = specific.getTag();
+ switch (tag) {
+ case Parameter::Specific::equalizer:
+ return setParameterEqualizer(specific);
+ case Parameter::Specific::bassBoost:
+ return setParameterBassBoost(specific);
+ case Parameter::Specific::virtualizer:
+ return setParameterVirtualizer(specific);
+ case Parameter::Specific::volume:
+ return setParameterVolume(specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "specificParamNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterEqualizer(const Parameter::Specific& specific) {
auto& eq = specific.get<Parameter::Specific::equalizer>();
auto eqTag = eq.getTag();
switch (eqTag) {
case Equalizer::preset:
RETURN_IF(mContext->setEqualizerPreset(eq.get<Equalizer::preset>()) != RetCode::SUCCESS,
EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
- break;
+ return ndk::ScopedAStatus::ok();
case Equalizer::bandLevels:
RETURN_IF(mContext->setEqualizerBandLevels(eq.get<Equalizer::bandLevels>()) !=
RetCode::SUCCESS,
EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
- break;
+ return ndk::ScopedAStatus::ok();
default:
LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
"eqTagNotSupported");
}
- return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterBassBoost(const Parameter::Specific& specific) {
+ auto& bb = specific.get<Parameter::Specific::bassBoost>();
+ auto bbTag = bb.getTag();
+ switch (bbTag) {
+ case BassBoost::strengthPm: {
+ RETURN_IF(mContext->setBassBoostStrength(bb.get<BassBoost::strengthPm>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default:
+ LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "bbTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterVirtualizer(const Parameter::Specific& specific) {
+ auto& vr = specific.get<Parameter::Specific::virtualizer>();
+ auto vrTag = vr.getTag();
+ switch (vrTag) {
+ case Virtualizer::strengthPm: {
+ RETURN_IF(mContext->setVirtualizerStrength(vr.get<Virtualizer::strengthPm>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default:
+ LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "vrTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterVolume(const Parameter::Specific& specific) {
+ auto& vol = specific.get<Parameter::Specific::volume>();
+ auto volTag = vol.getTag();
+ switch (volTag) {
+ case Volume::levelDb: {
+ RETURN_IF(mContext->setVolumeLevel(vol.get<Volume::levelDb>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Volume::mute:
+ RETURN_IF(mContext->setVolumeMute(vol.get<Volume::mute>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMuteFailed");
+ return ndk::ScopedAStatus::ok();
+ default:
+ LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "volTagNotSupported");
+ }
}
ndk::ScopedAStatus EffectBundleAidl::getParameterSpecific(const Parameter::Id& id,
Parameter::Specific* specific) {
RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
auto tag = id.getTag();
- RETURN_IF(Parameter::Id::equalizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
- auto eqId = id.get<Parameter::Id::equalizerTag>();
- auto eqIdTag = eqId.getTag();
- switch (eqIdTag) {
- case Equalizer::Id::commonTag:
- return getParameterEqualizer(eqId.get<Equalizer::Id::commonTag>(), specific);
+
+ switch (tag) {
+ case Parameter::Id::equalizerTag:
+ return getParameterEqualizer(id.get<Parameter::Id::equalizerTag>(), specific);
+ case Parameter::Id::bassBoostTag:
+ return getParameterBassBoost(id.get<Parameter::Id::bassBoostTag>(), specific);
+ case Parameter::Id::virtualizerTag:
+ return getParameterVirtualizer(id.get<Parameter::Id::virtualizerTag>(), specific);
+ case Parameter::Id::volumeTag:
+ return getParameterVolume(id.get<Parameter::Id::volumeTag>(), specific);
default:
- LOG(ERROR) << __func__ << " tag " << toString(eqIdTag) << " not supported";
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
- "EqualizerTagNotSupported");
+ "wrongIdTag");
}
}
-ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Tag& tag,
+ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Id& id,
Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != Equalizer::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "EqualizerTagNotSupported");
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
Equalizer eqParam;
+
+ auto tag = id.get<Equalizer::Id::commonTag>();
switch (tag) {
case Equalizer::bandLevels: {
eqParam.set<Equalizer::bandLevels>(mContext->getEqualizerBandLevels());
@@ -196,6 +294,83 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus EffectBundleAidl::getParameterBassBoost(const BassBoost::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != BassBoost::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "BassBoostTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ BassBoost bbParam;
+
+ auto tag = id.get<BassBoost::Id::commonTag>();
+ switch (tag) {
+ case BassBoost::strengthPm: {
+ bbParam.set<BassBoost::strengthPm>(mContext->getBassBoostStrength());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "BassBoostTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::bassBoost>(bbParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterVolume(const Volume::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != Volume::Id::commonTag, EX_ILLEGAL_ARGUMENT, "VolumeTagNotSupported");
+
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ Volume volParam;
+
+ auto tag = id.get<Volume::Id::commonTag>();
+ switch (tag) {
+ case Volume::levelDb: {
+ volParam.set<Volume::levelDb>(mContext->getVolumeLevel());
+ break;
+ }
+ case Volume::mute: {
+ volParam.set<Volume::mute>(mContext->getVolumeMute());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VolumeTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::volume>(volParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterVirtualizer(const Virtualizer::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != Virtualizer::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "VirtualizerTagNotSupported");
+
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ Virtualizer vrParam;
+
+ auto tag = id.get<Virtualizer::Id::commonTag>();
+ switch (tag) {
+ case Virtualizer::strengthPm: {
+ vrParam.set<Virtualizer::strengthPm>(mContext->getVirtualizerStrength());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VirtualizerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::virtualizer>(vrParam);
+ return ndk::ScopedAStatus::ok();
+}
+
std::shared_ptr<EffectContext> EffectBundleAidl::createContext(const Parameter::Common& common) {
if (mContext) {
LOG(DEBUG) << __func__ << " context already exist";
@@ -243,6 +418,8 @@
// Processing method running in EffectWorker thread.
IEffect::Status EffectBundleAidl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
return mContext->lvmProcess(in, out, sampleToProcess);
}
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
index 9e2f656..0330e5a 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -50,16 +50,28 @@
ndk::ScopedAStatus commandImpl(CommandId command) override;
- std::string getEffectName() override { return "EqualizerBundle"; }
+ std::string getEffectName() override { return *mEffectName; }
private:
std::shared_ptr<BundleContext> mContext;
const Descriptor* mDescriptor;
+ const std::string* mEffectName;
lvm::BundleEffectType mType = lvm::BundleEffectType::EQUALIZER;
IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
- ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
+
+ ndk::ScopedAStatus setParameterBassBoost(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Id& id,
Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterEqualizer(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Id& id,
+ Parameter::Specific* specific);
+ ndk::ScopedAStatus setParameterVolume(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterVolume(const Volume::Id& id, Parameter::Specific* specific);
+ ndk::ScopedAStatus setParameterVirtualizer(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Id& id,
+ Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 61a2bf5..59f1fc3 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -102,7 +102,8 @@
uint32_t state; // current state (enum preproc_session_state)
int id; // audio session ID
int io; // handle of input stream this session is on
- webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
+ rtc::scoped_refptr<webrtc::AudioProcessing>
+ apm; // handle on webRTC audio processing module (APM)
// Audio Processing module builder
webrtc::AudioProcessingBuilder ap_builder;
// frameCount represents the size of the buffers used for processing, and must represent 10ms.
@@ -260,9 +261,6 @@
ALOGV("Agc2Init");
effect->session->config = effect->session->apm->GetConfig();
effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
- effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- effect->session->config.gain_controller2.kRms;
- effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
effect->session->apm->ApplyConfig(effect->session->config);
return 0;
}
@@ -332,24 +330,19 @@
ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
break;
case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
- *(uint32_t*)pValue = (uint32_t)(
- effect->session->config.gain_controller2.adaptive_digital.level_estimator);
- ALOGV("Agc2GetParameter() level estimator %d",
- *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+ // WebRTC only supports RMS level estimator now
+ *(uint32_t*)pValue = (uint32_t)(0);
+ ALOGV("Agc2GetParameter() level estimator RMS");
break;
case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
- *(float*)pValue = (float)(effect->session->config.gain_controller2.adaptive_digital
- .extra_saturation_margin_db);
+ *(float*)pValue = (float)(2.0);
ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
break;
case AGC2_PARAM_PROPERTIES:
pProperties->fixedDigitalGain =
(float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
- pProperties->level_estimator = (uint32_t)(
- effect->session->config.gain_controller2.adaptive_digital.level_estimator);
- pProperties->extraSaturationMargin =
- (float)(effect->session->config.gain_controller2.adaptive_digital
- .extra_saturation_margin_db);
+ pProperties->level_estimator = 0;
+ pProperties->extraSaturationMargin = 2.0;
break;
default:
ALOGW("Agc2GetParameter() unknown param %d", param);
@@ -438,16 +431,19 @@
effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
break;
case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
- ALOGV("Agc2SetParameter() level estimator %d",
- *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
- effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+ ALOGV("Agc2SetParameter() level estimator %d", *(uint32_t*)pValue);
+ if (*(uint32_t*)pValue != 0) {
+ // only RMS is supported
+ status = -EINVAL;
+ }
break;
case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
valueFloat = (float)(*(int32_t*)pValue);
ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
- effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
- valueFloat;
+ if (valueFloat != 2.0) {
+ // extra_staturation_margin_db is no longer configurable in webrtc
+ status = -EINVAL;
+ }
break;
case AGC2_PARAM_PROPERTIES:
ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
@@ -455,11 +451,9 @@
pProperties->extraSaturationMargin);
effect->session->config.gain_controller2.fixed_digital.gain_db =
pProperties->fixedDigitalGain;
- effect->session->config.gain_controller2.adaptive_digital.level_estimator =
- (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)
- pProperties->level_estimator;
- effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
- pProperties->extraSaturationMargin;
+ if (pProperties->level_estimator != 0 || pProperties->extraSaturationMargin != 2.0) {
+ status = -EINVAL;
+ }
break;
default:
ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
@@ -879,8 +873,8 @@
error:
if (session->createdMsk == 0) {
- delete session->apm;
- session->apm = NULL;
+ // Scoped_refptr will handle reference counting here
+ session->apm = nullptr;
}
return status;
}
@@ -889,8 +883,8 @@
ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
session->createdMsk &= ~(1 << fx->procId);
if (session->createdMsk == 0) {
- delete session->apm;
- session->apm = NULL;
+ // Scoped_refptr will handle reference counting here
+ session->apm = nullptr;
session->id = 0;
}
diff --git a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
index 07006a1..8fdb864 100644
--- a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
@@ -143,10 +143,6 @@
const AGC2Params* agc2Params = ¶ms->agc2Params;
ASSERT_NO_FATAL_FAILURE(
effect.setParam(AGC2_PARAM_FIXED_DIGITAL_GAIN, agc2Params->fixedDigitalGain));
- ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
- agc2Params->adaptDigiLevelEstimator));
- ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
- agc2Params->extraSaturationMargin));
} else if (isAECEffect(uuid)) {
const AECParams* aecParams = ¶ms->aecParams;
ASSERT_NO_FATAL_FAILURE(effect.setParam(AEC_PARAM_ECHO_DELAY, aecParams->echoDelay));
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 3bd93f8..03400d7 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -400,20 +400,6 @@
ALOGE("Invalid AGC2 Fixed Digital Gain. Error %d\n", status);
return EXIT_FAILURE;
}
- if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
- (uint32_t)preProcCfgParams.agc2Level,
- effectHandle[PREPROC_AGC2]);
- status != 0) {
- ALOGE("Invalid AGC2 Level Estimator. Error %d\n", status);
- return EXIT_FAILURE;
- }
- if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
- (float)preProcCfgParams.agc2SaturationMargin,
- effectHandle[PREPROC_AGC2]);
- status != 0) {
- ALOGE("Invalid AGC2 Saturation Margin. Error %d\n", status);
- return EXIT_FAILURE;
- }
}
if (effectEn[PREPROC_NS]) {
if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
diff --git a/media/libeffects/visualizer/Android.bp b/media/libeffects/visualizer/Android.bp
index 8dd6789..fb9d7b7 100644
--- a/media/libeffects/visualizer/Android.bp
+++ b/media/libeffects/visualizer/Android.bp
@@ -18,34 +18,59 @@
],
}
-cc_library_shared {
- name: "libvisualizer",
-
+cc_defaults {
+ name: "visualizer_defaults",
vendor: true,
-
- srcs: [
- "EffectVisualizer.cpp",
- ],
-
cflags: [
- "-O2",
- "-fvisibility=hidden",
-
- "-DBUILD_FLOAT",
+ "-DBUILD_FLOAT", // TODO: remove BUILD_FLOAT and SUPPORT_MC in lvm libs
"-DSUPPORT_MC",
-
"-Wall",
"-Werror",
],
-
shared_libs: [
"liblog",
],
-
- relative_install_path: "soundfx",
-
header_libs: [
"libaudioeffects",
"libaudioutils_headers",
],
}
+
+cc_library_shared {
+ name: "libvisualizer",
+ defaults: [
+ "visualizer_defaults",
+ ],
+ srcs: [
+ "EffectVisualizer.cpp",
+ ],
+ relative_install_path: "soundfx",
+ cflags: [
+ "-O2",
+ "-fvisibility=hidden",
+ ],
+}
+
+cc_library_shared {
+ name: "libvisualizeraidl",
+ srcs: [
+ "aidl/Visualizer.cpp",
+ "aidl/VisualizerContext.cpp",
+ ":effectCommonFile",
+ ],
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "visualizer_defaults",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ ],
+ shared_libs: [
+ "libcutils",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp
new file mode 100644
index 0000000..28a7287
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/Visualizer.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2022 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_TAG "AHAL_VisualizerLibEffects"
+
+#include <android-base/logging.h>
+#include "Visualizer.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::VisualizerImpl;
+using aidl::android::hardware::audio::effect::kVisualizerImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kVisualizerImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<VisualizerImpl>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || *in_impl_uuid != kVisualizerImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ *_aidl_return = VisualizerImpl::kDescriptor;
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string VisualizerImpl::kEffectName = "Visualizer";
+const Visualizer::Capability VisualizerImpl::kCapability = {
+ .maxLatencyMs = VisualizerContext::kMaxLatencyMs,
+ .captureSampleRange = {.min = 0, .max = VisualizerContext::kMaxCaptureBufSize}};
+const Descriptor VisualizerImpl::kDescriptor = {
+ .common = {.id = {.type = kVisualizerTypeUUID,
+ .uuid = kVisualizerImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::LAST,
+ .volume = Flags::Volume::CTRL},
+ .name = VisualizerImpl::kEffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::visualizer>(VisualizerImpl::kCapability)};
+
+ndk::ScopedAStatus VisualizerImpl::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::setOnlyParameter(
+ const Visualizer::SetOnlyParameters& param) {
+ auto tag = param.getTag();
+ switch (tag) {
+ case Visualizer::SetOnlyParameters::latencyMs: {
+ RETURN_IF(mContext->setDownstreamLatency(
+ param.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& param = specific.get<Parameter::Specific::visualizer>();
+ const auto tag = param.getTag();
+ switch (tag) {
+ case Visualizer::captureSamples: {
+ RETURN_IF(mContext->setCaptureSamples(param.get<Visualizer::captureSamples>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setCaptureSizeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::scalingMode: {
+ RETURN_IF(mContext->setScalingMode(param.get<Visualizer::scalingMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setScalingModeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::measurementMode: {
+ RETURN_IF(mContext->setMeasurementMode(param.get<Visualizer::measurementMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::setOnlyParameters: {
+ return setOnlyParameter(param.get<Visualizer::setOnlyParameters>());
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus VisualizerImpl::getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
+ Parameter::Specific* specific) {
+ Visualizer visualizer;
+ Visualizer::GetOnlyParameters param;
+ switch (tag) {
+ case Visualizer::GetOnlyParameters::measurement: {
+ param.set<Visualizer::GetOnlyParameters::measurement>(mContext->getMeasure());
+ break;
+ }
+ case Visualizer::GetOnlyParameters::captureSampleBuffer: {
+ param.set<Visualizer::GetOnlyParameters::captureSampleBuffer>(mContext->capture());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
+ }
+ }
+ visualizer.set<Visualizer::getOnlyParameters>(param);
+ specific->set<Parameter::Specific::visualizer>(visualizer);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto specificId = id.get<Parameter::Id::visualizerTag>();
+ auto specificTag = specificId.getTag();
+ switch (specificTag) {
+ case Visualizer::Id::commonTag: {
+ return getParameterVisualizer(specificId.get<Visualizer::Id::commonTag>(), specific);
+ }
+ case Visualizer::Id::getOnlyParamTag: {
+ return getOnlyParameter(specificId.get<Visualizer::Id::getOnlyParamTag>(), specific);
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(specificTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ Visualizer param;
+ switch (tag) {
+ case Visualizer::captureSamples: {
+ param.set<Visualizer::captureSamples>(mContext->getCaptureSamples());
+ break;
+ }
+ case Visualizer::scalingMode: {
+ param.set<Visualizer::scalingMode>(mContext->getScalingMode());
+ break;
+ }
+ case Visualizer::measurementMode: {
+ param.set<Visualizer::measurementMode>(mContext->getMeasurementMode());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::visualizer>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> VisualizerImpl::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+
+ mContext = std::make_shared<VisualizerContext>(1 /* statusFmqDepth */, common);
+ mContext->initParams(common);
+ return mContext;
+}
+
+RetCode VisualizerImpl::releaseContext() {
+ if (mContext) {
+ mContext->disable();
+ mContext->resetBuffer();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status VisualizerImpl::effectProcessImpl(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->process(in, out, samples);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/Visualizer.h b/media/libeffects/visualizer/aidl/Visualizer.h
new file mode 100644
index 0000000..5908d9a
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/Visualizer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+#include "VisualizerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerImpl final : public EffectImpl {
+ public:
+ static const std::string kEffectName;
+ static const Visualizer::Capability kCapability;
+ static const Descriptor kDescriptor;
+ VisualizerImpl() { LOG(DEBUG) << __func__; }
+ ~VisualizerImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ std::shared_ptr<EffectContext> getContext() override { return mContext; }
+ std::string getEffectName() override { return kEffectName; }
+
+ private:
+ std::shared_ptr<VisualizerContext> mContext;
+ ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific);
+ ndk::ScopedAStatus setOnlyParameter(const Visualizer::SetOnlyParameters& param);
+ ndk::ScopedAStatus getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
new file mode 100644
index 0000000..1965e0e
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2022 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 "VisualizerContext.h"
+
+#include <algorithm>
+#include <android/binder_status.h>
+#include <audio_utils/primitives.h>
+#include <math.h>
+#include <system/audio.h>
+#include <time.h>
+#include <Utils.h>
+
+#ifndef BUILD_FLOAT
+ #error AIDL Visualizer only support float 32bits, make sure add cflags -DBUILD_FLOAT,
+#endif
+
+using android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::effect {
+
+VisualizerContext::VisualizerContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+}
+
+VisualizerContext::~VisualizerContext() {
+ std::lock_guard lg(mMutex);
+ LOG(DEBUG) << __func__;
+ mState = State::UNINITIALIZED;
+}
+
+RetCode VisualizerContext::initParams(const Parameter::Common& common) {
+ std::lock_guard lg(mMutex);
+ LOG(DEBUG) << __func__;
+ if (common.input != common.output) {
+ LOG(ERROR) << __func__ << " mismatch input: " << common.input.toString()
+ << " and output: " << common.output.toString();
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+
+ mState = State::INITIALIZED;
+ auto channelCount = getChannelCount(common.input.base.channelMask);
+#ifdef SUPPORT_MC
+ if (channelCount < 1 || channelCount > FCC_LIMIT) return RetCode::ERROR_ILLEGAL_PARAMETER;
+#else
+ if (channelCount != FCC_2) return RetCode::ERROR_ILLEGAL_PARAMETER;
+#endif
+ mChannelCount = channelCount;
+ mCommon = common;
+ return RetCode::SUCCESS;
+}
+
+RetCode VisualizerContext::enable() {
+ std::lock_guard lg(mMutex);
+ if (mState != State::INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = State::ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode VisualizerContext::disable() {
+ std::lock_guard lg(mMutex);
+ if (mState != State::ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ mState = State::INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+void VisualizerContext::reset() {
+ std::lock_guard lg(mMutex);
+ std::fill_n(mCaptureBuf.begin(), kMaxCaptureBufSize, 0x80);
+}
+
+RetCode VisualizerContext::setCaptureSamples(int samples) {
+ std::lock_guard lg(mMutex);
+ if (samples < 0 || (unsigned)samples > kMaxCaptureBufSize) {
+ LOG(ERROR) << __func__ << " captureSamples " << samples << " exceed valid range: 0 - "
+ << kMaxCaptureBufSize;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ mCaptureSamples = samples;
+ return RetCode::SUCCESS;
+}
+int VisualizerContext::getCaptureSamples() {
+ std::lock_guard lg(mMutex);
+ return mCaptureSamples;
+}
+
+RetCode VisualizerContext::setMeasurementMode(Visualizer::MeasurementMode mode) {
+ std::lock_guard lg(mMutex);
+ mMeasurementMode = mode;
+ return RetCode::SUCCESS;
+}
+Visualizer::MeasurementMode VisualizerContext::getMeasurementMode() {
+ std::lock_guard lg(mMutex);
+ return mMeasurementMode;
+}
+
+RetCode VisualizerContext::setScalingMode(Visualizer::ScalingMode mode) {
+ std::lock_guard lg(mMutex);
+ mScalingMode = mode;
+ return RetCode::SUCCESS;
+}
+Visualizer::ScalingMode VisualizerContext::getScalingMode() {
+ std::lock_guard lg(mMutex);
+ return mScalingMode;
+}
+
+RetCode VisualizerContext::setDownstreamLatency(int latency) {
+ if (latency < 0 || (unsigned)latency > kMaxLatencyMs) {
+ LOG(ERROR) << __func__ << " latency " << latency << " exceed valid range: 0 - "
+ << kMaxLatencyMs;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ std::lock_guard lg(mMutex);
+ mDownstreamLatency = latency;
+ return RetCode::SUCCESS;
+}
+
+uint32_t VisualizerContext::getDeltaTimeMsFromUpdatedTime_l() {
+ uint32_t deltaMs = 0;
+ if (mBufferUpdateTime.tv_sec != 0) {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+ time_t secs = ts.tv_sec - mBufferUpdateTime.tv_sec;
+ long nsec = ts.tv_nsec - mBufferUpdateTime.tv_nsec;
+ if (nsec < 0) {
+ --secs;
+ nsec += 1000000000;
+ }
+ deltaMs = secs * 1000 + nsec / 1000000;
+ }
+ }
+ return deltaMs;
+}
+
+Visualizer::GetOnlyParameters::Measurement VisualizerContext::getMeasure() {
+ uint16_t peakU16 = 0;
+ float sumRmsSquared = 0.0f;
+ uint8_t nbValidMeasurements = 0;
+
+ {
+ std::lock_guard lg(mMutex);
+ // reset measurements if last measurement was too long ago (which implies stored
+ // measurements aren't relevant anymore and shouldn't bias the new one)
+ const uint32_t delayMs = getDeltaTimeMsFromUpdatedTime_l();
+ if (delayMs > kDiscardMeasurementsTimeMs) {
+ LOG(INFO) << __func__ << " Discarding " << delayMs << " ms old measurements";
+ for (uint32_t i = 0; i < mMeasurementWindowSizeInBuffers; i++) {
+ mPastMeasurements[i].mIsValid = false;
+ mPastMeasurements[i].mPeakU16 = 0;
+ mPastMeasurements[i].mRmsSquared = 0;
+ }
+ mMeasurementBufferIdx = 0;
+ } else {
+ // only use actual measurements, otherwise the first RMS measure happening before
+ // MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS have been played will always be artificially
+ // low
+ for (uint32_t i = 0; i < mMeasurementWindowSizeInBuffers; i++) {
+ if (mPastMeasurements[i].mIsValid) {
+ if (mPastMeasurements[i].mPeakU16 > peakU16) {
+ peakU16 = mPastMeasurements[i].mPeakU16;
+ }
+ sumRmsSquared += mPastMeasurements[i].mRmsSquared;
+ nbValidMeasurements++;
+ }
+ }
+ }
+ }
+
+ float rms = nbValidMeasurements == 0 ? 0.0f : sqrtf(sumRmsSquared / nbValidMeasurements);
+ Visualizer::GetOnlyParameters::Measurement measure;
+ // convert from I16 sample values to mB and write results
+ measure.rms = (rms < 0.000016f) ? -9600 : (int32_t)(2000 * log10(rms / 32767.0f));
+ measure.peak = (peakU16 == 0) ? -9600 : (int32_t)(2000 * log10(peakU16 / 32767.0f));
+ LOG(INFO) << __func__ << " peak " << peakU16 << " (" << measure.peak << "mB), rms " << rms
+ << " (" << measure.rms << "mB)";
+ return measure;
+}
+
+std::vector<uint8_t> VisualizerContext::capture() {
+ std::vector<uint8_t> result;
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(mState != State::ACTIVE, result, "illegalState");
+ const uint32_t deltaMs = getDeltaTimeMsFromUpdatedTime_l();
+
+ // if audio framework has stopped playing audio although the effect is still active we must
+ // clear the capture buffer to return silence
+ if ((mLastCaptureIdx == mCaptureIdx) && (mBufferUpdateTime.tv_sec != 0) &&
+ (deltaMs > kMaxStallTimeMs)) {
+ LOG(INFO) << __func__ << " capture going to idle";
+ mBufferUpdateTime.tv_sec = 0;
+ return result;
+ }
+ int32_t latencyMs = mDownstreamLatency;
+ latencyMs -= deltaMs;
+ if (latencyMs < 0) {
+ latencyMs = 0;
+ }
+ uint32_t deltaSamples = mCaptureSamples + mCommon.input.base.sampleRate * latencyMs / 1000;
+
+ // large sample rate, latency, or capture size, could cause overflow.
+ // do not offset more than the size of buffer.
+ if (deltaSamples > kMaxCaptureBufSize) {
+ android_errorWriteLog(0x534e4554, "31781965");
+ deltaSamples = kMaxCaptureBufSize;
+ }
+
+ int32_t capturePoint;
+ //capturePoint = (int32_t)mCaptureIdx - deltaSamples;
+ __builtin_sub_overflow((int32_t) mCaptureIdx, deltaSamples, &capturePoint);
+ // a negative capturePoint means we wrap the buffer.
+ if (capturePoint < 0) {
+ uint32_t size = -capturePoint;
+ if (size > mCaptureSamples) {
+ size = mCaptureSamples;
+ }
+ result.insert(result.end(), &mCaptureBuf[kMaxCaptureBufSize + capturePoint],
+ &mCaptureBuf[kMaxCaptureBufSize + capturePoint + size]);
+ mCaptureSamples -= size;
+ capturePoint = 0;
+ }
+ result.insert(result.end(), &mCaptureBuf[capturePoint],
+ &mCaptureBuf[capturePoint + mCaptureSamples]);
+ mLastCaptureIdx = mCaptureIdx;
+ return result;
+}
+
+IEffect::Status VisualizerContext::process(float* in, float* out, int samples) {
+ IEffect::Status result = {STATUS_NOT_ENOUGH_DATA, 0, 0};
+ RETURN_VALUE_IF(in == nullptr || out == nullptr || samples == 0, result, "dataBufferError");
+
+ std::lock_guard lg(mMutex);
+ result.status = STATUS_INVALID_OPERATION;
+ RETURN_VALUE_IF(mState != State::ACTIVE, result, "stateNotActive");
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+ // perform measurements if needed
+ if (mMeasurementMode == Visualizer::MeasurementMode::PEAK_RMS) {
+ // find the peak and RMS squared for the new buffer
+ float rmsSqAcc = 0;
+ float maxSample = 0.f;
+ for (size_t inIdx = 0; inIdx < (unsigned)samples; ++inIdx) {
+ maxSample = fmax(maxSample, fabs(in[inIdx]));
+ rmsSqAcc += in[inIdx] * in[inIdx];
+ }
+ maxSample *= 1 << 15; // scale to int16_t, with exactly 1 << 15 representing positive num.
+ rmsSqAcc *= 1 << 30; // scale to int16_t * 2
+ mPastMeasurements[mMeasurementBufferIdx] = {
+ .mPeakU16 = (uint16_t)maxSample,
+ .mRmsSquared = rmsSqAcc / samples,
+ .mIsValid = true };
+ if (++mMeasurementBufferIdx >= mMeasurementWindowSizeInBuffers) {
+ mMeasurementBufferIdx = 0;
+ }
+ }
+
+ float fscale; // multiplicative scale
+ if (mScalingMode == Visualizer::ScalingMode::NORMALIZED) {
+ // derive capture scaling factor from peak value in current buffer
+ // this gives more interesting captures for display.
+ float maxSample = 0.f;
+ for (size_t inIdx = 0; inIdx < (unsigned)samples; ) {
+ // we reconstruct the actual summed value to ensure proper normalization
+ // for multichannel outputs (channels > 2 may often be 0).
+ float smp = 0.f;
+ for (int i = 0; i < mChannelCount; ++i) {
+ smp += in[inIdx++];
+ }
+ maxSample = fmax(maxSample, fabs(smp));
+ }
+ if (maxSample > 0.f) {
+ fscale = 0.99f / maxSample;
+ int exp; // unused
+ const float significand = frexp(fscale, &exp);
+ if (significand == 0.5f) {
+ fscale *= 255.f / 256.f; // avoid returning unaltered PCM signal
+ }
+ } else {
+ // scale doesn't matter, the values are all 0.
+ fscale = 1.f;
+ }
+ } else {
+ assert(mScalingMode == Visualizer::ScalingMode::AS_PLAYED);
+ // Note: if channels are uncorrelated, 1/sqrt(N) could be used at the risk of clipping.
+ fscale = 1.f / mChannelCount; // account for summing all the channels together.
+ }
+
+ uint32_t captIdx;
+ uint32_t inIdx;
+ for (inIdx = 0, captIdx = mCaptureIdx; inIdx < (unsigned)samples; captIdx++) {
+ // wrap
+ if (captIdx >= kMaxCaptureBufSize) {
+ captIdx = 0;
+ }
+
+ float smp = 0.f;
+ for (uint32_t i = 0; i < mChannelCount; ++i) {
+ smp += in[inIdx++];
+ }
+ mCaptureBuf[captIdx] = clamp8_from_float(smp * fscale);
+ }
+
+ // the following two should really be atomic, though it probably doesn't
+ // matter much for visualization purposes
+ mCaptureIdx = captIdx;
+ // update last buffer update time stamp
+ if (clock_gettime(CLOCK_MONOTONIC, &mBufferUpdateTime) < 0) {
+ mBufferUpdateTime.tv_sec = 0;
+ }
+
+ // TODO: handle access_mode
+ memcpy(out, in, samples * sizeof(float));
+ return {STATUS_OK, samples, samples};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.h b/media/libeffects/visualizer/aidl/VisualizerContext.h
new file mode 100644
index 0000000..bfda0b9
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <audio_effects/effect_dynamicsprocessing.h>
+
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerContext final : public EffectContext {
+ public:
+ static const uint32_t kMaxCaptureBufSize = 65536;
+ static const uint32_t kMaxLatencyMs = 3000; // 3 seconds of latency for audio pipeline
+
+ VisualizerContext(int statusDepth, const Parameter::Common& common);
+ ~VisualizerContext();
+
+ RetCode initParams(const Parameter::Common& common);
+
+ RetCode enable();
+ RetCode disable();
+ // keep all parameters and reset buffer.
+ void reset();
+
+ RetCode setCaptureSamples(int captureSize);
+ int getCaptureSamples();
+ RetCode setMeasurementMode(Visualizer::MeasurementMode mode);
+ Visualizer::MeasurementMode getMeasurementMode();
+ RetCode setScalingMode(Visualizer::ScalingMode mode);
+ Visualizer::ScalingMode getScalingMode();
+ RetCode setDownstreamLatency(int latency);
+
+ IEffect::Status process(float* in, float* out, int samples);
+ // Gets the current measurements, measured by process() and consumed by getParameter()
+ Visualizer::GetOnlyParameters::Measurement getMeasure();
+ // Gets the latest PCM capture, data captured by process() and consumed by getParameter()
+ std::vector<uint8_t> capture();
+
+ struct BufferStats {
+ bool mIsValid;
+ uint16_t mPeakU16; // the positive peak of the absolute value of the samples in a buffer
+ float mRmsSquared; // the average square of the samples in a buffer
+ };
+
+ enum State {
+ UNINITIALIZED,
+ INITIALIZED,
+ ACTIVE,
+ };
+
+ private:
+ // maximum time since last capture buffer update before resetting capture buffer. This means
+ // that the framework has stopped playing audio and we must start returning silence
+ static const uint32_t kMaxStallTimeMs = 1000;
+ // discard measurements older than this number of ms
+ static const uint32_t kDiscardMeasurementsTimeMs = 2000;
+ // maximum number of buffers for which we keep track of the measurements
+ // note: buffer index is stored in uint8_t
+ static const uint32_t kMeasurementWindowMaxSizeInBuffers = 25;
+
+ // serialize process() and parameter setting
+ std::mutex mMutex;
+ Parameter::Common mCommon GUARDED_BY(mMutex);
+ State mState GUARDED_BY(mMutex) = State::UNINITIALIZED;
+ uint32_t mCaptureIdx GUARDED_BY(mMutex) = 0;
+ uint32_t mLastCaptureIdx GUARDED_BY(mMutex) = 0;
+ Visualizer::ScalingMode mScalingMode GUARDED_BY(mMutex) = Visualizer::ScalingMode::NORMALIZED;
+ struct timespec mBufferUpdateTime GUARDED_BY(mMutex);
+ // capture buf with 8 bits PCM
+ std::array<uint8_t, kMaxCaptureBufSize> mCaptureBuf GUARDED_BY(mMutex);
+ uint32_t mDownstreamLatency GUARDED_BY(mMutex) = 0;
+ uint32_t mCaptureSamples GUARDED_BY(mMutex) = kMaxCaptureBufSize;
+
+ // to avoid recomputing it every time a buffer is processed
+ uint8_t mChannelCount GUARDED_BY(mMutex) = 0;
+ Visualizer::MeasurementMode mMeasurementMode GUARDED_BY(mMutex) =
+ Visualizer::MeasurementMode::NONE;
+ uint8_t mMeasurementWindowSizeInBuffers = kMeasurementWindowMaxSizeInBuffers;
+ uint8_t mMeasurementBufferIdx GUARDED_BY(mMutex) = 0;
+ std::array<BufferStats, kMeasurementWindowMaxSizeInBuffers> mPastMeasurements;
+ void init_params();
+
+ uint32_t getDeltaTimeMsFromUpdatedTime_l() REQUIRES(mMutex);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libheadtracking/SensorPoseProvider.cpp b/media/libheadtracking/SensorPoseProvider.cpp
index bd8af04..31d469c 100644
--- a/media/libheadtracking/SensorPoseProvider.cpp
+++ b/media/libheadtracking/SensorPoseProvider.cpp
@@ -42,6 +42,7 @@
// Identifier to use for our event queue on the loop.
// The number 19 is arbitrary, only useful if using multiple objects on the same looper.
+// Note: Instead of a fixed number, the SensorEventQueue's fd could be used instead.
constexpr int kIdent = 19;
static inline Looper* ALooper_to_Looper(ALooper* alooper) {
@@ -60,7 +61,8 @@
EventQueueGuard(const sp<SensorEventQueue>& queue, Looper* looper) : mQueue(queue) {
mQueue->looper = Looper_to_ALooper(looper);
mQueue->requestAdditionalInfo = false;
- looper->addFd(mQueue->getFd(), kIdent, ALOOPER_EVENT_INPUT, nullptr, nullptr);
+ looper->addFd(mQueue->getFd(), kIdent, ALOOPER_EVENT_INPUT,
+ nullptr /* callback */, nullptr /* data */);
}
~EventQueueGuard() {
@@ -75,7 +77,7 @@
[[nodiscard]] SensorEventQueue* get() const { return mQueue.get(); }
private:
- sp<SensorEventQueue> mQueue;
+ const sp<SensorEventQueue> mQueue;
};
/**
@@ -95,10 +97,7 @@
}
}
- SensorEnableGuard(const SensorEnableGuard&) = delete;
- SensorEnableGuard& operator=(const SensorEnableGuard&) = delete;
-
- // Enable moving.
+ // Enable move and delete default copy-ctor/copy-assignment.
SensorEnableGuard(SensorEnableGuard&& other) : mQueue(other.mQueue), mSensor(other.mSensor) {
other.mSensor = SensorPoseProvider::INVALID_HANDLE;
}
@@ -122,6 +121,7 @@
~SensorPoseProviderImpl() override {
// Disable all active sensors.
mEnabledSensors.clear();
+ mQuit = true;
mLooper->wake();
mThread.join();
}
@@ -130,7 +130,7 @@
// Figure out the sensor's data format.
DataFormat format = getSensorFormat(sensor);
if (format == DataFormat::kUnknown) {
- ALOGE("Unknown format for sensor %" PRId32, sensor);
+ ALOGE("%s: Unknown format for sensor %" PRId32, __func__, sensor);
return false;
}
@@ -144,17 +144,19 @@
// Enable the sensor.
if (mQueue->enableSensor(sensor, samplingPeriod.count(), 0, 0)) {
- ALOGE("Failed to enable sensor");
+ ALOGE("%s: Failed to enable sensor %" PRId32, __func__, sensor);
std::lock_guard lock(mMutex);
mEnabledSensorsExtra.erase(sensor);
return false;
}
- mEnabledSensors.emplace(sensor, SensorEnableGuard(mQueue.get(), sensor));
+ mEnabledSensors.emplace(sensor, SensorEnableGuard(mQueue, sensor));
+ ALOGD("%s: Sensor %" PRId32 " started", __func__, sensor);
return true;
}
void stopSensor(int handle) override {
+ ALOGD("%s: Sensor %" PRId32 " stopped", __func__, handle);
mEnabledSensors.erase(handle);
std::lock_guard lock(mMutex);
mEnabledSensorsExtra.erase(handle);
@@ -217,13 +219,14 @@
std::optional<int32_t> discontinuityCount;
};
+ bool mQuit = false;
sp<Looper> mLooper;
Listener* const mListener;
SensorManager* const mSensorManager;
std::timed_mutex mMutex;
+ sp<SensorEventQueue> mQueue;
std::map<int32_t, SensorEnableGuard> mEnabledSensors;
std::map<int32_t, SensorExtra> mEnabledSensorsExtra GUARDED_BY(mMutex);
- sp<SensorEventQueue> mQueue;
// We must do some of the initialization operations on the worker thread, because the API relies
// on the thread-local looper. In addition, as a matter of convenience, we store some of the
@@ -244,7 +247,13 @@
bool waitInitFinished() { return mInitPromise.get_future().get(); }
void threadFunc() {
- // Obtain looper.
+ // Name our std::thread to help identification. As is, canCallJava == false.
+ androidSetThreadName("SensorPoseProvider-looper");
+
+ // Run at the highest non-realtime priority.
+ androidSetThreadPriority(gettid(), PRIORITY_URGENT_AUDIO);
+
+ // The looper is started on the created std::thread.
mLooper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
// Create event queue.
@@ -260,20 +269,28 @@
initFinished(true);
- while (true) {
- int ret = mLooper->pollOnce(-1 /* no timeout */, nullptr, nullptr, nullptr);
+ while (!mQuit) {
+ const int ret = mLooper->pollOnce(-1 /* no timeout */, nullptr /* outFd */,
+ nullptr /* outEvents */, nullptr /* outData */);
switch (ret) {
case ALOOPER_POLL_WAKE:
- // Normal way to exit.
- return;
+ // Continue to see if mQuit flag is set.
+ // This can be spurious (due to bugreport being taken).
+ continue;
case kIdent:
// Possible events on our queue.
break;
default:
- ALOGE("Unexpected status out of Looper::pollOnce: %d", ret);
+ // Besides WAKE and kIdent, there should be no timeouts, callbacks,
+ // ALOOPER_POLL_ERROR, or other events.
+ // Exit now to avoid high frequency log spam on error,
+ // e.g. if the fd becomes invalid (b/31093485).
+ ALOGE("%s: Unexpected status out of Looper::pollOnce: %d", __func__, ret);
+ mQuit = true;
+ continue;
}
// Process an event.
@@ -285,7 +302,8 @@
ssize_t size = mQueue->filterEvents(&event, actual);
if (size < 0 || size > 1) {
- ALOGE("Unexpected return value from SensorEventQueue::filterEvents: %zd", size);
+ ALOGE("%s: Unexpected return value from SensorEventQueue::filterEvents: %zd",
+ __func__, size);
break;
}
if (size == 0) {
@@ -295,6 +313,7 @@
handleEvent(event);
}
+ ALOGD("%s: Exiting sensor event loop", __func__);
}
void handleEvent(const ASensorEvent& event) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index 6788b56..5e29b3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -191,8 +191,8 @@
uint8_t key[kBlockSize],
uint8_t iv[kBlockSize],
CryptoPlugin::Mode mode,
- size_t *clearbytes,
- size_t *encryptedbytes)
+ uint32_t *clearbytes,
+ uint32_t *encryptedbytes)
{
// size needed to store all the crypto data
size_t cryptosize;
@@ -236,7 +236,7 @@
if (!meta.findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
return NULL;
}
- size_t numSubSamples = cryptedsize / sizeof(size_t);
+ size_t numSubSamples = cryptedsize / sizeof(uint32_t);
if (numSubSamples <= 0) {
ALOGE("getSampleCryptoInfo INVALID numSubSamples: %zu", numSubSamples);
@@ -285,8 +285,8 @@
(uint8_t*) key,
(uint8_t*) iv,
(CryptoPlugin::Mode)mode,
- (size_t*) cleardata,
- (size_t*) crypteddata);
+ (uint32_t*) cleardata,
+ (uint32_t*) crypteddata);
}
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
index 4360656..232638c 100644
--- a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
+++ b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
@@ -106,8 +106,8 @@
uint8_t key[kBlockSize],
uint8_t iv[kBlockSize],
CryptoPlugin::Mode mode,
- size_t *clearbytes,
- size_t *encryptedbytes);
+ uint32_t *clearbytes,
+ uint32_t *encryptedbytes);
static CryptoInfo *getSampleCryptoInfo(MetaDataBase &meta);
diff --git a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
index c43e1f8..19c8577 100644
--- a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
+++ b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <fstream>
+#include <memory>
#include <media/stagefright/foundation/ABitReader.h>
#include <HevcUtils.h>
@@ -88,10 +89,10 @@
stringLine >> type >> chunkLength;
ASSERT_GT(chunkLength, 0) << "Length of data chunk must be greater than 0";
- char *data = (char *)malloc(chunkLength);
+ std::unique_ptr<char[]> data(new char[chunkLength]);
ASSERT_NE(data, nullptr) << "Failed to allocate data buffer of size: " << chunkLength;
- mMediaFileStream.read(data, chunkLength);
+ mMediaFileStream.read(data.get(), chunkLength);
ASSERT_EQ(mMediaFileStream.gcount(), chunkLength)
<< "Failed to read complete file, bytes read: " << mMediaFileStream.gcount();
@@ -105,7 +106,7 @@
offset += 3;
ASSERT_LE(offset, chunkLength) << "NAL unit offset must not exceed the chunk length";
- uint8_t *nalUnit = (uint8_t *)(data + offset);
+ uint8_t *nalUnit = (uint8_t *)(data.get() + offset);
size_t nalUnitLength = chunkLength - offset;
// Add NAL units only if they're of type: VPS/SPS/PPS/SEI
@@ -118,20 +119,18 @@
size_t sizeNalUnit = hevcParams.getSize(index);
ASSERT_EQ(sizeNalUnit, nalUnitLength) << "Invalid size returned for NAL: " << type;
- uint8_t *destination = (uint8_t *)malloc(nalUnitLength);
+ std::unique_ptr<uint8_t[]> destination(new uint8_t[nalUnitLength]);
ASSERT_NE(destination, nullptr)
<< "Failed to allocate buffer of size: " << nalUnitLength;
- bool status = hevcParams.write(index, destination, nalUnitLength);
+ bool status = hevcParams.write(index, destination.get(), nalUnitLength);
ASSERT_TRUE(status) << "Unable to write NAL Unit data";
- free(destination);
index++;
} else {
err = hevcParams.addNalUnit(nalUnit, nalUnitLength);
ASSERT_NE(err, (status_t)OK) << "Invalid NAL Unit added, type: " << type;
}
- free(data);
}
size_t numNalUnits = hevcParams.getNumNalUnitsOfType(kVPSCode);
@@ -166,10 +165,10 @@
<< "Expected NAL type: 34(PPS), found: " << typeNalUnit;
size_t hvccBoxSize = kHvccBoxMaxSize;
- uint8_t *hvcc = (uint8_t *)malloc(kHvccBoxMaxSize);
+ std::unique_ptr<uint8_t[]> hvcc(new uint8_t[kHvccBoxMaxSize]);
ASSERT_NE(hvcc, nullptr) << "Failed to allocate a hvcc buffer of size: " << kHvccBoxMaxSize;
- err = hevcParams.makeHvcc(hvcc, &hvccBoxSize, kNALSizeLength);
+ err = hevcParams.makeHvcc(hvcc.get(), &hvccBoxSize, kNALSizeLength);
ASSERT_EQ(err, (status_t)OK) << "Unable to create hvcc box";
ASSERT_GT(hvccBoxSize, kHvccBoxMinSize)
@@ -179,8 +178,6 @@
if (frameRate != mFrameRate)
cout << "[ WARN ] Expected frame rate: " << mFrameRate << " Found: " << frameRate
<< endl;
-
- free(hvcc);
}
// Info File contains the type and length for each chunk/frame
diff --git a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
index f934b54..b2044d3 100644
--- a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
+++ b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
@@ -22,6 +22,7 @@
#include <string.h>
#include <sys/stat.h>
#include <fstream>
+#include <memory>
#include <binder/Parcel.h>
#include <media/stagefright/foundation/AString.h>
@@ -240,10 +241,10 @@
if (remaining < tempFontNameLength) break;
const uint8_t *tmpFont = tmpData;
- char *tmpFontName = strndup((const char *)tmpFont, tempFontNameLength);
+ std::unique_ptr<char[]> tmpFontName(new char[tempFontNameLength]);
+ strncpy(tmpFontName.get(), (const char *)tmpFont, tempFontNameLength);
ASSERT_NE(tmpFontName, nullptr) << "Font Name is null";
- ALOGI("FontName = %s", tmpFontName);
- free(tmpFontName);
+ ALOGI("FontName = %s", tmpFontName.get());
tmpData += tempFontNameLength;
remaining -= tempFontNameLength;
fontRecordEntries.push_back({tempFontID, tempFontNameLength, tmpFont});
diff --git a/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
index 7221b92..2cc88ce 100644
--- a/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
+++ b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
@@ -21,6 +21,7 @@
#include <utils/Log.h>
#include <audio_utils/sndfile.h>
+#include <memory>
#include <stdio.h>
#include "pvamrwbdecoder.h"
@@ -121,7 +122,7 @@
TEST_F(AmrwbDecoderTest, MultiCreateAmrwbDecoderTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
- void *decoderBuf = malloc(memRequirements);
+ std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
@@ -129,25 +130,21 @@
void *amrHandle = nullptr;
int16_t *decoderCookie;
for (int count = 0; count < kMaxCount; count++) {
- pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+ pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
ALOGV("Decoder created successfully");
}
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
TEST_P(AmrwbDecoderTest, DecodeTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
- void *decoderBuf = malloc(memRequirements);
+ std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
void *amrHandle = nullptr;
int16_t *decoderCookie;
- pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+ pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
string inputFile = gEnv->getRes() + GetParam();
@@ -159,25 +156,21 @@
SNDFILE *outFileHandle = openOutputFile(&sfInfo);
ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
- int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+ int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
sf_close(outFileHandle);
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
TEST_P(AmrwbDecoderTest, ResetDecoderTest) {
uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
- void *decoderBuf = malloc(memRequirements);
+ std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
void *amrHandle = nullptr;
int16_t *decoderCookie;
- pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+ pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
string inputFile = gEnv->getRes() + GetParam();
@@ -190,20 +183,18 @@
ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
// Decode 150 frames first
- int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle, kNumFrameReset);
+ int32_t decoderErr =
+ DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle, kNumFrameReset);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
// Reset Decoder
- pvDecoder_AmrWb_Reset(decoderBuf, 1);
+ pvDecoder_AmrWb_Reset(decoderBuf.get(), 1);
// Start decoding again
- decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+ decoderErr = DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle);
ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
sf_close(outFileHandle);
- if (decoderBuf) {
- free(decoderBuf);
- }
}
INSTANTIATE_TEST_SUITE_P(AmrwbDecoderTestAll, AmrwbDecoderTest,
diff --git a/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp b/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
index 91326a8..88e9eae 100644
--- a/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
+++ b/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
@@ -20,6 +20,7 @@
#include <utils/Log.h>
#include <audio_utils/sndfile.h>
+#include <memory>
#include <stdio.h>
#include "mp3reader.h"
@@ -99,27 +100,23 @@
TEST_F(Mp3DecoderTest, MultiCreateMp3DecoderTest) {
size_t memRequirements = pvmp3_decoderMemRequirements();
ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
- void *decoderBuf = malloc(memRequirements);
+ unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
for (int count = 0; count < kMaxCount; count++) {
- pvmp3_InitDecoder(mConfig, decoderBuf);
+ pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
ALOGV("Decoder created successfully");
}
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
TEST_P(Mp3DecoderTest, DecodeTest) {
size_t memRequirements = pvmp3_decoderMemRequirements();
ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
- void *decoderBuf = malloc(memRequirements);
+ unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
- pvmp3_InitDecoder(mConfig, decoderBuf);
+ pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
ALOGV("Decoder created successfully");
string inputFile = gEnv->getRes() + GetParam();
bool status = mMp3Reader.init(inputFile.c_str());
@@ -130,27 +127,23 @@
SNDFILE *outFileHandle = openOutputFile(&sfInfo);
ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
- ERROR_CODE decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+ ERROR_CODE decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo);
ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
mMp3Reader.close();
sf_close(outFileHandle);
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
TEST_P(Mp3DecoderTest, ResetDecoderTest) {
size_t memRequirements = pvmp3_decoderMemRequirements();
ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
- void *decoderBuf = malloc(memRequirements);
+ unique_ptr<char[]> decoderBuf(new char[memRequirements]);
ASSERT_NE(decoderBuf, nullptr)
<< "Failed to allocate decoder memory of size " << memRequirements;
- pvmp3_InitDecoder(mConfig, decoderBuf);
+ pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
ALOGV("Decoder created successfully.");
string inputFile = gEnv->getRes() + GetParam();
bool status = mMp3Reader.init(inputFile.c_str());
@@ -162,24 +155,20 @@
ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
ERROR_CODE decoderErr;
- decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo, kNumFrameReset);
+ decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo, kNumFrameReset);
ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
- pvmp3_resetDecoder(decoderBuf);
+ pvmp3_resetDecoder((void*)decoderBuf.get());
// Decode the same file.
- decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+ decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo);
ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
mMp3Reader.close();
sf_close(outFileHandle);
- if (decoderBuf) {
- free(decoderBuf);
- decoderBuf = nullptr;
- }
}
INSTANTIATE_TEST_SUITE_P(Mp3DecoderTestAll, Mp3DecoderTest,
diff --git a/media/module/esds/TEST_MAPPING b/media/module/esds/TEST_MAPPING
new file mode 100644
index 0000000..9368b6d
--- /dev/null
+++ b/media/module/esds/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/module/esds
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+ { "name": "ESDSTest" }
+ ]
+}
diff --git a/media/module/esds/tests/ESDSTest.cpp b/media/module/esds/tests/ESDSTest.cpp
index ea9a888..33bdcac 100644
--- a/media/module/esds/tests/ESDSTest.cpp
+++ b/media/module/esds/tests/ESDSTest.cpp
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <string.h>
#include <fstream>
+#include <memory>
#include <media/esds/ESDS.h>
#include <binder/ProcessState.h>
@@ -121,18 +122,16 @@
};
TEST_P(ESDSUnitTest, InvalidDataTest) {
- void *invalidData = calloc(mESDSSize, 1);
+ std::unique_ptr<char[]> invalidData(new char[mESDSSize]());
ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
- ESDS esds(invalidData, mESDSSize);
- free(invalidData);
+ ESDS esds((void*)invalidData.get(), mESDSSize);
ASSERT_NE(esds.InitCheck(), OK) << "invalid ESDS data accepted";
}
TEST(ESDSSanityUnitTest, ConstructorSanityTest) {
- void *invalidData = malloc(1);
+ std::unique_ptr<char[]> invalidData(new char[1]());
ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
- ESDS esds_zero(invalidData, 0);
- free(invalidData);
+ ESDS esds_zero((void*)invalidData.get(), 0);
ASSERT_NE(esds_zero.InitCheck(), OK) << "invalid ESDS data accepted";
ESDS esds_null(NULL, 0);
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 2e889e3..3a5a869 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -394,6 +394,15 @@
return MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1;
case FOURCC("mhm1"):
return MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1;
+ case FOURCC("dtsc"):
+ return MEDIA_MIMETYPE_AUDIO_DTS;
+ case FOURCC("dtse"):
+ case FOURCC("dtsh"):
+ return MEDIA_MIMETYPE_AUDIO_DTS_HD;
+ case FOURCC("dtsl"):
+ return MEDIA_MIMETYPE_AUDIO_DTS_HD_MA;
+ case FOURCC("dtsx"):
+ return MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2;
default:
ALOGW("Unknown fourcc: %c%c%c%c",
(fourcc >> 24) & 0xff,
@@ -1804,6 +1813,11 @@
case 0x6D730055: // "ms U" mp3 audio
case FOURCC("mha1"):
case FOURCC("mhm1"):
+ case FOURCC("dtsc"):
+ case FOURCC("dtse"):
+ case FOURCC("dtsh"):
+ case FOURCC("dtsl"):
+ case FOURCC("dtsx"):
{
if (mIsQT && depth >= 1 && mPath[depth - 1] == FOURCC("wave")) {
@@ -6723,7 +6737,7 @@
const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
offset = smpl->offset;
size = smpl->size;
- cts = mCurrentTime + smpl->compositionOffset;
+ cts = (int64_t)mCurrentTime + (int64_t)smpl->compositionOffset;
if (mElstInitialEmptyEditTicks > 0) {
cts += mElstInitialEmptyEditTicks;
diff --git a/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp b/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
index 77a8599..57ac822 100644
--- a/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
+++ b/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <fstream>
+#include <memory>
#include "media/stagefright/foundation/ABitReader.h"
#include "media/stagefright/foundation/avc_utils.h"
@@ -151,10 +152,10 @@
size_t fileSize = buf.st_size;
ASSERT_NE(fileSize, 0) << "Invalid file size found";
- const uint8_t *volBuffer = new uint8_t[fileSize];
+ std::unique_ptr<uint8_t[]> volBuffer(new uint8_t[fileSize]);
ASSERT_NE(volBuffer, nullptr) << "Failed to allocate VOL buffer of size: " << fileSize;
- inputFileStream.read((char *)(volBuffer), fileSize);
+ inputFileStream.read((char *)(volBuffer.get()), fileSize);
ASSERT_EQ(inputFileStream.gcount(), fileSize)
<< "Failed to read complete file, bytes read: " << inputFileStream.gcount();
@@ -163,15 +164,13 @@
int32_t volWidth = -1;
int32_t volHeight = -1;
- bool status = ExtractDimensionsFromVOLHeader(volBuffer, fileSize, &volWidth, &volHeight);
+ bool status = ExtractDimensionsFromVOLHeader(volBuffer.get(), fileSize, &volWidth, &volHeight);
ASSERT_TRUE(status)
<< "Failed to get VOL dimensions from function: ExtractDimensionsFromVOLHeader()";
ASSERT_EQ(volWidth, width) << "Expected width: " << width << "Found: " << volWidth;
ASSERT_EQ(volHeight, height) << "Expected height: " << height << "Found: " << volHeight;
-
- delete[] volBuffer;
}
TEST_P(AVCDimensionTest, DimensionTest) {
@@ -186,7 +185,8 @@
stringLine >> type >> chunkLength;
ASSERT_GT(chunkLength, 0) << "Length of the data chunk must be greater than zero";
- const uint8_t *data = new uint8_t[chunkLength];
+ std::unique_ptr<uint8_t[]> dataArray(new uint8_t[chunkLength]);
+ const uint8_t *data = dataArray.get();
ASSERT_NE(data, nullptr) << "Failed to create a data buffer of size: " << chunkLength;
const uint8_t *nalStart;
@@ -197,9 +197,11 @@
<< "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
size_t smallBufferSize = kSmallBufferSize;
- const uint8_t *sanityData = new uint8_t[smallBufferSize];
+ uint8_t sanityDataBuffer[smallBufferSize];
+ const uint8_t *sanityData = sanityDataBuffer;
memcpy((void *)sanityData, (void *)data, smallBufferSize);
+ // sanityData could be changed, but sanityDataPtr is not and can be cleaned up.
status_t result = getNextNALUnit(&sanityData, &smallBufferSize, &nalStart, &nalSize, true);
ASSERT_EQ(result, -EAGAIN) << "Invalid result found when wrong NAL unit passed";
@@ -221,7 +223,6 @@
ASSERT_EQ(avcHeight, mFrameHeight)
<< "Expected height: " << mFrameHeight << "Found: " << avcHeight;
}
- delete[] data;
}
if (mNalUnitsExpected < 0) {
ASSERT_GT(numNalUnits, 0) << "Failed to find an NAL Unit";
@@ -251,7 +252,8 @@
accessUnitLength += chunkLength;
if (!type.compare("SPS")) {
- const uint8_t *data = new uint8_t[chunkLength];
+ std::unique_ptr<uint8_t[]> dataArray(new uint8_t[chunkLength]);
+ const uint8_t *data = dataArray.get();
ASSERT_NE(data, nullptr) << "Failed to create a data buffer of size: " << chunkLength;
const uint8_t *nalStart;
@@ -271,14 +273,13 @@
profile = nalStart[1];
level = nalStart[3];
}
- delete[] data;
}
}
- const uint8_t *accessUnitData = new uint8_t[accessUnitLength];
+ std::unique_ptr<uint8_t[]> accessUnitData(new uint8_t[accessUnitLength]);
ASSERT_NE(accessUnitData, nullptr) << "Failed to create a buffer of size: " << accessUnitLength;
mInputFileStream.seekg(0, ios::beg);
- mInputFileStream.read((char *)accessUnitData, accessUnitLength);
+ mInputFileStream.read((char *)accessUnitData.get(), accessUnitLength);
ASSERT_EQ(mInputFileStream.gcount(), accessUnitLength)
<< "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
@@ -286,7 +287,7 @@
ASSERT_NE(accessUnit, nullptr)
<< "Failed to create an android data buffer of size: " << accessUnitLength;
- memcpy(accessUnit->data(), accessUnitData, accessUnitLength);
+ memcpy(accessUnit->data(), accessUnitData.get(), accessUnitLength);
sp<ABuffer> csdDataBuffer = MakeAVCCodecSpecificData(accessUnit, &avcWidth, &avcHeight);
ASSERT_NE(csdDataBuffer, nullptr) << "No data returned from MakeAVCCodecSpecificData()";
@@ -306,7 +307,6 @@
ASSERT_EQ(*(csdData + 3), level)
<< "Expected AVC level: " << level << " found: " << *(csdData + 3);
csdDataBuffer.clear();
- delete[] accessUnitData;
accessUnit.clear();
}
@@ -321,32 +321,31 @@
stringLine >> type >> chunkLength >> frameLayerID;
ASSERT_GT(chunkLength, 0) << "Length of the data chunk must be greater than zero";
- char *data = new char[chunkLength];
+ std::unique_ptr<char[]> data(new char[chunkLength]);
ASSERT_NE(data, nullptr) << "Failed to allocation data buffer of size: " << chunkLength;
- mInputFileStream.read(data, chunkLength);
+ mInputFileStream.read(data.get(), chunkLength);
ASSERT_EQ(mInputFileStream.gcount(), chunkLength)
<< "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
if (!type.compare("IDR")) {
- bool isIDR = IsIDR((uint8_t *)data, chunkLength);
+ bool isIDR = IsIDR((uint8_t *)data.get(), chunkLength);
ASSERT_TRUE(isIDR);
- layerID = FindAVCLayerId((uint8_t *)data, chunkLength);
+ layerID = FindAVCLayerId((uint8_t *)data.get(), chunkLength);
ASSERT_EQ(layerID, frameLayerID) << "Wrong layer ID found";
} else if (!type.compare("P") || !type.compare("B")) {
sp<ABuffer> accessUnit = new ABuffer(chunkLength);
ASSERT_NE(accessUnit, nullptr) << "Unable to create access Unit";
- memcpy(accessUnit->data(), data, chunkLength);
+ memcpy(accessUnit->data(), data.get(), chunkLength);
bool isReferenceFrame = IsAVCReferenceFrame(accessUnit);
ASSERT_TRUE(isReferenceFrame);
accessUnit.clear();
- layerID = FindAVCLayerId((uint8_t *)data, chunkLength);
+ layerID = FindAVCLayerId((uint8_t *)data.get(), chunkLength);
ASSERT_EQ(layerID, frameLayerID) << "Wrong layer ID found";
}
- delete[] data;
}
}
diff --git a/media/module/foundation/tests/MetaDataBaseUnitTest.cpp b/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
index 0aed4d2..b562e07 100644
--- a/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
+++ b/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
@@ -19,6 +19,7 @@
#include <string.h>
#include <sys/stat.h>
#include <fstream>
+#include <memory>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaDataBase.h>
@@ -48,18 +49,16 @@
class MetaDataBaseUnitTest : public ::testing::Test {};
TEST_F(MetaDataBaseUnitTest, CreateMetaDataBaseTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
// Testing copy constructor
- MetaDataBase *metaDataCopy = metaData;
+ MetaDataBase *metaDataCopy = metaData.get();
ASSERT_NE(metaDataCopy, nullptr) << "Failed to create meta data copy";
-
- delete metaData;
}
TEST_F(MetaDataBaseUnitTest, SetAndFindDataTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
// Setting the different key-value pair type for first time, overwrite
@@ -142,12 +141,10 @@
int32_t angle;
status = metaData->findInt32(kKeyRotation, &angle);
ASSERT_FALSE(status) << "Value for an invalid key is returned when the key is not set";
-
- delete (metaData);
}
TEST_F(MetaDataBaseUnitTest, OverWriteFunctionalityTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
// set/set/read to check first overwrite operation
@@ -186,12 +183,10 @@
status = metaData->findInt32(kKeyHeight, &height);
ASSERT_TRUE(status) << "kKeyHeight key does not exists in metadata";
ASSERT_EQ(height, kHeight3) << "Value of height is not overwritten";
-
- delete (metaData);
}
TEST_F(MetaDataBaseUnitTest, RemoveKeyTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
bool status = metaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -246,12 +241,10 @@
metaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
ASSERT_FALSE(status) << "Overwrite should be false since the metadata was cleared";
-
- delete (metaData);
}
TEST_F(MetaDataBaseUnitTest, ConvertToStringTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
String8 info = metaData->toString();
@@ -281,8 +274,6 @@
info = metaData->toString();
ASSERT_EQ(info.length(), 0) << "MetaData length is non-zero after clearing it: "
<< info.length();
-
- delete (metaData);
}
} // namespace android
diff --git a/media/module/metadatautils/TEST_MAPPING b/media/module/metadatautils/TEST_MAPPING
new file mode 100644
index 0000000..21836a5
--- /dev/null
+++ b/media/module/metadatautils/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/module/metadatautils
+{
+ // tests which require dynamic content
+ // invoke with: atest -- --enable-module-dynamic-download=true
+ // TODO(b/148094059): unit tests not allowed to download content
+ "dynamic-presubmit": [
+ { "name": "MetaDataUtilsTest" }
+ ]
+}
diff --git a/media/module/metadatautils/test/MetaDataUtilsTest.cpp b/media/module/metadatautils/test/MetaDataUtilsTest.cpp
index 08c9284..7c35249 100644
--- a/media/module/metadatautils/test/MetaDataUtilsTest.cpp
+++ b/media/module/metadatautils/test/MetaDataUtilsTest.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <fstream>
+#include <memory>
#include <string>
#include <media/esds/ESDS.h>
@@ -228,7 +229,7 @@
ASSERT_TRUE(status) << "Failed to get the mime type";
ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_VIDEO_AVC);
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
@@ -264,7 +265,6 @@
int32_t result = memcmp(csdAMediaFormatBuffer, csdMetaDataBaseBuffer, csdAMediaFormatSize);
ASSERT_EQ(result, 0) << "CSD from AMediaFormat and MetaDataBase do not match";
- delete metaData;
AMediaFormat_delete(csdData);
}
@@ -275,7 +275,7 @@
bool status = MakeAVCCodecSpecificData(csdData, mInputBuffer, mInputBufferSize);
ASSERT_FALSE(status) << "MakeAVCCodecSpecificData with AMediaFormat succeeds with invalid data";
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
@@ -307,7 +307,7 @@
ASSERT_TRUE(status) << "Failed to get the mime type";
ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
status = MakeAACCodecSpecificData(*metaData, mAacProfile, mAacSamplingFreqIndex,
@@ -356,11 +356,10 @@
ASSERT_EQ(memcmpResult, 0) << "AMediaFormat and MetaDataBase CSDs do not match";
AMediaFormat_delete(csdData);
- delete metaData;
}
TEST_P(AacADTSTest, AacADTSValidationTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
@@ -380,12 +379,10 @@
status = metaData->findCString(kKeyMIMEType, &mimeType);
ASSERT_TRUE(status) << "Failed to get mime type";
ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
-
- delete metaData;
}
TEST_P(AacCSDValidateTest, AacInvalidInputTest) {
- MetaDataBase *metaData = new MetaDataBase();
+ std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
@@ -412,14 +409,14 @@
istringstream dataStringLine(dataLine);
dataStringLine >> comment;
- char *buffer = strndup(comment.c_str(), commentLength);
+ std::unique_ptr<char[]> buffer(new char[commentLength]);
ASSERT_NE(buffer, nullptr) << "Failed to allocate buffer of size: " << commentLength;
+ strncpy(buffer.get(), comment.c_str(), commentLength);
AMediaFormat *fileMeta = AMediaFormat_new();
ASSERT_NE(fileMeta, nullptr) << "Failed to create AMedia format";
- parseVorbisComment(fileMeta, buffer, commentLength);
- free(buffer);
+ parseVorbisComment(fileMeta, buffer.get(), commentLength);
if (!strncasecmp(tag.c_str(), "ANDROID_HAPTIC", sizeof(tag))) {
int32_t numChannelExpected = stoi(value);
diff --git a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
index 8577e62..b4e659c 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
@@ -33,7 +33,11 @@
class MtpPropertyFuzzer : MtpPacketFuzzerUtils {
public:
- MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+ MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+ sizeof(struct usbdevfs_iso_packet_desc));
+ };
+ ~MtpPropertyFuzzer() { free(mUsbDevFsUrb); };
void process();
private:
@@ -41,7 +45,7 @@
};
void MtpPropertyFuzzer::process() {
- MtpProperty* mtpProperty;
+ MtpProperty* mtpProperty = nullptr;
if (mFdp.ConsumeBool()) {
mtpProperty = new MtpProperty();
} else {
@@ -75,6 +79,7 @@
fillFilePath(&mFdp);
int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
fillUsbRequest(fd, &mFdp);
+ mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
mtpDataPacket.write(&mUsbRequest,
mFdp.PickValueInArray<UrbPacketDivisionMode>(
kUrbPacketDivisionModes),
diff --git a/media/utils/SchedulingPolicyService.cpp b/media/utils/SchedulingPolicyService.cpp
index ad38862..6e515ff 100644
--- a/media/utils/SchedulingPolicyService.cpp
+++ b/media/utils/SchedulingPolicyService.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
#include <utils/Mutex.h>
#include "ISchedulingPolicyService.h"
#include "mediautils/SchedulingPolicyService.h"
@@ -86,4 +87,25 @@
return ret;
}
+int requestSpatializerPriority(pid_t pid, pid_t tid) {
+ if (pid == -1 || tid == -1) return BAD_VALUE;
+
+ // update priority to RT if specified.
+ constexpr int32_t kRTPriorityMin = 1;
+ constexpr int32_t kRTPriorityMax = 3;
+ const int32_t priorityBoost =
+ property_get_int32("audio.spatializer.priority", kRTPriorityMin);
+ if (priorityBoost >= kRTPriorityMin && priorityBoost <= kRTPriorityMax) {
+ const status_t status = requestPriority(
+ pid, tid, priorityBoost, false /* isForApp */, true /*asynchronous*/);
+ if (status != OK) {
+ ALOGW("%s: Cannot request spatializer priority boost %d, status:%d",
+ __func__, priorityBoost, status);
+ return status < 0 ? status : UNKNOWN_ERROR;
+ }
+ return priorityBoost;
+ }
+ return 0; // no boost requested
+}
+
} // namespace android
diff --git a/media/utils/include/mediautils/SchedulingPolicyService.h b/media/utils/include/mediautils/SchedulingPolicyService.h
index 546cec5..af1fcd2 100644
--- a/media/utils/include/mediautils/SchedulingPolicyService.h
+++ b/media/utils/include/mediautils/SchedulingPolicyService.h
@@ -23,7 +23,7 @@
class IBinder;
// Request elevated priority for thread tid, whose thread group leader must be pid.
-// The priority parameter is currently restricted to either 1 or 2.
+// The priority parameter is currently restricted from 1 to 3.
// The asynchronous parameter should be 'true' to return immediately,
// after the request is enqueued but not necessarily executed.
// The default value 'false' means to return after request has been enqueued and executed.
@@ -37,6 +37,12 @@
// 'client' is ignored in this case.
int requestCpusetBoost(bool enable, const sp<IBinder> &client);
+// Audio: Request Spatializer RT priority for thread tid, whose thread group leader must be pid.
+// returns positive value if successful, the RT priority used
+// zero, if no RT priority selected
+// negative status code if RT priority unable to be set.
+int requestSpatializerPriority(pid_t pid, pid_t tid);
+
} // namespace android
#endif // _ANDROID_SCHEDULING_POLICY_SERVICE_H
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8f82657..5b49e70 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2117,9 +2117,9 @@
void AudioFlinger::onSupportedLatencyModesChanged(
audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
int32_t outputAidl = VALUE_OR_FATAL(legacy2aidl_audio_io_handle_t_int32_t(output));
- std::vector<media::LatencyMode> modesAidl = VALUE_OR_FATAL(
- convertContainer<std::vector<media::LatencyMode>>(modes,
- legacy2aidl_audio_latency_mode_t_LatencyMode));
+ std::vector<media::audio::common::AudioLatencyMode> modesAidl = VALUE_OR_FATAL(
+ convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+ modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
Mutex::Autolock _l(mClientLock);
size_t size = mNotificationClients.size();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fc4c807..7b9b44a 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -678,14 +678,16 @@
binder::Status getVolumeShaperState(
int32_t id,
std::optional<media::VolumeShaperState>* _aidl_return) override;
- binder::Status getDualMonoMode(media::AudioDualMonoMode* _aidl_return) override;
- binder::Status setDualMonoMode(media::AudioDualMonoMode mode) override;
+ binder::Status getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return) override;
+ binder::Status setDualMonoMode(
+ media::audio::common::AudioDualMonoMode mode) override;
binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
binder::Status setAudioDescriptionMixLevel(float leveldB) override;
binder::Status getPlaybackRateParameters(
- media::AudioPlaybackRate* _aidl_return) override;
+ media::audio::common::AudioPlaybackRate* _aidl_return) override;
binder::Status setPlaybackRateParameters(
- const media::AudioPlaybackRate& playbackRate) override;
+ const media::audio::common::AudioPlaybackRate& playbackRate) override;
private:
const sp<PlaybackThread::Track> mTrack;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index fc3c07f..98829d0 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1756,6 +1756,7 @@
mNotifyFramesProcessed(notifyFramesProcessed)
{
ALOGV("constructor %p client %p", this, client.get());
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
if (client == 0) {
return;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 67a8caf..a4c1832 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -269,6 +269,23 @@
return ss.str();
}
+static std::string toString(audio_latency_mode_t mode) {
+ // We convert to the AIDL type to print (eventually the legacy type will be removed).
+ const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+ return result.has_value() ? media::audio::common::toString(*result) : "UNKNOWN";
+}
+
+// Could be made a template, but other toString overloads for std::vector are confused.
+static std::string toString(const std::vector<audio_latency_mode_t>& elements) {
+ std::string s("{ ");
+ for (const auto& e : elements) {
+ s.append(toString(e));
+ s.append(" ");
+ }
+ s.append("}");
+ return s;
+}
+
static pthread_once_t sFastTrackMultiplierOnce = PTHREAD_ONCE_INIT;
static void sFastTrackMultiplierInit()
@@ -7321,6 +7338,17 @@
if (status != INVALID_OPERATION) {
updateHalSupportedLatencyModes_l();
}
+
+ const pid_t tid = getTid();
+ if (tid == -1) {
+ // Unusual: PlaybackThread::onFirstRef() should set the threadLoop running.
+ ALOGW("%s: Cannot update Spatializer mixer thread priority, not running", __func__);
+ } else {
+ const int priorityBoost = requestSpatializerPriority(getpid(), tid);
+ if (priorityBoost > 0) {
+ stream()->setHalThreadPriority(priorityBoost);
+ }
+ }
}
status_t AudioFlinger::SpatializerThread::createAudioPatch_l(const struct audio_patch *patch,
@@ -7333,10 +7361,13 @@
void AudioFlinger::SpatializerThread::updateHalSupportedLatencyModes_l() {
std::vector<audio_latency_mode_t> latencyModes;
- if (mOutput->stream->getRecommendedLatencyModes(&latencyModes) != NO_ERROR) {
+ const status_t status = mOutput->stream->getRecommendedLatencyModes(&latencyModes);
+ if (status != NO_ERROR) {
latencyModes.clear();
}
if (latencyModes != mSupportedLatencyModes) {
+ ALOGD("%s: thread(%d) status %d supported latency modes: %s",
+ __func__, mId, status, toString(latencyModes).c_str());
mSupportedLatencyModes.swap(latencyModes);
sendHalLatencyModesChangedEvent_l();
}
@@ -7376,6 +7407,8 @@
if (latencyMode != mSetLatencyMode) {
status_t status = mOutput->stream->setLatencyMode(latencyMode);
+ ALOGD("%s: thread(%d) setLatencyMode(%s) returned %d",
+ __func__, mId, toString(latencyMode).c_str(), status);
if (status == NO_ERROR) {
mSetLatencyMode = latencyMode;
}
@@ -7457,6 +7490,8 @@
std::vector<audio_latency_mode_t> modes) {
Mutex::Autolock _l(mLock);
if (modes != mSupportedLatencyModes) {
+ ALOGD("%s: thread(%d) supported latency modes: %s",
+ __func__, mId, toString(modes).c_str());
mSupportedLatencyModes.swap(modes);
sendHalLatencyModesChangedEvent_l();
}
@@ -7533,10 +7568,11 @@
ALOGV("%p kUseFastCapture = Always, initFastCapture = true", this);
break;
case FastCapture_Static:
- initFastCapture = (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
- ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d",
- this, (long long)mFrameCount, mSampleRate, kMinNormalCaptureBufferSizeMs,
- initFastCapture);
+ initFastCapture = !mIsMsdDevice // Disable fast capture for MSD BUS devices.
+ && (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
+ ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d "
+ "mIsMsdDevice = %d", this, (long long)mFrameCount, mSampleRate,
+ kMinNormalCaptureBufferSizeMs, initFastCapture, mIsMsdDevice);
break;
// case FastCapture_Dynamic:
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ca31bbc..02c4aaf 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -334,6 +334,7 @@
: BnAudioTrack(),
mTrack(track)
{
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
AudioFlinger::TrackHandle::~TrackHandle() {
@@ -438,7 +439,8 @@
return Status::ok();
}
-Status AudioFlinger::TrackHandle::getDualMonoMode(media::AudioDualMonoMode* _aidl_return)
+Status AudioFlinger::TrackHandle::getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return)
{
audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
const status_t status = mTrack->getDualMonoMode(&mode)
@@ -451,7 +453,7 @@
}
Status AudioFlinger::TrackHandle::setDualMonoMode(
- media::AudioDualMonoMode mode)
+ media::audio::common::AudioDualMonoMode mode)
{
const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
@@ -475,7 +477,7 @@
}
Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
- media::AudioPlaybackRate* _aidl_return)
+ media::audio::common::AudioPlaybackRate* _aidl_return)
{
audio_playback_rate_t localPlaybackRate{};
status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
@@ -488,7 +490,7 @@
}
Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
- const media::AudioPlaybackRate& playbackRate)
+ const media::audio::common::AudioPlaybackRate& playbackRate)
{
const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
@@ -2327,6 +2329,7 @@
: BnAudioRecord(),
mRecordTrack(recordTrack)
{
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
AudioFlinger::RecordHandle::~RecordHandle() {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b8c39f4..3518037 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -68,16 +68,6 @@
// media / notification / system volume.
constexpr float IN_CALL_EARPIECE_HEADROOM_DB = 3.f;
-// Compressed formats for MSD module, ordered from most preferred to least preferred.
-static const std::vector<audio_format_t> msdCompressedFormatsOrder = {{
- AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
- AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
-// Channel masks for MSD module, 3D > 2D > 1D ordering (most preferred to least preferred).
-static const std::vector<audio_channel_mask_t> msdSurroundChannelMasksOrder = {{
- AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
- AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
- AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
-
template <typename T>
bool operator== (const SortedVector<T> &left, const SortedVector<T> &right)
{
@@ -1644,10 +1634,28 @@
const AudioProfileVector &sourceProfiles, const AudioProfileVector &sinkProfiles,
audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
{
+ // Compressed formats for MSD module, ordered from most preferred to least preferred.
+ static const std::vector<audio_format_t> formatsOrder = {{
+ AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
+ AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
+ static const std::vector<audio_channel_mask_t> channelMasksOrder = [](){
+ // Channel position masks for MSD module, 3D > 2D > 1D ordering (most preferred to least
+ // preferred).
+ std::vector<audio_channel_mask_t> masks = {{
+ AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
+ AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
+ AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
+ // insert index masks (higher counts most preferred) as preferred over position masks
+ for (int i = 1; i <= AUDIO_CHANNEL_COUNT_MAX; i++) {
+ masks.insert(
+ masks.begin(), audio_channel_mask_for_index_assignment_from_count(i));
+ }
+ return masks;
+ }();
+
struct audio_config_base bestSinkConfig;
- status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles,
- msdCompressedFormatsOrder, msdSurroundChannelMasksOrder,
- true /*preferHigherSamplingRates*/, bestSinkConfig);
+ status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles, formatsOrder,
+ channelMasksOrder, true /*preferHigherSamplingRates*/, bestSinkConfig);
if (result != NO_ERROR) {
ALOGD("%s() no matching config found for sink, hwAvSync: %d",
__func__, hwAvSync);
@@ -1669,7 +1677,10 @@
}
sourceConfig->sample_rate = bestSinkConfig.sample_rate;
// Specify exact channel mask to prevent guessing by bit count in PatchPanel.
- sourceConfig->channel_mask = audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
+ sourceConfig->channel_mask =
+ audio_channel_mask_get_representation(bestSinkConfig.channel_mask)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX ?
+ bestSinkConfig.channel_mask : audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
sourceConfig->format = bestSinkConfig.format;
// Copy input stream directly without any processing (e.g. resampling).
sourceConfig->flags.input = static_cast<audio_input_flags_t>(
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 92e1b6b..281785e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -202,6 +202,7 @@
mCaptureStateNotifier(false),
mCreateAudioPolicyManager(createAudioPolicyManager),
mDestroyAudioPolicyManager(destroyAudioPolicyManager) {
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
void AudioPolicyService::loadAudioPolicyManager()
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 38ad494..2fe7b9e 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -34,6 +34,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/MediaMetricsItem.h>
#include <media/ShmemCompat.h>
+#include <mediautils/SchedulingPolicyService.h>
#include <mediautils/ServiceUtilities.h>
#include <utils/Thread.h>
@@ -111,6 +112,14 @@
};
void onMessageReceived(const sp<AMessage> &msg) override {
+ // No ALooper method to get the tid so update
+ // Spatializer priority on the first message received.
+ std::call_once(mPrioritySetFlag, [](){
+ const pid_t pid = getpid();
+ const pid_t tid = gettid();
+ (void)requestSpatializerPriority(pid, tid);
+ });
+
sp<Spatializer> spatializer = mSpatializer.promote();
if (spatializer == nullptr) {
ALOGW("%s: Cannot promote spatializer", __func__);
@@ -163,6 +172,7 @@
}
private:
wp<Spatializer> mSpatializer;
+ std::once_flag mPrioritySetFlag;
};
const std::vector<const char *> Spatializer::sHeadPoseKeys = {
@@ -255,6 +265,7 @@
: mEngineDescriptor(engineDescriptor),
mPolicyCallback(callback) {
ALOGV("%s", __func__);
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
void Spatializer::onFirstRef() {
@@ -263,7 +274,7 @@
mLooper->start(
/*runOnCallingThread*/false,
/*canCallJava*/ false,
- PRIORITY_AUDIO);
+ PRIORITY_URGENT_AUDIO);
mHandler = new EngineCallbackHandler(this);
mLooper->registerHandler(mHandler);
@@ -963,7 +974,10 @@
}
}
if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
- AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
+ const status_t status =
+ AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
+ ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
+ __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
}
}
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index bcbd92b..0f6bafe 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -23,6 +23,7 @@
#include <android/media/SpatializationLevel.h>
#include <android/media/SpatializationMode.h>
#include <android/media/SpatializerHeadTrackingMode.h>
+#include <android/media/audio/common/AudioLatencyMode.h>
#include <audio_utils/SimpleLog.h>
#include <math.h>
#include <media/AudioEffect.h>
@@ -165,14 +166,11 @@
std::string toString(unsigned level) const NO_THREAD_SAFETY_ANALYSIS;
static std::string toString(audio_latency_mode_t mode) {
- switch (mode) {
- case AUDIO_LATENCY_MODE_FREE:
- return "LATENCY_MODE_FREE";
- case AUDIO_LATENCY_MODE_LOW:
- return "LATENCY_MODE_LOW";
- }
- return "EnumNotImplemented";
- };
+ // We convert to the AIDL type to print (eventually the legacy type will be removed).
+ const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+ return result.has_value() ?
+ media::audio::common::toString(*result) : "unknown_latency_mode";
+ }
/**
* Format head to stage vector to a string, [0.00, 0.00, 0.00, -1.29, -0.50, 15.27].
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index d51c57c..c341b32 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -446,7 +446,7 @@
sp<AudioProfile> ac3OutputProfile = new AudioProfile(
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
sp<AudioProfile> iec958OutputProfile = new AudioProfile(
- AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
+ AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
mMsdOutputDevice->addAudioProfile(pcmOutputProfile);
mMsdOutputDevice->addAudioProfile(ac3OutputProfile);
mMsdOutputDevice->addAudioProfile(iec958OutputProfile);
@@ -519,7 +519,7 @@
// Add HDMI input device with IEC60958 profile for HDMI in -> MSD patching.
mHdmiInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_HDMI);
sp<AudioProfile> iec958InputProfile = new AudioProfile(
- AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate);
+ AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
mHdmiInputDevice->addAudioProfile(iec958InputProfile);
config.addDevice(mHdmiInputDevice);
sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
@@ -677,8 +677,8 @@
ASSERT_EQ(AUDIO_PORT_ROLE_SINK, patch->mPatch.sinks[0].role);
ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sources[0].format);
ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sinks[0].format);
- ASSERT_EQ(AUDIO_CHANNEL_IN_STEREO, patch->mPatch.sources[0].channel_mask);
- ASSERT_EQ(AUDIO_CHANNEL_OUT_STEREO, patch->mPatch.sinks[0].channel_mask);
+ ASSERT_EQ(AUDIO_CHANNEL_INDEX_MASK_24, patch->mPatch.sources[0].channel_mask);
+ ASSERT_EQ(AUDIO_CHANNEL_INDEX_MASK_24, patch->mPatch.sinks[0].channel_mask);
ASSERT_EQ(k48000SamplingRate, patch->mPatch.sources[0].sample_rate);
ASSERT_EQ(k48000SamplingRate, patch->mPatch.sinks[0].sample_rate);
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
@@ -754,7 +754,7 @@
audio_config_base_t msdDirectConfig2 = AUDIO_CONFIG_BASE_INITIALIZER;
msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
msdDirectConfig2.sample_rate = 48000;
- msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ msdDirectConfig2.channel_mask = AUDIO_CHANNEL_INDEX_MASK_24;
audio_config_base_t msdNonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER;
msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
@@ -821,7 +821,7 @@
audio_config_t msdDirectConfig2 = AUDIO_CONFIG_INITIALIZER;
msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
msdDirectConfig2.sample_rate = 48000;
- msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ msdDirectConfig2.channel_mask = AUDIO_CHANNEL_INDEX_MASK_24;
audio_config_t msdNonDirectConfig = AUDIO_CONFIG_INITIALIZER;
msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 15df981..2a8a103 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -944,8 +944,8 @@
std::vector<int> surfaceIds;
bool isDepthCompositeStream =
camera3::DepthCompositeStream::isDepthCompositeStream(surfaces[0]);
- bool isHeicCompisiteStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
- if (isDepthCompositeStream || isHeicCompisiteStream) {
+ bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
+ if (isDepthCompositeStream || isHeicCompositeStream) {
sp<CompositeStream> compositeStream;
if (isDepthCompositeStream) {
compositeStream = new camera3::DepthCompositeStream(mDevice, getRemoteCallback());
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 84b5aa4..396104c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1526,7 +1526,8 @@
vsyncTime.deadlineTimestamp >= currentTime &&
((!cameraDisplayInSync && vsyncTime.expectedPresentationTime > minPresentT) ||
(cameraDisplayInSync && vsyncTime.expectedPresentationTime >
- mLastPresentTime + minInterval + biasForShortDelay * kTimelineThresholdNs))) {
+ mLastPresentTime + minInterval +
+ static_cast<nsecs_t>(biasForShortDelay * kTimelineThresholdNs)))) {
expectedPresentT = vsyncTime.expectedPresentationTime;
minDiff = std::abs(vsyncTime.expectedPresentationTime - idealPresentT);
}