Merge "libcameraservice: Provide flag for overriding camera output to portrait."
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index c0b0052..2869669 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -74,6 +74,7 @@
ACAMERA_HEIC_INFO,
ACAMERA_AUTOMOTIVE,
ACAMERA_AUTOMOTIVE_LENS,
+ ACAMERA_EXTENSION,
ACAMERA_SECTION_COUNT,
ACAMERA_VENDOR = 0x8000
@@ -119,6 +120,7 @@
ACAMERA_HEIC_INFO_START = ACAMERA_HEIC_INFO << 16,
ACAMERA_AUTOMOTIVE_START = ACAMERA_AUTOMOTIVE << 16,
ACAMERA_AUTOMOTIVE_LENS_START = ACAMERA_AUTOMOTIVE_LENS << 16,
+ ACAMERA_EXTENSION_START = ACAMERA_EXTENSION << 16,
ACAMERA_VENDOR_START = ACAMERA_VENDOR << 16
} acamera_metadata_section_start_t;
@@ -10989,6 +10991,7 @@
+
__END_DECLS
#endif /* _NDK_CAMERA_METADATA_TAGS_H */
diff --git a/drm/libmediadrm/CryptoHalAidl.cpp b/drm/libmediadrm/CryptoHalAidl.cpp
index 8b9d1de..f01ecb3 100644
--- a/drm/libmediadrm/CryptoHalAidl.cpp
+++ b/drm/libmediadrm/CryptoHalAidl.cpp
@@ -41,7 +41,7 @@
using ::aidl::android::hardware::drm::DecryptArgs;
using ::android::sp;
-using ::android::DrmUtils::statusAidlToStatusT;
+using ::android::DrmUtils::statusAidlToDrmStatus;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_memory;
@@ -268,7 +268,7 @@
}
auto err = mPlugin->setMediaDrmSession(toStdVec(sessionId));
- return statusAidlToStatusT(err);
+ return statusAidlToDrmStatus(err);
}
ssize_t CryptoHalAidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
@@ -352,7 +352,7 @@
int32_t result = 0;
::ndk::ScopedAStatus statusAidl = mPlugin->decrypt(args, &result);
- err = statusAidlToStatusT(statusAidl);
+ err = statusAidlToDrmStatus(statusAidl);
std::string msgStr(statusAidl.getMessage());
if (errorDetailMsg != nullptr) {
*errorDetailMsg = toString8(msgStr);
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index c394d5a..754f066 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -20,6 +20,7 @@
#include <mediadrm/DrmHal.h>
#include <mediadrm/DrmHalAidl.h>
#include <mediadrm/DrmHalHidl.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/DrmUtils.h>
namespace android {
@@ -31,49 +32,49 @@
DrmHal::~DrmHal() {}
-status_t DrmHal::initCheck() const {
- if (mDrmHalAidl->initCheck() == OK || mDrmHalHidl->initCheck() == OK) return OK;
- if (mDrmHalAidl->initCheck() == NO_INIT || mDrmHalHidl->initCheck() == NO_INIT) return NO_INIT;
+DrmStatus DrmHal::initCheck() const {
+ if (mDrmHalAidl->initCheck() == OK || mDrmHalHidl->initCheck() == OK) return DrmStatus(OK);
+ if (mDrmHalAidl->initCheck() == NO_INIT || mDrmHalHidl->initCheck() == NO_INIT)
+ return DrmStatus(NO_INIT);
return mDrmHalHidl->initCheck();
}
-status_t DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel securityLevel, bool* result) {
- status_t statusResult;
- statusResult = mDrmHalAidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
+DrmStatus DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result) {
+ DrmStatus statusResult =
+ mDrmHalAidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
if (*result) return statusResult;
return mDrmHalHidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
}
-status_t DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
- status_t statusResult;
- statusResult = mDrmHalAidl->createPlugin(uuid, appPackageName);
- if (statusResult != OK) return mDrmHalHidl->createPlugin(uuid, appPackageName);
- return statusResult;
+DrmStatus DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+ return mDrmHalAidl->createPlugin(uuid, appPackageName) == OK
+ ? DrmStatus(OK)
+ : mDrmHalHidl->createPlugin(uuid, appPackageName);
}
-status_t DrmHal::destroyPlugin() {
- status_t statusResult = mDrmHalAidl->destroyPlugin();
- status_t statusResultHidl = mDrmHalHidl->destroyPlugin();
+DrmStatus DrmHal::destroyPlugin() {
+ DrmStatus statusResult = mDrmHalAidl->destroyPlugin();
+ DrmStatus statusResultHidl = mDrmHalHidl->destroyPlugin();
if (statusResult != OK) return statusResult;
return statusResultHidl;
}
-status_t DrmHal::openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHal::openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t>& sessionId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->openSession(securityLevel, sessionId);
return mDrmHalHidl->openSession(securityLevel, sessionId);
}
-status_t DrmHal::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHal::closeSession(Vector<uint8_t> const& sessionId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->closeSession(sessionId);
return mDrmHalHidl->closeSession(sessionId);
}
-status_t DrmHal::getKeyRequest(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& initData,
- String8 const& mimeType, DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const& optionalParameters,
- Vector<uint8_t>& request, String8& defaultUrl,
- DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHal::getKeyRequest(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& initData,
+ String8 const& mimeType, DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->getKeyRequest(sessionId, initData, mimeType, keyType,
optionalParameters, request, defaultUrl, keyRequestType);
@@ -81,212 +82,212 @@
request, defaultUrl, keyRequestType);
}
-status_t DrmHal::provideKeyResponse(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& response, Vector<uint8_t>& keySetId) {
+DrmStatus DrmHal::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response, Vector<uint8_t>& keySetId) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->provideKeyResponse(sessionId, response, keySetId);
return mDrmHalHidl->provideKeyResponse(sessionId, response, keySetId);
}
-status_t DrmHal::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::removeKeys(Vector<uint8_t> const& keySetId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeKeys(keySetId);
return mDrmHalHidl->removeKeys(keySetId);
}
-status_t DrmHal::restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->restoreKeys(sessionId, keySetId);
return mDrmHalHidl->restoreKeys(sessionId, keySetId);
}
-status_t DrmHal::queryKeyStatus(Vector<uint8_t> const& sessionId,
- KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHal::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->queryKeyStatus(sessionId, infoMap);
return mDrmHalHidl->queryKeyStatus(sessionId, infoMap);
}
-status_t DrmHal::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
- Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHal::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
return mDrmHalHidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
}
-status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const& response,
- Vector<uint8_t>& certificate,
- Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHal::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->provideProvisionResponse(response, certificate, wrappedKey);
return mDrmHalHidl->provideProvisionResponse(response, certificate, wrappedKey);
}
-status_t DrmHal::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHal::getSecureStops(List<Vector<uint8_t>>& secureStops) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStops(secureStops);
return mDrmHalHidl->getSecureStops(secureStops);
}
-status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHal::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStopIds(secureStopIds);
return mDrmHalHidl->getSecureStopIds(secureStopIds);
}
-status_t DrmHal::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHal::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStop(ssid, secureStop);
return mDrmHalHidl->getSecureStop(ssid, secureStop);
}
-status_t DrmHal::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHal::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->releaseSecureStops(ssRelease);
return mDrmHalHidl->releaseSecureStops(ssRelease);
}
-status_t DrmHal::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHal::removeSecureStop(Vector<uint8_t> const& ssid) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeSecureStop(ssid);
return mDrmHalHidl->removeSecureStop(ssid);
}
-status_t DrmHal::removeAllSecureStops() {
+DrmStatus DrmHal::removeAllSecureStops() {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeAllSecureStops();
return mDrmHalHidl->removeAllSecureStops();
}
-status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
- DrmPlugin::HdcpLevel* maxLevel) const {
+DrmStatus DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getHdcpLevels(connectedLevel, maxLevel);
return mDrmHalHidl->getHdcpLevels(connectedLevel, maxLevel);
}
-status_t DrmHal::getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const {
+DrmStatus DrmHal::getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->getNumberOfSessions(currentSessions, maxSessions);
return mDrmHalHidl->getNumberOfSessions(currentSessions, maxSessions);
}
-status_t DrmHal::getSecurityLevel(Vector<uint8_t> const& sessionId,
- DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHal::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecurityLevel(sessionId, level);
return mDrmHalHidl->getSecurityLevel(sessionId, level);
}
-status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getOfflineLicenseKeySetIds(keySetIds);
return mDrmHalHidl->getOfflineLicenseKeySetIds(keySetIds);
}
-status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeOfflineLicense(keySetId);
return mDrmHalHidl->removeOfflineLicense(keySetId);
}
-status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
- DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHal::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->getOfflineLicenseState(keySetId, licenseState);
return mDrmHalHidl->getOfflineLicenseState(keySetId, licenseState);
}
-status_t DrmHal::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHal::getPropertyString(String8 const& name, String8& value) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyString(name, value);
return mDrmHalHidl->getPropertyString(name, value);
}
-status_t DrmHal::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHal::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyByteArray(name, value);
return mDrmHalHidl->getPropertyByteArray(name, value);
}
-status_t DrmHal::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHal::setPropertyString(String8 const& name, String8 const& value) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyString(name, value);
return mDrmHalHidl->setPropertyString(name, value);
}
-status_t DrmHal::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHal::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyByteArray(name, value);
return mDrmHalHidl->setPropertyByteArray(name, value);
}
-status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHal::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getMetrics(consumer);
return mDrmHalHidl->getMetrics(consumer);
}
-status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHal::setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->setCipherAlgorithm(sessionId, algorithm);
return mDrmHalHidl->setCipherAlgorithm(sessionId, algorithm);
}
-status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHal::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setMacAlgorithm(sessionId, algorithm);
return mDrmHalHidl->setMacAlgorithm(sessionId, algorithm);
}
-status_t DrmHal::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHal::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->encrypt(sessionId, keyId, input, iv, output);
return mDrmHalHidl->encrypt(sessionId, keyId, input, iv, output);
}
-status_t DrmHal::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHal::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->decrypt(sessionId, keyId, input, iv, output);
return mDrmHalHidl->decrypt(sessionId, keyId, input, iv, output);
}
-status_t DrmHal::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHal::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->sign(sessionId, keyId, message, signature);
return mDrmHalHidl->sign(sessionId, keyId, message, signature);
}
-status_t DrmHal::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
- bool& match) {
+DrmStatus DrmHal::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->verify(sessionId, keyId, message, signature, match);
return mDrmHalHidl->verify(sessionId, keyId, message, signature, match);
}
-status_t DrmHal::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
- Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
- Vector<uint8_t>& signature) {
+DrmStatus DrmHal::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
return mDrmHalHidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
}
-status_t DrmHal::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHal::setListener(const sp<IDrmClient>& listener) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setListener(listener);
return mDrmHalHidl->setListener(listener);
}
-status_t DrmHal::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHal::requiresSecureDecoder(const char* mime, bool* required) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->requiresSecureDecoder(mime, required);
return mDrmHalHidl->requiresSecureDecoder(mime, required);
}
-status_t DrmHal::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
- bool* required) const {
+DrmStatus DrmHal::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
if (mDrmHalAidl->initCheck() == OK)
return mDrmHalAidl->requiresSecureDecoder(mime, securityLevel, required);
return mDrmHalHidl->requiresSecureDecoder(mime, securityLevel, required);
}
-status_t DrmHal::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHal::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPlaybackId(sessionId, playbackId);
return mDrmHalHidl->setPlaybackId(sessionId, playbackId);
}
-status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getLogMessages(logs);
return mDrmHalHidl->getLogMessages(logs);
}
-status_t DrmHal::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHal::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
status_t statusResult;
statusResult = mDrmHalAidl->getSupportedSchemes(schemes);
if (statusResult == OK) return statusResult;
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
index bdd83e9..c369529 100644
--- a/drm/libmediadrm/DrmHalAidl.cpp
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -29,9 +29,9 @@
#include <media/stagefright/foundation/hexdump.h>
#include <mediadrm/DrmHalAidl.h>
#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/DrmUtils.h>
-using ::android::DrmUtils::statusAidlToStatusT;
using ::aidl::android::hardware::drm::CryptoSchemes;
using ::aidl::android::hardware::drm::DrmMetricNamedValue;
using ::aidl::android::hardware::drm::DrmMetricValue;
@@ -55,6 +55,7 @@
using ::aidl::android::hardware::drm::Status;
using ::aidl::android::hardware::drm::SupportedContentType;
using ::aidl::android::hardware::drm::Uuid;
+using ::android::DrmUtils::statusAidlToDrmStatus;
using DrmMetricGroupAidl = ::aidl::android::hardware::drm::DrmMetricGroup;
using DrmMetricGroupHidl = ::android::hardware::drm::V1_1::DrmMetricGroup;
using DrmMetricAidl = ::aidl::android::hardware::drm::DrmMetric;
@@ -396,19 +397,19 @@
mFactories(DrmUtils::makeDrmFactoriesAidl()),
mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
-status_t DrmHalAidl::initCheck() const {
- return mInitCheck;
+DrmStatus DrmHalAidl::initCheck() const {
+ return DrmStatus(mInitCheck);
}
DrmHalAidl::~DrmHalAidl() {}
-status_t DrmHalAidl::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHalAidl::setListener(const sp<IDrmClient>& listener) {
mListener->setListener(listener);
- return NO_ERROR;
+ return DrmStatus(NO_ERROR);
}
-status_t DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel level, bool* isSupported) {
+DrmStatus DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported) {
Mutex::Autolock autoLock(mLock);
*isSupported = false;
Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
@@ -438,9 +439,9 @@
// isCryptoSchemeSupported(uuid, mimeType)
*isSupported = contentTypes.count(mimeTypeStr);
}
- return OK;
+ return DrmStatus(OK);
} else if (mimeType == "") {
- return BAD_VALUE;
+ return DrmStatus(BAD_VALUE);
}
auto ct = contentTypes[mimeTypeStr];
@@ -452,10 +453,10 @@
break;
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+DrmStatus DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
Mutex::Autolock autoLock(mLock);
Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
@@ -497,10 +498,10 @@
}
}
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
-status_t DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -510,14 +511,14 @@
return ERROR_DRM_CANNOT_HANDLE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
bool retry = true;
do {
std::vector<uint8_t> aSessionId;
::ndk::ScopedAStatus status = mPlugin->openSession(aSecurityLevel, &aSessionId);
if (status.isOk()) sessionId = toVector(aSessionId);
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
mLock.unlock();
@@ -545,13 +546,13 @@
return err;
}
-status_t DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
::ndk::ScopedAStatus status = mPlugin->closeSession(sessionIdAidl);
- status_t response = statusAidlToStatusT(status);
+ DrmStatus response = statusAidlToDrmStatus(status);
if (status.isOk()) {
DrmSessionManager::Instance()->removeSession(sessionId);
for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
@@ -568,12 +569,12 @@
return response;
}
-status_t DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& initData, String8 const& mimeType,
- DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const& optionalParameters,
- Vector<uint8_t>& request, String8& defaultUrl,
- DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
@@ -592,7 +593,7 @@
return BAD_VALUE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
std::vector<uint8_t> initDataAidl = toStdVec(initData);
@@ -607,21 +608,21 @@
*keyRequestType = toKeyRequestType(keyRequest.requestType);
}
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
keyRequestTimer.SetAttribute(err);
return err;
}
-status_t DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& response,
- Vector<uint8_t>& keySetId) {
+DrmStatus DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
std::vector<uint8_t> responseAidl = toStdVec(response);
@@ -630,21 +631,21 @@
mPlugin->provideKeyResponse(sessionIdAidl, responseAidl, &keySetIdsAidl);
if (status.isOk()) keySetId = toVector(keySetIdsAidl.keySetId);
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
keyResponseTimer.SetAttribute(err);
return err;
}
-status_t DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
::ndk::ScopedAStatus status = mPlugin->removeKeys(toStdVec(keySetId));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -653,11 +654,11 @@
KeySetId keySetIdsAidl;
keySetIdsAidl.keySetId = toStdVec(keySetId);
::ndk::ScopedAStatus status = mPlugin->restoreKeys(toStdVec(sessionId), keySetIdsAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
- KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -668,15 +669,15 @@
infoMap = toKeyedVector(infoMapAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
- Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
ProvisionRequest requestAidl;
::ndk::ScopedAStatus status = mPlugin->getProvisionRequest(
@@ -685,29 +686,29 @@
request = toVector(requestAidl.request);
defaultUrl = toString8(requestAidl.defaultUrl);
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
mMetrics.mGetProvisionRequestCounter.Increment(err);
return err;
}
-status_t DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response,
- Vector<uint8_t>& certificate,
- Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
ProvideProvisionResponseResult result;
::ndk::ScopedAStatus status = mPlugin->provideProvisionResponse(toStdVec(response), &result);
certificate = toVector(result.certificate);
wrappedKey = toVector(result.wrappedKey);
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
mMetrics.mProvideProvisionResponseCounter.Increment(err);
return err;
}
-status_t DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -716,10 +717,10 @@
secureStops = toSecureStops(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -728,10 +729,10 @@
secureStopIds = toSecureStopIds(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -743,10 +744,10 @@
secureStop = toVector(result.opaqueData);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -754,10 +755,10 @@
ssId.opaqueData = toStdVec(ssRelease);
::ndk::ScopedAStatus status = mPlugin->releaseSecureStops(ssId);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -765,19 +766,19 @@
SecureStopId ssidAidl;
ssidAidl.secureStopId = toStdVec(ssid);
::ndk::ScopedAStatus status = mPlugin->removeSecureStop(ssidAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::removeAllSecureStops() {
+DrmStatus DrmHalAidl::removeAllSecureStops() {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
::ndk::ScopedAStatus status = mPlugin->releaseAllSecureStops();
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
- DrmPlugin::HdcpLevel* max) const {
+DrmStatus DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+ DrmPlugin::HdcpLevel* max) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -794,10 +795,10 @@
*connected = toHdcpLevel(lvlsAidl.connectedLevel);
*max = toHdcpLevel(lvlsAidl.maxLevel);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+DrmStatus DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -814,11 +815,11 @@
*open = result.currentSessions;
*max = result.maxSessions;
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
- DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -833,10 +834,10 @@
*level = toSecurityLevel(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -845,21 +846,21 @@
keySetIds = toKeySetIds(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
KeySetId keySetIdAidl;
keySetIdAidl.keySetId = toStdVec(keySetId);
::ndk::ScopedAStatus status = mPlugin->removeOfflineLicense(keySetIdAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
- DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -873,15 +874,15 @@
*licenseState = toOfflineLicenseState(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHalAidl::getPropertyString(String8 const& name, String8& value) const {
Mutex::Autolock autoLock(mLock);
- return getPropertyStringInternal(name, value);
+ return DrmStatus(getPropertyStringInternal(name, value));
}
-status_t DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+DrmStatus DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
INIT_CHECK();
@@ -891,52 +892,53 @@
value = toString8(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
Mutex::Autolock autoLock(mLock);
- return getPropertyByteArrayInternal(name, value);
+ return DrmStatus(getPropertyByteArrayInternal(name, value));
}
-status_t DrmHalAidl::getPropertyByteArrayInternal(String8 const& name,
- Vector<uint8_t>& value) const {
+DrmStatus DrmHalAidl::getPropertyByteArrayInternal(String8 const& name,
+ Vector<uint8_t>& value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
std::vector<uint8_t> result;
::ndk::ScopedAStatus status = mPlugin->getPropertyByteArray(toStdString(name), &result);
value = toVector(result);
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
if (name == kPropertyDeviceUniqueId) {
mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
}
return err;
}
-status_t DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
::ndk::ScopedAStatus status = mPlugin->setPropertyString(toStdString(name), toStdString(value));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHalAidl::setPropertyByteArray(String8 const& name,
+ Vector<uint8_t> const& value) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
::ndk::ScopedAStatus status = mPlugin->setPropertyByteArray(toStdString(name), toStdVec(value));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
if (consumer == nullptr) {
- return UNEXPECTED_NULL;
+ return DrmStatus(UNEXPECTED_NULL);
}
consumer->consumeFrameworkMetrics(mMetrics);
@@ -957,7 +959,7 @@
vendor += description;
hidl_vec<DrmMetricGroupHidl> pluginMetrics;
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
std::vector<DrmMetricGroupAidl> result;
::ndk::ScopedAStatus status = mPlugin->getMetrics(&result);
@@ -967,13 +969,13 @@
consumer->consumeHidlMetrics(vendor, pluginMetrics);
}
- err = statusAidlToStatusT(status);
+ err = statusAidlToDrmStatus(status);
return err;
}
-status_t DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
- String8 const& algorithm) {
+DrmStatus DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -981,10 +983,10 @@
::ndk::ScopedAStatus status =
mPlugin->setCipherAlgorithm(toStdVec(sessionId), toStdString(algorithm));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -992,12 +994,12 @@
::ndk::ScopedAStatus status =
mPlugin->setMacAlgorithm(toStdVec(sessionId), toStdString(algorithm));
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1009,12 +1011,12 @@
output = toVector(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1026,11 +1028,11 @@
output = toVector(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1042,12 +1044,12 @@
signature = toVector(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
- bool& match) {
+DrmStatus DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1056,12 +1058,12 @@
::ndk::ScopedAStatus status = mPlugin->verify(toStdVec(sessionId), toStdVec(keyId),
toStdVec(message), toStdVec(signature), &match);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
- Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
- Vector<uint8_t>& signature) {
+DrmStatus DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1074,10 +1076,10 @@
signature = toVector(result);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1086,14 +1088,15 @@
mPlugin->requiresSecureDecoder(mimeAidl, SecurityLevel::DEFAULT, required);
if (!status.isOk()) {
DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalAidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
- bool* required) const {
+DrmStatus DrmHalAidl::requiresSecureDecoder(const char* mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1101,7 +1104,7 @@
std::string mimeAidl(mime);
::ndk::ScopedAStatus status = mPlugin->requiresSecureDecoder(mimeAidl, aLevel, required);
- status_t err = statusAidlToStatusT(status);
+ DrmStatus err = statusAidlToDrmStatus(status);
if (!status.isOk()) {
DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
}
@@ -1109,17 +1112,17 @@
return err;
}
-status_t DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
std::string playbackIdAidl(playbackId);
::ndk::ScopedAStatus status = mPlugin->setPlaybackId(toStdVec(sessionId), playbackIdAidl);
- return statusAidlToStatusT(status);
+ return statusAidlToDrmStatus(status);
}
-status_t DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
Mutex::Autolock autoLock(mLock);
- return DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs);
+ return DrmStatus(DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs));
}
void DrmHalAidl::closeOpenSessions() {
@@ -1189,7 +1192,7 @@
return serializedMetrics;
}
-status_t DrmHalAidl::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHalAidl::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
Mutex::Autolock autoLock(mLock);
if (mFactories.empty()) return UNKNOWN_ERROR;
@@ -1205,7 +1208,7 @@
}
}
- return OK;
+ return DrmStatus(OK);
}
void DrmHalAidl::cleanup() {
@@ -1225,9 +1228,9 @@
mPlugin.reset();
}
-status_t DrmHalAidl::destroyPlugin() {
+DrmStatus DrmHalAidl::destroyPlugin() {
cleanup();
- return OK;
+ return DrmStatus(OK);
}
::ndk::ScopedAStatus DrmHalAidl::onEvent(EventTypeAidl eventTypeAidl,
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
index 055f20a..2e0bfee 100644
--- a/drm/libmediadrm/DrmHalHidl.cpp
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -35,6 +35,7 @@
#include <mediadrm/DrmHalHidl.h>
#include <mediadrm/DrmSessionClientInterface.h>
#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrmMetricsConsumer.h>
#include <utils/Log.h>
@@ -368,14 +369,14 @@
return plugin;
}
-status_t DrmHalHidl::initCheck() const {
- return mInitCheck;
+DrmStatus DrmHalHidl::initCheck() const {
+ return DrmStatus(mInitCheck);
}
-status_t DrmHalHidl::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHalHidl::setListener(const sp<IDrmClient>& listener) {
Mutex::Autolock lock(mEventLock);
mListener = listener;
- return NO_ERROR;
+ return DrmStatus(NO_ERROR);
}
Return<void> DrmHalHidl::sendEvent(EventType hEventType, const hidl_vec<uint8_t>& sessionId,
@@ -502,10 +503,10 @@
return Void();
}
-status_t DrmHalHidl::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory>& factory,
- const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel level,
- bool* isSupported) {
+DrmStatus DrmHalHidl::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory>& factory,
+ const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level,
+ bool* isSupported) {
*isSupported = false;
// handle default value cases
@@ -517,23 +518,23 @@
// isCryptoSchemeSupported(uuid, mimeType)
*isSupported = factory->isContentTypeSupported(mimeType.string());
}
- return OK;
+ return DrmStatus(OK);
} else if (mimeType == "") {
- return BAD_VALUE;
+ return DrmStatus(BAD_VALUE);
}
sp<drm::V1_2::IDrmFactory> factoryV1_2 = drm::V1_2::IDrmFactory::castFrom(factory);
if (factoryV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
} else {
*isSupported = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
toHidlSecurityLevel(level));
- return OK;
+ return DrmStatus(OK);
}
}
-status_t DrmHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel level, bool* isSupported) {
+DrmStatus DrmHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported) {
Mutex::Autolock autoLock(mLock);
*isSupported = false;
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
@@ -541,10 +542,10 @@
return matchMimeTypeAndSecurityLevel(mFactories[i], uuid, mimeType, level, isSupported);
}
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+DrmStatus DrmHalHidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
Mutex::Autolock autoLock(mLock);
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
@@ -581,15 +582,15 @@
}
}
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
-status_t DrmHalHidl::destroyPlugin() {
+DrmStatus DrmHalHidl::destroyPlugin() {
cleanup();
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHalHidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -604,7 +605,7 @@
}
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
bool retry = true;
do {
hidl_vec<uint8_t> hSessionId;
@@ -657,7 +658,7 @@
return err;
}
-status_t DrmHalHidl::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHalHidl::closeSession(Vector<uint8_t> const& sessionId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -672,13 +673,13 @@
}
}
}
- status_t response = toStatusT(status);
+ DrmStatus response = toStatusT(status);
mMetrics.SetSessionEnd(sessionId);
mMetrics.mCloseSessionCounter.Increment(response);
return response;
}
mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
static DrmPlugin::KeyRequestType toKeyRequestType(KeyRequestType keyRequestType) {
@@ -712,12 +713,12 @@
}
}
-status_t DrmHalHidl::getKeyRequest(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& initData, String8 const& mimeType,
- DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const& optionalParameters,
- Vector<uint8_t>& request, String8& defaultUrl,
- DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHalHidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
@@ -738,7 +739,7 @@
::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult;
if (mPluginV1_2 != NULL) {
@@ -787,16 +788,16 @@
return err;
}
-status_t DrmHalHidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& response,
- Vector<uint8_t>& keySetId) {
+DrmStatus DrmHalHidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->provideKeyResponse(toHidlVec(sessionId), toHidlVec(response),
@@ -811,27 +812,27 @@
return err;
}
-status_t DrmHalHidl::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::removeKeys(Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::restoreKeys(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId), toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
- KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHalHidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -839,7 +840,7 @@
::KeyedVector hInfoMap;
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->queryKeyStatus(
toHidlVec(sessionId), [&](Status status, const hidl_vec<KeyValue>& map) {
@@ -849,15 +850,15 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? DrmStatus(err) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
- Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHalHidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult;
if (mPluginV1_2 != NULL) {
@@ -888,13 +889,13 @@
return err;
}
-status_t DrmHalHidl::provideProvisionResponse(Vector<uint8_t> const& response,
- Vector<uint8_t>& certificate,
- Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHalHidl::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->provideProvisionResponse(
toHidlVec(response), [&](Status status, const hidl_vec<uint8_t>& hCertificate,
@@ -911,11 +912,11 @@
return err;
}
-status_t DrmHalHidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHalHidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->getSecureStops([&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
@@ -925,10 +926,10 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHalHidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -939,7 +940,7 @@
return ERROR_DRM_CANNOT_HANDLE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPluginV1_1->getSecureStopIds(
[&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
@@ -949,14 +950,14 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHalHidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->getSecureStop(
toHidlVec(ssid), [&](Status status, const SecureStop& hSecureStop) {
@@ -966,10 +967,10 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHalHidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -981,10 +982,10 @@
} else {
status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
}
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHalHidl::removeSecureStop(Vector<uint8_t> const& ssid) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -996,10 +997,10 @@
}
Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::removeAllSecureStops() {
+DrmStatus DrmHalHidl::removeAllSecureStops() {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1009,18 +1010,18 @@
} else {
status = mPlugin->releaseAllSecureStops();
}
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
- DrmPlugin::HdcpLevel* max) const {
+DrmStatus DrmHalHidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+ DrmPlugin::HdcpLevel* max) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
if (connected == NULL || max == NULL) {
return BAD_VALUE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
*connected = DrmPlugin::kHdcpLevelUnknown;
*max = DrmPlugin::kHdcpLevelUnknown;
@@ -1046,26 +1047,26 @@
err = toStatusT(status);
});
} else {
- return ERROR_DRM_CANNOT_HANDLE;
+ return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
}
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+DrmStatus DrmHalHidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
if (open == NULL || max == NULL) {
return BAD_VALUE;
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
*open = 0;
*max = 0;
if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
+ return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
}
Return<void> hResult =
@@ -1077,21 +1078,21 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
- DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHalHidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
if (level == NULL) {
- return BAD_VALUE;
+ return DrmStatus(BAD_VALUE);
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
+ return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
}
*level = DrmPlugin::kSecurityLevelUnknown;
@@ -1104,21 +1105,21 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHalHidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
}
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
[&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
@@ -1128,38 +1129,38 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
}
Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
- DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHalHidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
- return mInitCheck;
+ return DrmStatus(mInitCheck);
}
if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
}
*licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPluginV1_2->getOfflineLicenseState(
toHidlVec(keySetId), [&](Status status, OfflineLicenseState hLicenseState) {
@@ -1169,20 +1170,20 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHalHidl::getPropertyString(String8 const& name, String8& value) const {
Mutex::Autolock autoLock(mLock);
return getPropertyStringInternal(name, value);
}
-status_t DrmHalHidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+DrmStatus DrmHalHidl::getPropertyStringInternal(String8 const& name, String8& value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->getPropertyString(
toHidlString(name), [&](Status status, const hidl_string& hValue) {
@@ -1192,21 +1193,21 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHalHidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
Mutex::Autolock autoLock(mLock);
return getPropertyByteArrayInternal(name, value);
}
-status_t DrmHalHidl::getPropertyByteArrayInternal(String8 const& name,
- Vector<uint8_t>& value) const {
+DrmStatus DrmHalHidl::getPropertyByteArrayInternal(String8 const& name,
+ Vector<uint8_t>& value) const {
// This function is internal to the class and should only be called while
// mLock is already held.
INIT_CHECK();
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->getPropertyByteArray(
toHidlString(name), [&](Status status, const hidl_vec<uint8_t>& hValue) {
@@ -1223,25 +1224,26 @@
return err;
}
-status_t DrmHalHidl::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHalHidl::setPropertyString(String8 const& name, String8 const& value) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
Return<Status> status = mPlugin->setPropertyString(toHidlString(name), toHidlString(value));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHalHidl::setPropertyByteArray(String8 const& name,
+ Vector<uint8_t> const& value) const {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name), toHidlVec(value));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHalHidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
if (consumer == nullptr) {
- return UNEXPECTED_NULL;
+ return DrmStatus(UNEXPECTED_NULL);
}
consumer->consumeFrameworkMetrics(mMetrics);
@@ -1262,7 +1264,7 @@
vendor += description;
hidl_vec<DrmMetricGroup> pluginMetrics;
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> status =
mPluginV1_1->getMetrics([&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
@@ -1273,14 +1275,14 @@
}
err = toStatusT(status);
});
- return status.isOk() ? err : DEAD_OBJECT;
+ return status.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
- String8 const& algorithm) {
+DrmStatus DrmHalHidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
@@ -1288,28 +1290,28 @@
Return<Status> status =
mPlugin->setCipherAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHalHidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHalHidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->encrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
@@ -1320,18 +1322,18 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output) {
+DrmStatus DrmHalHidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->decrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
@@ -1342,17 +1344,17 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHalHidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->sign(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
[&](Status status, const hidl_vec<uint8_t>& hSignature) {
@@ -1362,18 +1364,18 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
- bool& match) {
+DrmStatus DrmHalHidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult =
mPlugin->verify(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
@@ -1386,18 +1388,18 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
- Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
- Vector<uint8_t>& signature) {
+DrmStatus DrmHalHidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
DrmSessionManager::Instance()->useSession(sessionId);
- status_t err = UNKNOWN_ERROR;
+ DrmStatus err = UNKNOWN_ERROR;
Return<void> hResult = mPlugin->signRSA(
toHidlVec(sessionId), toHidlString(algorithm), toHidlVec(message),
@@ -1408,7 +1410,7 @@
err = toStatusT(status);
});
- return hResult.isOk() ? err : DEAD_OBJECT;
+ return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
}
std::string DrmHalHidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
@@ -1467,55 +1469,56 @@
return metricsString;
}
-status_t DrmHalHidl::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHalHidl::requiresSecureDecoder(const char* mime, bool* required) const {
Mutex::Autolock autoLock(mLock);
if (mPluginV1_4 == NULL) {
- return false;
+ return DrmStatus(false);
}
auto hResult = mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
if (!hResult.isOk()) {
DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
if (required) {
*required = hResult;
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
- bool* required) const {
+DrmStatus DrmHalHidl::requiresSecureDecoder(const char* mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
Mutex::Autolock autoLock(mLock);
if (mPluginV1_4 == NULL) {
- return false;
+ return DrmStatus(false);
}
auto hLevel = toHidlSecurityLevel(securityLevel);
auto hResult = mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
if (!hResult.isOk()) {
DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
- return DEAD_OBJECT;
+ return DrmStatus(DEAD_OBJECT);
}
if (required) {
*required = hResult;
}
- return OK;
+ return DrmStatus(OK);
}
-status_t DrmHalHidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHalHidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
Mutex::Autolock autoLock(mLock);
if (mPluginV1_4 == NULL) {
- return ERROR_UNSUPPORTED;
+ return DrmStatus(ERROR_UNSUPPORTED);
}
auto err = mPluginV1_4->setPlaybackId(toHidlVec(sessionId), hidl_string(playbackId));
- return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
+ return err.isOk() ? DrmStatus(toStatusT(err)) : DrmStatus(DEAD_OBJECT);
}
-status_t DrmHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
Mutex::Autolock autoLock(mLock);
- return DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs);
+ return DrmStatus(DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs));
}
-status_t DrmHalHidl::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHalHidl::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
Mutex::Autolock autoLock(mLock);
for (auto &factory : mFactories) {
sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
@@ -1531,7 +1534,7 @@
});
}
- return OK;
+ return DrmStatus(OK);
}
} // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index eab597b..16e5fe1 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -15,6 +15,7 @@
*/
#include <mediadrm/IDrm.h>
+#include <mediadrm/DrmStatus.h>
#ifndef DRM_HAL_H_
#define DRM_HAL_H_
@@ -24,100 +25,99 @@
struct DrmHal : public IDrm {
DrmHal();
virtual ~DrmHal();
- virtual status_t initCheck() const;
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel securityLevel,
- bool *result);
- virtual status_t createPlugin(const uint8_t uuid[16],
- const String8 &appPackageName);
- virtual status_t destroyPlugin();
- virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+ virtual DrmStatus initCheck() const;
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result);
+ virtual DrmStatus createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName);
+ virtual DrmStatus destroyPlugin();
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
Vector<uint8_t> &sessionId);
- virtual status_t closeSession(Vector<uint8_t> const &sessionId);
- virtual status_t
+ virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId);
+ virtual DrmStatus
getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
String8 const &mimeType, DrmPlugin::KeyType keyType,
KeyedVector<String8, String8> const &optionalParameters,
Vector<uint8_t> &request, String8 &defaultUrl,
DrmPlugin::KeyRequestType *keyRequestType);
- virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response,
- Vector<uint8_t> &keySetId);
- virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
- virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId);
- virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const;
- virtual status_t getProvisionRequest(String8 const &certType,
- String8 const &certAuthority,
- Vector<uint8_t> &request,
- String8 &defaultUrl);
- virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey);
- virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
- virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
- virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
- virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
- virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
- virtual status_t removeAllSecureStops();
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId);
+ virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId);
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId);
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const;
+ virtual DrmStatus getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaultUrl);
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey);
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops);
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease);
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid);
+ virtual DrmStatus removeAllSecureStops();
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
DrmPlugin::HdcpLevel *maxLevel) const;
- virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+ virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
uint32_t *maxSessions) const;
- virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
DrmPlugin::SecurityLevel *level) const;
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
- virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId);
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
DrmPlugin::OfflineLicenseState *licenseState) const;
- virtual status_t getPropertyString(String8 const &name, String8 &value) const;
- virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value) const;
- virtual status_t setPropertyString(String8 const &name,
- String8 const &value ) const;
- virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value) const;
- virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
- virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
- virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus getPropertyString(String8 const &name, String8 &value) const;
+ virtual DrmStatus getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value) const;
+ virtual DrmStatus setPropertyString(String8 const &name,
+ String8 const &value ) const;
+ virtual DrmStatus setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value) const;
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+ virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+ virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+ virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature);
+ virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
- virtual status_t decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
- virtual status_t sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature);
- virtual status_t verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match);
- virtual status_t signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature);
- virtual status_t setListener(const sp<IDrmClient>& listener);
- virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
- virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
- bool *required) const;
- virtual status_t setPlaybackId(
+ Vector<uint8_t> const &signature,
+ bool &match);
+ virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature);
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+ virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const;
+ virtual DrmStatus requiresSecureDecoder(const char *mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const;
+ virtual DrmStatus setPlaybackId(
Vector<uint8_t> const &sessionId,
const char *playbackId);
- virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
- virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const;
private:
sp<IDrm> mDrmHalHidl;
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
index 0f51ce9..e0b8341 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
@@ -25,6 +25,7 @@
#include <mediadrm/DrmMetrics.h>
#include <mediadrm/DrmSessionManager.h>
#include <mediadrm/DrmHalListener.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/IDrm.h>
using IDrmPluginAidl = ::aidl::android::hardware::drm::IDrmPlugin;
@@ -38,74 +39,78 @@
struct DrmSessionClient;
DrmHalAidl();
virtual ~DrmHalAidl();
- virtual status_t initCheck() const;
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
- DrmPlugin::SecurityLevel securityLevel, bool* result);
- virtual status_t createPlugin(const uint8_t uuid[16], const String8& appPackageName);
- virtual status_t destroyPlugin();
- virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
- Vector<uint8_t>& sessionId);
- virtual status_t closeSession(Vector<uint8_t> const& sessionId);
- virtual status_t getKeyRequest(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& initData, String8 const& mimeType,
- DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const& optionalParameters,
- Vector<uint8_t>& request, String8& defaultUrl,
- DrmPlugin::KeyRequestType* keyRequestType);
- virtual status_t provideKeyResponse(Vector<uint8_t> const& sessionId,
- Vector<uint8_t> const& response, Vector<uint8_t>& keySetId);
- virtual status_t removeKeys(Vector<uint8_t> const& keySetId);
- virtual status_t restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId);
- virtual status_t queryKeyStatus(Vector<uint8_t> const& sessionId,
- KeyedVector<String8, String8>& infoMap) const;
- virtual status_t getProvisionRequest(String8 const& certType, String8 const& certAuthority,
- Vector<uint8_t>& request, String8& defaultUrl);
- virtual status_t provideProvisionResponse(Vector<uint8_t> const& response,
- Vector<uint8_t>& certificate,
- Vector<uint8_t>& wrappedKey);
- virtual status_t getSecureStops(List<Vector<uint8_t>>& secureStops);
- virtual status_t getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
- virtual status_t getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
- virtual status_t releaseSecureStops(Vector<uint8_t> const& ssRelease);
- virtual status_t removeSecureStop(Vector<uint8_t> const& ssid);
- virtual status_t removeAllSecureStops();
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
- DrmPlugin::HdcpLevel* maxLevel) const;
- virtual status_t getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
- virtual status_t getSecurityLevel(Vector<uint8_t> const& sessionId,
- DrmPlugin::SecurityLevel* level) const;
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
- virtual status_t removeOfflineLicense(Vector<uint8_t> const& keySetId);
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const& keySetId,
- DrmPlugin::OfflineLicenseState* licenseState) const;
- virtual status_t getPropertyString(String8 const& name, String8& value) const;
- virtual status_t getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
- virtual status_t setPropertyString(String8 const& name, String8 const& value) const;
- virtual status_t setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
- virtual status_t getMetrics(const sp<IDrmMetricsConsumer>& consumer);
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
- virtual status_t setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
- virtual status_t encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output);
- virtual status_t decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
- Vector<uint8_t>& output);
- virtual status_t sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t>& signature);
- virtual status_t verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
- Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
- bool& match);
- virtual status_t signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
- Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
- Vector<uint8_t>& signature);
- virtual status_t setListener(const sp<IDrmClient>& listener);
- virtual status_t requiresSecureDecoder(const char* mime, bool* required) const;
- virtual status_t requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
- bool* required) const;
- virtual status_t setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
- virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
- virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+ virtual DrmStatus initCheck() const;
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result);
+ virtual DrmStatus createPlugin(const uint8_t uuid[16], const String8& appPackageName);
+ virtual DrmStatus destroyPlugin();
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
+ Vector<uint8_t>& sessionId);
+ virtual DrmStatus closeSession(Vector<uint8_t> const& sessionId);
+ virtual DrmStatus getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType);
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId);
+ virtual DrmStatus removeKeys(Vector<uint8_t> const& keySetId);
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId);
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const;
+ virtual DrmStatus getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl);
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey);
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>>& secureStops);
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const& ssRelease);
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const& ssid);
+ virtual DrmStatus removeAllSecureStops();
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const;
+ virtual DrmStatus getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const;
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const& keySetId);
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const;
+ virtual DrmStatus getPropertyString(String8 const& name, String8& value) const;
+ virtual DrmStatus getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
+ virtual DrmStatus setPropertyString(String8 const& name, String8 const& value) const;
+ virtual DrmStatus setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer>& consumer);
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm);
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+ virtual DrmStatus encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+ virtual DrmStatus decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+ virtual DrmStatus sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature);
+ virtual DrmStatus verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match);
+ virtual DrmStatus signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature);
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+ virtual DrmStatus requiresSecureDecoder(const char* mime, bool* required) const;
+ virtual DrmStatus requiresSecureDecoder(const char* mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const;
+ virtual DrmStatus setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t>& schemes) const;
::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
const std::vector<uint8_t>& in_sessionId,
@@ -128,8 +133,8 @@
void closeOpenSessions();
std::string reportPluginMetrics() const;
std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
- status_t getPropertyStringInternal(String8 const& name, String8& value) const;
- status_t getPropertyByteArrayInternal(String8 const& name, Vector<uint8_t>& value) const;
+ DrmStatus getPropertyStringInternal(String8 const& name, String8& value) const;
+ DrmStatus getPropertyByteArrayInternal(String8 const& name, Vector<uint8_t>& value) const;
DISALLOW_EVIL_CONSTRUCTORS(DrmHalAidl);
};
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
index 11f0608..45764a1 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
@@ -26,6 +26,7 @@
#include <media/drm/DrmAPI.h>
#include <mediadrm/DrmMetrics.h>
#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/IDrm.h>
#include <mediadrm/IDrmClient.h>
#include <mediadrm/IDrmMetricsConsumer.h>
@@ -63,24 +64,22 @@
DrmHalHidl();
virtual ~DrmHalHidl();
- virtual status_t initCheck() const;
+ virtual DrmStatus initCheck() const;
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8& mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported);
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported);
- virtual status_t createPlugin(const uint8_t uuid[16],
+ virtual DrmStatus createPlugin(const uint8_t uuid[16],
const String8 &appPackageName);
- virtual status_t destroyPlugin();
+ virtual DrmStatus destroyPlugin();
- virtual status_t openSession(DrmPlugin::SecurityLevel level,
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel level,
Vector<uint8_t> &sessionId);
- virtual status_t closeSession(Vector<uint8_t> const &sessionId);
+ virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId);
- virtual status_t
+ virtual DrmStatus
getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
String8 const &mimeType, DrmPlugin::KeyType keyType,
@@ -88,103 +87,104 @@
Vector<uint8_t> &request, String8 &defaultUrl,
DrmPlugin::KeyRequestType *keyRequestType);
- virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response,
- Vector<uint8_t> &keySetId);
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId);
- virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
+ virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId);
- virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId);
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId);
- virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const;
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const;
- virtual status_t getProvisionRequest(String8 const &certType,
- String8 const &certAuthority,
- Vector<uint8_t> &request,
- String8 &defaultUrl);
+ virtual DrmStatus getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaultUrl);
- virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey);
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey);
- virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
- virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
- virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops);
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
- virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
- virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
- virtual status_t removeAllSecureStops();
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease);
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid);
+ virtual DrmStatus removeAllSecureStops();
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
DrmPlugin::HdcpLevel *maxLevel) const;
- virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+ virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
uint32_t *maxSessions) const;
- virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
DrmPlugin::SecurityLevel *level) const;
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
- virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId);
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
DrmPlugin::OfflineLicenseState *licenseState) const;
- virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
- virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value ) const;
- virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
- virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value ) const;
- virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+ virtual DrmStatus getPropertyString(String8 const &name, String8 &value ) const;
+ virtual DrmStatus getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value ) const;
+ virtual DrmStatus setPropertyString(String8 const &name, String8 const &value ) const;
+ virtual DrmStatus setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value ) const;
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer);
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
- virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
- virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature);
+
+ virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
-
- virtual status_t decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
-
- virtual status_t sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature);
-
- virtual status_t verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match);
-
- virtual status_t signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature);
+ Vector<uint8_t> const &signature,
+ bool &match);
- virtual status_t setListener(const sp<IDrmClient>& listener);
+ virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature);
- virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener);
- virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
- bool *required) const;
+ virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const;
- virtual status_t setPlaybackId(
+ virtual DrmStatus requiresSecureDecoder(const char *mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const;
+
+ virtual DrmStatus setPlaybackId(
Vector<uint8_t> const &sessionId,
const char *playbackId);
- virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
- virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const;
// Methods of IDrmPluginListener
Return<void> sendEvent(EventType eventType,
@@ -238,10 +238,10 @@
std::string reportPluginMetrics() const;
std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
- status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
- status_t getPropertyByteArrayInternal(String8 const &name,
+ DrmStatus getPropertyStringInternal(String8 const &name, String8 &value) const;
+ DrmStatus getPropertyByteArrayInternal(String8 const &name,
Vector<uint8_t> &value) const;
- status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
+ DrmStatus matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
const uint8_t uuid[16],
const String8 &mimeType,
DrmPlugin::SecurityLevel level,
diff --git a/drm/libmediadrm/include/mediadrm/DrmStatus.h b/drm/libmediadrm/include/mediadrm/DrmStatus.h
new file mode 100644
index 0000000..4f29a5a
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmStatus.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#ifndef DRM_STATUS_
+#define DRM_STATUS_
+#include <stdint.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+struct DrmStatus {
+ public:
+ DrmStatus(status_t status, int32_t cdmerr = 0, int32_t oemerr = 0)
+ : mStatus(status), mCdmErr(cdmerr), mOemErr(oemerr) {}
+ operator status_t() const { return mStatus; }
+ int32_t cdmErr() const { return mCdmErr; }
+ int32_t oemErr() const { return mOemErr; }
+ 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{};
+};
+
+} // namespace android
+
+#endif // DRM_STATUS_
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index ee2be6a..3dc7485 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -16,6 +16,7 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/drm/DrmAPI.h>
+#include <mediadrm/DrmStatus.h>
#include <mediadrm/IDrmClient.h>
#include <mediadrm/IDrmMetricsConsumer.h>
@@ -40,24 +41,23 @@
virtual ~IDrm() {}
- virtual status_t initCheck() const = 0;
+ virtual DrmStatus initCheck() const = 0;
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel securityLevel,
- bool *result) = 0;
+ virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool* result) = 0;
- virtual status_t createPlugin(const uint8_t uuid[16],
- const String8 &appPackageName) = 0;
+ virtual DrmStatus createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName) = 0;
- virtual status_t destroyPlugin() = 0;
+ virtual DrmStatus destroyPlugin() = 0;
- virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+ virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
Vector<uint8_t> &sessionId) = 0;
- virtual status_t closeSession(Vector<uint8_t> const &sessionId) = 0;
+ virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId) = 0;
- virtual status_t
+ virtual DrmStatus
getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
String8 const &mimeType, DrmPlugin::KeyType keyType,
@@ -65,107 +65,108 @@
Vector<uint8_t> &request, String8 &defaultUrl,
DrmPlugin::KeyRequestType *keyRequestType) = 0;
- virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response,
- Vector<uint8_t> &keySetId) = 0;
+ virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId) = 0;
- virtual status_t removeKeys(Vector<uint8_t> const &keySetId) = 0;
+ virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId) = 0;
- virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId) = 0;
+ virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId) = 0;
- virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const = 0;
+ virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const = 0;
- virtual status_t getProvisionRequest(String8 const &certType,
- String8 const &certAuthority,
- Vector<uint8_t> &request,
- String8 &defaulUrl) = 0;
+ virtual DrmStatus getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaultUrl) = 0;
- virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey) = 0;
+ virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey) = 0;
- virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops) = 0;
- virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) = 0;
- virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
+ virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops) = 0;
+ virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) = 0;
+ virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
- virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
- virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) = 0;
- virtual status_t removeAllSecureStops() = 0;
+ virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
+ virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid) = 0;
+ virtual DrmStatus removeAllSecureStops() = 0;
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+ virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
DrmPlugin::HdcpLevel *maxLevel)
const = 0;
- virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+ virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
uint32_t *maxSessions) const = 0;
- virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
DrmPlugin::SecurityLevel *level) const = 0;
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const = 0;
- virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) = 0;
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+ virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const = 0;
+ virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId) = 0;
+ virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
DrmPlugin::OfflineLicenseState *licenseState) const = 0;
- virtual status_t getPropertyString(String8 const &name, String8 &value) const = 0;
- virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value) const = 0;
- virtual status_t setPropertyString(String8 const &name,
- String8 const &value ) const = 0;
- virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value) const = 0;
+ virtual DrmStatus getPropertyString(String8 const &name, String8 &value) const = 0;
+ virtual DrmStatus getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value) const = 0;
+ virtual DrmStatus setPropertyString(String8 const &name,
+ String8 const &value ) const = 0;
+ virtual DrmStatus setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value) const = 0;
- virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer) = 0;
+ virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer) = 0;
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) = 0;
+ virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm) = 0;
- virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) = 0;
+ virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm) = 0;
- virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output) = 0;
+
+ virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output) = 0;
+
+ virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature) = 0;
+
+ virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output) = 0;
-
- virtual status_t decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output) = 0;
-
- virtual status_t sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature) = 0;
-
- virtual status_t verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match) = 0;
-
- virtual status_t signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature) = 0;
+ Vector<uint8_t> const &signature,
+ bool &match) = 0;
- virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
+ virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature) = 0;
- virtual status_t requiresSecureDecoder(const char *mime, bool *required) const = 0;
+ virtual DrmStatus setListener(const sp<IDrmClient>& listener) = 0;
- virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
- bool *required) const = 0;
+ virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const = 0;
- virtual status_t setPlaybackId(
+ virtual DrmStatus requiresSecureDecoder(const char *mime,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const = 0;
+
+ virtual DrmStatus setPlaybackId(
Vector<uint8_t> const &sessionId,
const char *playbackId) = 0;
- virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const = 0;
+ virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const = 0;
- virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const = 0;
+ virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const = 0;
protected:
IDrm() {}
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index 980ce55..e4fc406 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -22,6 +22,7 @@
#include <android/hardware/drm/1.4/IDrmPlugin.h>
#include <android/hardware/drm/1.4/types.h>
#include <media/stagefright/MediaErrors.h>
+#include <mediadrm/DrmStatus.h>
#include <utils/Errors.h> // for status_t
#include <utils/Log.h>
#include <utils/String8.h>
@@ -198,7 +199,7 @@
return toStatusT_1_4(err);
}
-inline status_t statusAidlToStatusT(::ndk::ScopedAStatus &statusAidl) {
+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());
@@ -370,7 +371,7 @@
});
logs.appendVector(allLogs);
- return OK;
+ return toStatusT(err);
}
std::string GetExceptionMessage(status_t err, const char *msg,
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index abfd8a7..6c364c9 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -1701,22 +1701,55 @@
* Available since API level 26.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return actual sample rate
+ * @return actual sample rate of the stream
*/
AAUDIO_API int32_t AAudioStream_getSampleRate(AAudioStream* stream) __INTRODUCED_IN(26);
/**
+ * There may be sample rate conversions in the Audio framework.
+ * The sample rate set in the stream builder may not be actual sample rate used in the hardware.
+ *
+ * This returns the sample rate used by the hardware.
+ *
+ * If AAudioStreamBuilder_openStream() returned AAUDIO_OK, the result should always be valid.
+ *
+ * Available since API level 34.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return actual sample rate of the underlying hardware
+ */
+AAUDIO_API int32_t AAudioStream_getHardwareSampleRate(AAudioStream* stream)
+ __INTRODUCED_IN(__ANDROID_API_U__);
+
+/**
* A stream has one or more channels of data.
* A frame will contain one sample for each channel.
*
* Available since API level 26.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return actual number of channels
+ * @return actual number of channels of the stream
*/
AAUDIO_API int32_t AAudioStream_getChannelCount(AAudioStream* stream) __INTRODUCED_IN(26);
/**
+ * There may be channel conversions in the Audio framework.
+ * The channel count or channel mask set in the stream builder may not be actual number of
+ * channels used in the hardware.
+ *
+ * This returns the channel count used by the hardware.
+ *
+ * If AAudioStreamBuilder_openStream() returned AAUDIO_OK, the result should always be valid.
+ *
+ * Available since API level 34.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return actual number of channels of the underlying hardware
+ */
+AAUDIO_API int32_t AAudioStream_getHardwareChannelCount(AAudioStream* stream)
+ __INTRODUCED_IN(__ANDROID_API_U__);
+
+/**
* Identical to AAudioStream_getChannelCount().
*
* Available since API level 26.
@@ -1738,11 +1771,27 @@
* Available since API level 26.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return actual data format
+ * @return actual data format of the stream
*/
AAUDIO_API aaudio_format_t AAudioStream_getFormat(AAudioStream* stream) __INTRODUCED_IN(26);
/**
+ * There may be data format conversions in the Audio framework.
+ * The data format set in the stream builder may not be actual format used in the hardware.
+ *
+ * This returns the audio format used by the hardware.
+ * AUDIO_FORMAT_PCM_8_24_BIT is currently not supported in AAudio, but the hardware may use it.
+ * If AUDIO_FORMAT_PCM_8_24_BIT is used by the hardware, return AAUDIO_FORMAT_PCM_I24_PACKED.
+ *
+ * Available since API level 34.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return actual data format of the underlying hardware.
+ */
+AAUDIO_API aaudio_format_t AAudioStream_getHardwareFormat(AAudioStream* stream)
+ __INTRODUCED_IN(__ANDROID_API_U__);
+
+/**
* Provide actual sharing mode.
*
* Available since API level 26.
diff --git a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
index b60bac2..c4692ce 100644
--- a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
@@ -40,6 +40,10 @@
auto convFormat = android::aidl2legacy_AudioFormatDescription_audio_format_t(
parcelable.audioFormat);
setFormat(convFormat.ok() ? convFormat.value() : AUDIO_FORMAT_INVALID);
+ if (!convFormat.ok()) {
+ ALOGE("audioFormat (%s) aidl2legacy conversion failed",
+ parcelable.hardwareAudioFormat.toString().c_str());
+ }
static_assert(sizeof(aaudio_direction_t) == sizeof(parcelable.direction));
setDirection(parcelable.direction);
static_assert(sizeof(audio_usage_t) == sizeof(parcelable.usage));
@@ -52,7 +56,6 @@
setSpatializationBehavior(parcelable.spatializationBehavior);
setIsContentSpatialized(parcelable.isContentSpatialized);
-
static_assert(sizeof(aaudio_input_preset_t) == sizeof(parcelable.inputPreset));
setInputPreset(parcelable.inputPreset);
setBufferCapacity(parcelable.bufferCapacity);
@@ -62,6 +65,15 @@
static_assert(sizeof(aaudio_session_id_t) == sizeof(parcelable.sessionId));
setSessionId(parcelable.sessionId);
setPrivacySensitive(parcelable.isPrivacySensitive);
+ setHardwareSamplesPerFrame(parcelable.hardwareSamplesPerFrame);
+ setHardwareSampleRate(parcelable.hardwareSampleRate);
+ auto convHardwareFormat = android::aidl2legacy_AudioFormatDescription_audio_format_t(
+ parcelable.hardwareAudioFormat);
+ setHardwareFormat(convHardwareFormat.ok() ? convHardwareFormat.value() : AUDIO_FORMAT_INVALID);
+ if (!convHardwareFormat.ok()) {
+ ALOGE("hardwareAudioFormat (%s) aidl2legacy conversion failed",
+ parcelable.hardwareAudioFormat.toString().c_str());
+ }
}
AAudioStreamConfiguration&
@@ -82,6 +94,8 @@
if (convAudioFormat.ok()) {
result.audioFormat = convAudioFormat.value();
} else {
+ ALOGE("audioFormat (%s) legacy2aidl conversion failed",
+ audio_format_to_string(getFormat()));
result.audioFormat = AudioFormatDescription{};
result.audioFormat.type =
android::media::audio::common::AudioFormatType::SYS_RESERVED_INVALID;
@@ -92,6 +106,10 @@
result.usage = getUsage();
static_assert(sizeof(aaudio_content_type_t) == sizeof(result.contentType));
result.contentType = getContentType();
+ static_assert(
+ sizeof(aaudio_spatialization_behavior_t) == sizeof(result.spatializationBehavior));
+ result.spatializationBehavior = getSpatializationBehavior();
+ result.isContentSpatialized = isContentSpatialized();
static_assert(sizeof(aaudio_input_preset_t) == sizeof(result.inputPreset));
result.inputPreset = getInputPreset();
result.bufferCapacity = getBufferCapacity();
@@ -100,5 +118,18 @@
static_assert(sizeof(aaudio_session_id_t) == sizeof(result.sessionId));
result.sessionId = getSessionId();
result.isPrivacySensitive = isPrivacySensitive();
+ result.hardwareSamplesPerFrame = getHardwareSamplesPerFrame();
+ result.hardwareSampleRate = getHardwareSampleRate();
+ auto convHardwareAudioFormat = android::legacy2aidl_audio_format_t_AudioFormatDescription(
+ getHardwareFormat());
+ if (convHardwareAudioFormat.ok()) {
+ result.hardwareAudioFormat = convHardwareAudioFormat.value();
+ } else {
+ ALOGE("hardwareAudioFormat (%s) legacy2aidl conversion failed",
+ audio_format_to_string(getHardwareFormat()));
+ result.hardwareAudioFormat = AudioFormatDescription{};
+ result.hardwareAudioFormat.type =
+ android::media::audio::common::AudioFormatType::SYS_RESERVED_INVALID;
+ }
return result;
}
diff --git a/media/libaaudio/src/binding/aidl/aaudio/StreamParameters.aidl b/media/libaaudio/src/binding/aidl/aaudio/StreamParameters.aidl
index 983e193..fa46e0d 100644
--- a/media/libaaudio/src/binding/aidl/aaudio/StreamParameters.aidl
+++ b/media/libaaudio/src/binding/aidl/aaudio/StreamParameters.aidl
@@ -34,4 +34,7 @@
int /* aaudio_allowed_capture_policy_t */ allowedCapturePolicy; // = AAUDIO_UNSPECIFIED;
int /* aaudio_session_id_t */ sessionId; // = AAUDIO_SESSION_ID_NONE;
boolean isPrivacySensitive; // = false;
+ int hardwareSamplesPerFrame;//= AAUDIO_UNSPECIFIED;
+ int hardwareSampleRate; // = AAUDIO_UNSPECIFIED;
+ AudioFormatDescription hardwareAudioFormat; // = AUDIO_FORMAT_DEFAULT;
}
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 27f519b..8fe8569 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -131,6 +131,10 @@
request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
+ request.getConfiguration().setHardwareSamplesPerFrame(builder.getHardwareSamplesPerFrame());
+ request.getConfiguration().setHardwareSampleRate(builder.getHardwareSampleRate());
+ request.getConfiguration().setHardwareFormat(builder.getHardwareFormat());
+
mDeviceChannelCount = getSamplesPerFrame(); // Assume it will be the same. Update if not.
mServiceStreamHandle = mServiceInterface.openStream(request, configurationOutput);
@@ -192,6 +196,10 @@
// Save device format so we can do format conversion and volume scaling together.
setDeviceFormat(configurationOutput.getFormat());
+ setHardwareSamplesPerFrame(configurationOutput.getHardwareSamplesPerFrame());
+ setHardwareSampleRate(configurationOutput.getHardwareSampleRate());
+ setHardwareFormat(configurationOutput.getHardwareFormat());
+
result = mServiceInterface.getStreamDescription(mServiceStreamHandle, mEndPointParcelable);
if (result != AAUDIO_OK) {
goto error;
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 9c82424..8a13a6f 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -418,12 +418,24 @@
return audioStream->getSampleRate();
}
+AAUDIO_API int32_t AAudioStream_getHardwareSampleRate(AAudioStream* stream)
+{
+ AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+ return audioStream->getHardwareSampleRate();
+}
+
AAUDIO_API int32_t AAudioStream_getChannelCount(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
return audioStream->getSamplesPerFrame();
}
+AAUDIO_API int32_t AAudioStream_getHardwareChannelCount(AAudioStream* stream)
+{
+ AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+ return audioStream->getHardwareSamplesPerFrame();
+}
+
AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream)
{
return AAudioStream_getChannelCount(stream);
@@ -443,6 +455,14 @@
return AAudioConvert_androidToAAudioDataFormat(internalFormat);
}
+AAUDIO_API aaudio_format_t AAudioStream_getHardwareFormat(AAudioStream* stream)
+{
+ AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+ // Use audio_format_t internally.
+ audio_format_t internalFormat = audioStream->getHardwareFormat();
+ return AAudioConvert_androidToNearestAAudioDataFormat(internalFormat);
+}
+
AAUDIO_API aaudio_result_t AAudioStream_setBufferSizeInFrames(AAudioStream* stream,
int32_t requestedFrames)
{
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index e6b00d7..c8461cc 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -49,6 +49,9 @@
mOpPackageName = other.mOpPackageName;
mAttributionTag = other.mAttributionTag;
mChannelMask = other.mChannelMask;
+ mHardwareSamplesPerFrame = other.mHardwareSamplesPerFrame;
+ mHardwareSampleRate = other.mHardwareSampleRate;
+ mHardwareAudioFormat = other.mHardwareAudioFormat;
}
static aaudio_result_t isFormatValid(audio_format_t format) {
@@ -311,4 +314,7 @@
"(null)" : mOpPackageName.value().c_str());
ALOGD("mAttributionTag = %s", !mAttributionTag.has_value() ?
"(null)" : mAttributionTag.value().c_str());
-}
+ ALOGD("mHardwareSamplesPerFrame = %6d", mHardwareSamplesPerFrame);
+ ALOGD("mHardwareSampleRate = %6d", mHardwareSampleRate);
+ ALOGD("mHardwareAudioFormat = %6d", (int)mHardwareAudioFormat);
+}
\ No newline at end of file
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.h b/media/libaaudio/src/core/AAudioStreamParameters.h
index cb998bf..565d54c 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.h
+++ b/media/libaaudio/src/core/AAudioStreamParameters.h
@@ -171,6 +171,30 @@
mSamplesPerFrame = AAudioConvert_channelMaskToCount(channelMask);
}
+ int32_t getHardwareSamplesPerFrame() const {
+ return mHardwareSamplesPerFrame;
+ }
+
+ void setHardwareSamplesPerFrame(int32_t hardwareSamplesPerFrame) {
+ mHardwareSamplesPerFrame = hardwareSamplesPerFrame;
+ }
+
+ int32_t getHardwareSampleRate() const {
+ return mHardwareSampleRate;
+ }
+
+ void setHardwareSampleRate(int32_t hardwareSampleRate) {
+ mHardwareSampleRate = hardwareSampleRate;
+ }
+
+ audio_format_t getHardwareFormat() const {
+ return mHardwareAudioFormat;
+ }
+
+ void setHardwareFormat(audio_format_t hardwareAudioFormat) {
+ mHardwareAudioFormat = hardwareAudioFormat;
+ }
+
/**
* @return bytes per frame of getFormat()
*/
@@ -210,6 +234,10 @@
std::optional<std::string> mOpPackageName = {};
std::optional<std::string> mAttributionTag = {};
aaudio_channel_mask_t mChannelMask = AAUDIO_UNSPECIFIED;
+ int mHardwareSamplesPerFrame
+ = AAUDIO_UNSPECIFIED;
+ int mHardwareSampleRate = AAUDIO_UNSPECIFIED;
+ audio_format_t mHardwareAudioFormat = AUDIO_FORMAT_DEFAULT;
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 5ddc515..9b4b734 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -224,14 +224,26 @@
return mSampleRate;
}
+ aaudio_result_t getHardwareSampleRate() const {
+ return mHardwareSampleRate;
+ }
+
audio_format_t getFormat() const {
return mFormat;
}
+ audio_format_t getHardwareFormat() const {
+ return mHardwareFormat;
+ }
+
aaudio_result_t getSamplesPerFrame() const {
return mSamplesPerFrame;
}
+ aaudio_result_t getHardwareSamplesPerFrame() const {
+ return mHardwareSamplesPerFrame;
+ }
+
virtual int32_t getPerformanceMode() const {
return mPerformanceMode;
}
@@ -530,6 +542,11 @@
}
// This should not be called after the open() call.
+ void setHardwareSampleRate(int32_t hardwareSampleRate) {
+ mHardwareSampleRate = hardwareSampleRate;
+ }
+
+ // This should not be called after the open() call.
void setFramesPerBurst(int32_t framesPerBurst) {
mFramesPerBurst = framesPerBurst;
}
@@ -550,6 +567,16 @@
}
// This should not be called after the open() call.
+ void setHardwareFormat(audio_format_t format) {
+ mHardwareFormat = format;
+ }
+
+ // This should not be called after the open() call.
+ void setHardwareSamplesPerFrame(int32_t hardwareSamplesPerFrame) {
+ mHardwareSamplesPerFrame = hardwareSamplesPerFrame;
+ }
+
+ // This should not be called after the open() call.
void setDeviceFormat(audio_format_t format) {
mDeviceFormat = format;
}
@@ -694,12 +721,15 @@
// These do not change after open().
int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
+ int32_t mHardwareSamplesPerFrame = AAUDIO_UNSPECIFIED;
aaudio_channel_mask_t mChannelMask = AAUDIO_UNSPECIFIED;
int32_t mSampleRate = AAUDIO_UNSPECIFIED;
+ int32_t mHardwareSampleRate = AAUDIO_UNSPECIFIED;
int32_t mDeviceId = AAUDIO_UNSPECIFIED;
aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
bool mSharingModeMatchRequired = false; // must match sharing mode requested
audio_format_t mFormat = AUDIO_FORMAT_DEFAULT;
+ audio_format_t mHardwareFormat = AUDIO_FORMAT_DEFAULT;
aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
int32_t mFramesPerBurst = 0;
int32_t mBufferCapacity = 0;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index da152b0..e760dab 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -208,6 +208,10 @@
setBufferCapacity(getBufferCapacityFromDevice());
setFramesPerBurst(getFramesPerBurstFromDevice());
+ setHardwareSamplesPerFrame(mAudioRecord->getHalChannelCount());
+ setHardwareSampleRate(mAudioRecord->getHalSampleRate());
+ setHardwareFormat(mAudioRecord->getHalFormat());
+
// We may need to pass the data through a block size adapter to guarantee constant size.
if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
// The block adapter runs before the format conversion.
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 10bd5f7..fc8ba9e 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -202,6 +202,10 @@
setBufferCapacity(getBufferCapacityFromDevice());
setFramesPerBurst(getFramesPerBurstFromDevice());
+ setHardwareSamplesPerFrame(mAudioTrack->getHalChannelCount());
+ setHardwareSampleRate(mAudioTrack->getHalSampleRate());
+ setHardwareFormat(mAudioTrack->getHalFormat());
+
// We may need to pass the data through a block size adapter to guarantee constant size.
if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
// This may need to change if we add format conversion before
diff --git a/media/libaaudio/src/libaaudio.map.txt b/media/libaaudio/src/libaaudio.map.txt
index f45b816..e28dcb4 100644
--- a/media/libaaudio/src/libaaudio.map.txt
+++ b/media/libaaudio/src/libaaudio.map.txt
@@ -67,6 +67,9 @@
AAudioStream_getChannelMask; # introduced=32
AAudioStream_getSpatializationBehavior; # introduced=32
AAudioStream_isContentSpatialized; # introduced=32
+ AAudioStream_getHardwareChannelCount; # introduced=UpsideDownCake
+ AAudioStream_getHardwareFormat; # introduced=UpsideDownCake
+ AAudioStream_getHardwareSampleRate; # introduced=UpsideDownCake
local:
*;
};
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 0afa11b..8920e53 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -184,6 +184,17 @@
return aaudioFormat;
}
+aaudio_format_t AAudioConvert_androidToNearestAAudioDataFormat(audio_format_t androidFormat) {
+ // Special case AUDIO_FORMAT_PCM_8_24_BIT because this function should be used to find the
+ // resolution of the data format. Setting AUDIO_FORMAT_PCM_8_24_BIT directly is not available
+ // from AAudio but hardware may use AUDIO_FORMAT_PCM_8_24_BIT under the hood.
+ if (androidFormat == AUDIO_FORMAT_PCM_8_24_BIT) {
+ ALOGD("%s() converting 8.24 to 24 bit packed", __func__);
+ return AAUDIO_FORMAT_PCM_I24_PACKED;
+ }
+ return AAudioConvert_androidToAAudioDataFormat(androidFormat);
+}
+
// Make a message string from the condition.
#define STATIC_ASSERT(condition) static_assert(condition, #condition)
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index ac75306..d8e5b00 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -65,6 +65,7 @@
aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t format);
+aaudio_format_t AAudioConvert_androidToNearestAAudioDataFormat(audio_format_t format);
/**
* Note that this function does not validate the passed in value.
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 90d51fd..d32788a 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -1527,6 +1527,8 @@
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);
}
@@ -1572,6 +1574,8 @@
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);
}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 6c198d3..37ecd6f 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -282,6 +282,7 @@
name: "libaudioclient_aidl",
srcs: [
"aidl/android/media/IPlayer.aidl",
+ "aidl/android/media/AudioHalVersion.aidl",
],
path: "aidl",
}
@@ -342,6 +343,7 @@
"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",
@@ -390,6 +392,8 @@
srcs: [
"aidl/android/media/AudioAttributesEx.aidl",
"aidl/android/media/AudioMix.aidl",
+ "aidl/android/media/AudioMixerAttributesInternal.aidl",
+ "aidl/android/media/AudioMixerBehavior.aidl",
"aidl/android/media/AudioMixCallbackFlag.aidl",
"aidl/android/media/AudioMixMatchCriterion.aidl",
"aidl/android/media/AudioMixMatchCriterionValue.aidl",
@@ -449,6 +453,10 @@
"aidl/android/media/IAudioRecord.aidl",
"aidl/android/media/IAudioTrack.aidl",
"aidl/android/media/IAudioTrackCallback.aidl",
+
+ "aidl/android/media/ISoundDose.aidl",
+ "aidl/android/media/ISoundDoseCallback.aidl",
+ "aidl/android/media/SoundDoseRecord.aidl",
],
imports: [
"android.media.audio.common.types-V2",
@@ -540,3 +548,21 @@
},
},
}
+
+aidl_interface {
+ name: "sounddose-aidl",
+ unstable: true,
+ local_include_dir: "aidl",
+ srcs: [
+ "aidl/android/media/ISoundDose.aidl",
+ "aidl/android/media/ISoundDoseCallback.aidl",
+ "aidl/android/media/SoundDoseRecord.aidl",
+ ],
+
+ double_loadable: true,
+ backend: {
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 69d73ad..12bcec6 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -560,6 +560,21 @@
return NO_ERROR;
}
+uint32_t AudioRecord::getHalSampleRate() const
+{
+ return mHalSampleRate;
+}
+
+uint32_t AudioRecord::getHalChannelCount() const
+{
+ return mHalChannelCount;
+}
+
+audio_format_t AudioRecord::getHalFormat() const
+{
+ return mHalFormat;
+}
+
status_t AudioRecord::getMarkerPosition(uint32_t *marker) const
{
if (marker == NULL) {
@@ -878,6 +893,9 @@
mServerFrameSize = audio_bytes_per_frame(
audio_channel_count_from_in_mask(mServerConfig.channel_mask), mServerConfig.format);
mServerSampleSize = audio_bytes_per_sample(mServerConfig.format);
+ mHalSampleRate = output.halConfig.sample_rate;
+ mHalChannelCount = audio_channel_count_from_in_mask(output.halConfig.channel_mask);
+ mHalFormat = output.halConfig.format;
if (output.cblk == 0) {
errorMessage = StringPrintf("%s(%d): Could not get control block", __func__, mPortId);
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index af00ab1..1f107a6 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -34,6 +34,7 @@
#include <system/audio.h>
#include <android/media/GetInputForAttrResponse.h>
+#include <android/media/AudioMixerAttributesInternal.h>
#define VALUE_OR_RETURN_BINDER_STATUS(x) \
({ auto _tmp = (x); \
@@ -1020,7 +1021,8 @@
audio_port_handle_t* selectedDeviceId,
audio_port_handle_t* portId,
std::vector<audio_io_handle_t>* secondaryOutputs,
- bool *isSpatialized) {
+ bool *isSpatialized,
+ bool *isBitPerfect) {
if (attr == nullptr) {
ALOGE("%s NULL audio attributes", __func__);
return BAD_VALUE;
@@ -1083,6 +1085,7 @@
*secondaryOutputs = VALUE_OR_RETURN_STATUS(convertContainer<std::vector<audio_io_handle_t>>(
responseAidl.secondaryOutputs, aidl2legacy_int32_t_audio_io_handle_t));
*isSpatialized = responseAidl.isSpatialized;
+ *isBitPerfect = responseAidl.isBitPerfect;
return OK;
}
@@ -2374,6 +2377,20 @@
return OK;
}
+status_t AudioSystem::getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ if (soundDose == nullptr) {
+ return BAD_VALUE;
+ }
+
+ RETURN_STATUS_IF_ERROR(af->getSoundDoseInterface(callback, soundDose));
+ return OK;
+}
+
status_t AudioSystem::getDirectPlaybackSupport(const audio_attributes_t *attr,
const audio_config_t *config,
audio_direct_mode_t* directMode) {
@@ -2529,6 +2546,84 @@
return af->getAAudioHardwareBurstMinUsec();
}
+status_t AudioSystem::getSupportedMixerAttributes(
+ audio_port_handle_t portId, std::vector<audio_mixer_attributes_t> *mixerAttrs) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == nullptr) {
+ return PERMISSION_DENIED;
+ }
+
+ int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
+ std::vector<media::AudioMixerAttributesInternal> _aidlReturn;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ aps->getSupportedMixerAttributes(portIdAidl, &_aidlReturn)));
+ *mixerAttrs = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<audio_mixer_attributes_t>>(
+ _aidlReturn,
+ aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t));
+ return OK;
+}
+
+status_t AudioSystem::setPreferredMixerAttributes(const audio_attributes_t *attr,
+ audio_port_handle_t portId,
+ uid_t uid,
+ const audio_mixer_attributes_t *mixerAttr) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == nullptr) {
+ return PERMISSION_DENIED;
+ }
+
+ media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::AudioMixerAttributesInternal mixerAttrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal(*mixerAttr));
+ int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
+ int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
+
+ return statusTFromBinderStatus(
+ aps->setPreferredMixerAttributes(attrAidl, portIdAidl, uidAidl, mixerAttrAidl));
+}
+
+status_t AudioSystem::getPreferredMixerAttributes(
+ const audio_attributes_t *attr,
+ audio_port_handle_t portId,
+ std::optional<audio_mixer_attributes_t> *mixerAttr) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == nullptr) {
+ return PERMISSION_DENIED;
+ }
+
+ media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
+ std::optional<media::AudioMixerAttributesInternal> _aidlReturn;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ aps->getPreferredMixerAttributes(attrAidl, portIdAidl, &_aidlReturn)));
+
+ if (_aidlReturn.has_value()) {
+ *mixerAttr = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t(
+ _aidlReturn.value()));
+ }
+ return NO_ERROR;
+}
+
+status_t AudioSystem::clearPreferredMixerAttributes(const audio_attributes_t *attr,
+ audio_port_handle_t portId,
+ uid_t uid) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == nullptr) {
+ return PERMISSION_DENIED;
+ }
+
+ media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
+ int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
+ return statusTFromBinderStatus(
+ aps->clearPreferredMixerAttributes(attrAidl, portIdAidl, uidAidl));
+}
+
// ---------------------------------------------------------------------------
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index b18a569..22bd2a3 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1233,6 +1233,21 @@
return mOriginalSampleRate;
}
+uint32_t AudioTrack::getHalSampleRate() const
+{
+ return mAfSampleRate;
+}
+
+uint32_t AudioTrack::getHalChannelCount() const
+{
+ return mAfChannelCount;
+}
+
+audio_format_t AudioTrack::getHalFormat() const
+{
+ return mAfFormat;
+}
+
status_t AudioTrack::setDualMonoMode(audio_dual_mono_mode_t mode)
{
AutoMutex lock(mLock);
@@ -1888,6 +1903,8 @@
mAfFrameCount = output.afFrameCount;
mAfSampleRate = output.afSampleRate;
+ mAfChannelCount = audio_channel_count_from_out_mask(output.afChannelMask);
+ mAfFormat = output.afFormat;
mAfLatency = output.afLatencyMs;
mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 6ad97d1..141c84f 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 {
@@ -112,6 +112,10 @@
aidl.afFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(afFrameCount));
aidl.afSampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(afSampleRate));
aidl.afLatencyMs = VALUE_OR_RETURN(convertIntegral<int32_t>(afLatencyMs));
+ aidl.afChannelMask = VALUE_OR_RETURN(
+ legacy2aidl_audio_channel_mask_t_AudioChannelLayout(afChannelMask, false /*isInput*/));
+ aidl.afFormat = VALUE_OR_RETURN(
+ legacy2aidl_audio_format_t_AudioFormatDescription(afFormat));
aidl.outputId = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(outputId));
aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(portId));
aidl.audioTrack = audioTrack;
@@ -135,6 +139,11 @@
legacy.afFrameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.afFrameCount));
legacy.afSampleRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.afSampleRate));
legacy.afLatencyMs = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.afLatencyMs));
+ legacy.afChannelMask = VALUE_OR_RETURN(
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.afChannelMask,
+ false /*isInput*/));
+ legacy.afFormat = VALUE_OR_RETURN(
+ aidl2legacy_AudioFormatDescription_audio_format_t(aidl.afFormat));
legacy.outputId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.outputId));
legacy.portId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
legacy.audioTrack = aidl.audioTrack;
@@ -199,6 +208,8 @@
aidl.audioRecord = audioRecord;
aidl.serverConfig = VALUE_OR_RETURN(
legacy2aidl_audio_config_base_t_AudioConfigBase(serverConfig, true /*isInput*/));
+ aidl.halConfig = VALUE_OR_RETURN(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(halConfig, true /*isInput*/));
return aidl;
}
@@ -221,6 +232,8 @@
legacy.audioRecord = aidl.audioRecord;
legacy.serverConfig = VALUE_OR_RETURN(
aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.serverConfig, true /*isInput*/));
+ legacy.halConfig = VALUE_OR_RETURN(
+ aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.halConfig, true /*isInput*/));
return legacy;
}
@@ -837,10 +850,18 @@
return NO_ERROR;
}
+status_t AudioFlingerClientAdapter::getSoundDoseInterface(
+ const sp<media::ISoundDoseCallback> &callback,
+ sp<media::ISoundDose>* soundDose) {
+ return statusTFromBinderStatus(mDelegate->getSoundDoseInterface(callback, soundDose));
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// 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,
@@ -1355,4 +1376,11 @@
return Status::ok();
}
+Status AudioFlingerServerAdapter::getSoundDoseInterface(
+ const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose)
+{
+ return Status::fromStatusT(mDelegate->getSoundDoseInterface(callback, soundDose));
+}
+
} // namespace android
diff --git a/media/libaudioclient/PolicyAidlConversion.cpp b/media/libaudioclient/PolicyAidlConversion.cpp
index 4423eb6..60b08fa 100644
--- a/media/libaudioclient/PolicyAidlConversion.cpp
+++ b/media/libaudioclient/PolicyAidlConversion.cpp
@@ -472,4 +472,51 @@
return unexpected(BAD_VALUE);
}
+ConversionResult<audio_mixer_behavior_t>
+aidl2legacy_AudioMixerBehavior_audio_mixer_behavior_t(media::AudioMixerBehavior aidl) {
+ switch (aidl) {
+ case media::AudioMixerBehavior::DEFAULT:
+ return AUDIO_MIXER_BEHAVIOR_DEFAULT;
+ case media::AudioMixerBehavior::BIT_PERFECT:
+ return AUDIO_MIXER_BEHAVIOR_BIT_PERFECT;
+ case media::AudioMixerBehavior::INVALID:
+ return AUDIO_MIXER_BEHAVIOR_INVALID;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<media::AudioMixerBehavior>
+legacy2aidl_audio_mixer_behavior_t_AudioMixerBehavior(audio_mixer_behavior_t legacy) {
+ switch (legacy) {
+ case AUDIO_MIXER_BEHAVIOR_DEFAULT:
+ return media::AudioMixerBehavior::DEFAULT;
+ case AUDIO_MIXER_BEHAVIOR_BIT_PERFECT:
+ return media::AudioMixerBehavior::BIT_PERFECT;
+ case AUDIO_MIXER_BEHAVIOR_INVALID:
+ return media::AudioMixerBehavior::INVALID;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_mixer_attributes_t>
+aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t(
+ const media::AudioMixerAttributesInternal& aidl) {
+ audio_mixer_attributes_t legacy = AUDIO_MIXER_ATTRIBUTES_INITIALIZER;
+ legacy.config = VALUE_OR_RETURN(
+ aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config, false /*isInput*/));
+ legacy.mixer_behavior = VALUE_OR_RETURN(
+ aidl2legacy_AudioMixerBehavior_audio_mixer_behavior_t(aidl.mixerBehavior));
+ return legacy;
+}
+ConversionResult<media::AudioMixerAttributesInternal>
+legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal(
+ const audio_mixer_attributes& legacy) {
+ media::AudioMixerAttributesInternal aidl;
+ aidl.config = VALUE_OR_RETURN(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(legacy.config, false /*isInput*/));
+ aidl.mixerBehavior = VALUE_OR_RETURN(
+ legacy2aidl_audio_mixer_behavior_t_AudioMixerBehavior(legacy.mixer_behavior));
+ return aidl;
+}
+
+
} // namespace android
diff --git a/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl b/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl
new file mode 100644
index 0000000..49048040
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * The audio HAL version definition.
+ *
+ * {@hide}
+ */
+parcelable AudioHalVersion {
+
+ @Backing(type="int")
+ enum Type {
+ /**
+ * Indicate the audio HAL is implemented with HIDL (HAL interface definition language).
+ * @see <a href="https://source.android.com/docs/core/architecture/hidl/">HIDL</a>
+ */
+ HIDL = 0,
+
+ /**
+ * Indicate the audio HAL is implemented with AIDL (Android Interface Definition Language).
+ * @see <a href="https://source.android.com/docs/core/architecture/aidl/">AIDL</a>
+ */
+ AIDL
+ }
+
+ Type type = Type.HIDL;
+
+ /**
+ * Major version number.
+ */
+ int major;
+
+ /**
+ * Minor version number.
+ */
+ int minor;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioMixerAttributesInternal.aidl b/media/libaudioclient/aidl/android/media/AudioMixerAttributesInternal.aidl
new file mode 100644
index 0000000..ed25060
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioMixerAttributesInternal.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.media.AudioMixerBehavior;
+import android.media.audio.common.AudioConfigBase;
+
+/**
+ * This class is used to contains information about audio mixer.
+ * The "Internal" suffix of this type name is to disambiguate it from the
+ * android.media.AudioMixerAttributes SDK type.
+ *
+ * {@hide}
+ */
+parcelable AudioMixerAttributesInternal {
+ AudioConfigBase config;
+ AudioMixerBehavior mixerBehavior;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioMixerBehavior.aidl b/media/libaudioclient/aidl/android/media/AudioMixerBehavior.aidl
new file mode 100644
index 0000000..38f50d6
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioMixerBehavior.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * Defines the mixer behavior that can be used when setting mixer attributes.
+ */
+@Backing(type="int")
+enum AudioMixerBehavior {
+ /**
+ * The mixer behavior is invalid.
+ */
+ INVALID = -1,
+ /**
+ * The mixer behavior that follows platform default behavior, which is mixing audio from
+ * different sources.
+ */
+ DEFAULT = 0,
+ /**
+ * The audio data in the mixer will be bit-perfect as long as possible.
+ */
+ BIT_PERFECT = 1,
+}
diff --git a/media/libaudioclient/aidl/android/media/CreateRecordResponse.aidl b/media/libaudioclient/aidl/android/media/CreateRecordResponse.aidl
index 7d159d0..5f1e288 100644
--- a/media/libaudioclient/aidl/android/media/CreateRecordResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateRecordResponse.aidl
@@ -45,4 +45,5 @@
/** The newly created record. */
@nullable IAudioRecord audioRecord;
AudioConfigBase serverConfig;
+ AudioConfigBase halConfig;
}
diff --git a/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl b/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
index da6f454..42e0bb4 100644
--- a/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
@@ -16,6 +16,8 @@
package android.media;
+import android.media.audio.common.AudioChannelLayout;
+import android.media.audio.common.AudioFormatDescription;
import android.media.audio.common.AudioStreamType;
import android.media.IAudioTrack;
@@ -38,6 +40,8 @@
AudioStreamType streamType;
long afFrameCount;
int afSampleRate;
+ AudioChannelLayout afChannelMask;
+ AudioFormatDescription afFormat;
int afLatencyMs;
/** Interpreted as audio_io_handle_t. */
int outputId;
diff --git a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
index 5b25d79..385f787 100644
--- a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
@@ -36,4 +36,5 @@
boolean isSpatialized;
/** The suggested audio config if fails to get an output. **/
AudioConfigBase configBase;
+ boolean isBitPerfect;
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 9b8a843..4383b9e 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -35,6 +35,8 @@
import android.media.IAudioFlingerClient;
import android.media.IAudioRecord;
import android.media.IAudioTrack;
+import android.media.ISoundDose;
+import android.media.ISoundDoseCallback;
import android.media.LatencyMode;
import android.media.MicrophoneInfoData;
import android.media.RenderPosition;
@@ -246,6 +248,12 @@
*/
LatencyMode[] getSupportedLatencyModes(int output);
+ /**
+ * Registers the sound dose callback and returns the interface for executing
+ * sound dose methods on the audio server.
+ */
+ ISoundDose getSoundDoseInterface(in ISoundDoseCallback callback);
+
// When adding a new method, please review and update
// IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
// AudioFlinger.cpp AudioFlinger::onTransactWrapper()
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 24b59bf..e0db8f9 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -22,6 +22,7 @@
import android.media.AudioAttributesInternal;
import android.media.AudioDirectMode;
import android.media.AudioMix;
+import android.media.AudioMixerAttributesInternal;
import android.media.AudioOffloadMode;
import android.media.AudioPatch;
import android.media.AudioPolicyDeviceState;
@@ -391,6 +392,60 @@
*/
AudioProfile[] getDirectProfilesForAttributes(in AudioAttributesInternal attr);
+ /**
+ * Return a list of AudioMixerAttributes that can be used to set preferred mixer attributes
+ * for the given device.
+ */
+ AudioMixerAttributesInternal[] getSupportedMixerAttributes(
+ int /* audio_port_handle_t */ portId);
+
+ /**
+ * Set preferred mixer attributes for a given device on a given audio attributes.
+ * When conflicting requests are received, the last request will be honored.
+ * The preferred mixer attributes can only be set when 1) the usage is media, 2) the
+ * given device is currently available, 3) the given device is usb device, 4) the given mixer
+ * attributes is supported by the given device.
+ *
+ * @param attr the audio attributes whose mixer attributes should be set.
+ * @param portId the port id of the device to be routed.
+ * @param uid the uid of the request client. The uid will be used to recognize the ownership for
+ * the preferred mixer attributes. All the playback with same audio attributes from
+ * the same uid will be attached to the mixer with the preferred attributes if the
+ * playback is routed to the given device.
+ * @param mixerAttr the preferred mixer attributes.
+ */
+ void setPreferredMixerAttributes(in AudioAttributesInternal attr,
+ int /* audio_port_handle_t */ portId,
+ int /* uid_t */ uid,
+ in AudioMixerAttributesInternal mixerAttr);
+
+ /**
+ * Get preferred mixer attributes for a given device on a given audio attributes.
+ * Null will be returned if there is no preferred mixer attributes set or it has
+ * been cleared.
+ *
+ * @param attr the audio attributes whose mixer attributes should be set.
+ * @param portId the port id of the device to be routed.
+ */
+ @nullable AudioMixerAttributesInternal getPreferredMixerAttributes(
+ in AudioAttributesInternal attr,
+ int /* audio_port_handle_t */ portId);
+
+ /**
+ * Clear preferred mixer attributes for a given device on a given audio attributes that
+ * is previously set via setPreferredMixerAttributes.
+ *
+ * @param attr the audio attributes whose mixer attributes should be set.
+ * @param portId the port id of the device to be routed.
+ * @param uid the uid of the request client. The uid is used to identify the ownership for the
+ * preferred mixer attributes. The preferred mixer attributes will only be cleared
+ * if the uid is the same as the owner of current preferred mixer attributes.
+ */
+ void clearPreferredMixerAttributes(in AudioAttributesInternal attr,
+ int /* audio_port_handle_t */ portId,
+ int /* uid_t */ uid);
+
+
// When adding a new method, please review and update
// AudioPolicyService.cpp AudioPolicyService::onTransact()
// AudioPolicyService.cpp IAUDIOPOLICYSERVICE_BINDER_METHOD_MACRO_LIST
diff --git a/media/libaudioclient/aidl/android/media/ISoundDose.aidl b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
new file mode 100644
index 0000000..f31f091
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 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.
+ */
+
+package android.media;
+
+import android.media.SoundDoseRecord;
+
+/**
+ * Interface used to push the sound dose related information from the
+ * AudioService#SoundDoseHelper to the audio server
+ */
+oneway interface ISoundDose {
+ /** Set a new RS2 value used for momentary exposure warnings. */
+ void setOutputRs2(float rs2Value);
+
+ /**
+ * Resets the native CSD values. This can happen after a crash in the
+ * audio server or after booting when restoring the previous state.
+ * 'currentCsd' represents the restored CSD value and 'records' contains the
+ * dosage values and MELs together with their timestamps that lead to this
+ * CSD.
+ */
+ void resetCsd(float currentCsd, in SoundDoseRecord[] records);
+}
diff --git a/media/libaudioclient/aidl/android/media/ISoundDoseCallback.aidl b/media/libaudioclient/aidl/android/media/ISoundDoseCallback.aidl
new file mode 100644
index 0000000..7e59409
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/ISoundDoseCallback.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright 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.
+ */
+
+package android.media;
+
+import android.media.SoundDoseRecord;
+
+/**
+ * Interface used to push the sound dose related information from the audio
+ * server to the AudioService#SoundDoseHelper.
+ */
+interface ISoundDoseCallback {
+ /** Called whenever the momentary exposure exceeds the RS2 value. */
+ oneway void onMomentaryExposure(float currentMel, int deviceId);
+
+ /**
+ * Notifies that the CSD value has changed. The currentCsd is normalized
+ * with value 1 representing 100% of sound dose. SoundDoseRecord represents
+ * the newest record that lead to the new currentCsd.
+ */
+ oneway void onNewCsdValue(float currentCsd, in SoundDoseRecord[] records);
+}
diff --git a/media/libaudioclient/aidl/android/media/SoundDoseRecord.aidl b/media/libaudioclient/aidl/android/media/SoundDoseRecord.aidl
new file mode 100644
index 0000000..94b8ce2
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/SoundDoseRecord.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 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.
+ */
+
+package android.media;
+
+/** Record containing information about the computed sound dose. */
+parcelable SoundDoseRecord {
+ /**
+ * Corresponds to the time in seconds when the CSD value is calculated from.
+ * Values should be consistent and referenced from the same clock (e.g.: monotonic)
+ */
+ long timestamp;
+ /** Corresponds to the duration that leads to the CSD value. */
+ int duration;
+ /** The actual contribution to the CSD computation normalized: 1.f is 100%CSD. */
+ float value;
+ /** The average MEL value in this time frame that lead to this CSD value. */
+ float averageMel;
+}
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index 5a1ff65..3f33d7a 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -326,6 +326,15 @@
*/
uint32_t getSampleRate() const { return mSampleRate; }
+ /* Return the sample rate from the AudioFlinger input thread. */
+ uint32_t getHalSampleRate() const;
+
+ /* Return the channel count from the AudioFlinger input thread. */
+ uint32_t getHalChannelCount() const;
+
+ /* Return the HAL format from the AudioFlinger input thread. */
+ audio_format_t getHalFormat() const;
+
/* Sets marker position. When record reaches the number of frames specified,
* a callback with event type EVENT_MARKER is called. Calling setMarkerPosition
* with marker == 0 cancels marker notification callback.
@@ -770,6 +779,9 @@
size_t mServerSampleSize;
std::unique_ptr<uint8_t[]> mFormatConversionBufRaw;
Buffer mFormatConversionBuffer;
+ uint32_t mHalSampleRate; // AudioFlinger thread sample rate
+ uint32_t mHalChannelCount; // AudioFlinger thread channel count
+ audio_format_t mHalFormat; // AudioFlinger thread format
private:
class DeathNotifier : public IBinder::DeathRecipient {
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 6e6b9c8..e04b82e 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -28,6 +28,8 @@
#include <android/media/BnAudioPolicyServiceClient.h>
#include <android/media/EffectDescriptor.h>
#include <android/media/INativeSpatializerCallback.h>
+#include <android/media/ISoundDose.h>
+#include <android/media/ISoundDoseCallback.h>
#include <android/media/ISpatializer.h>
#include <android/media/RecordClientInfo.h>
#include <android/media/audio/common/AudioConfigBase.h>
@@ -299,6 +301,7 @@
* @param[out] portId the generated port id to identify the client
* @param[out] secondaryOutputs collection of io handle for secondary outputs
* @param[out] isSpatialized true if the playback will be spatialized
+ * @param[out] isBitPerfect true if the playback will be bit-perfect
* @return if the call is successful or not
*/
static status_t getOutputForAttr(audio_attributes_t *attr,
@@ -311,7 +314,8 @@
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId,
std::vector<audio_io_handle_t> *secondaryOutputs,
- bool *isSpatialized);
+ bool *isSpatialized,
+ bool *isBitPerfect);
static status_t startOutput(audio_port_handle_t portId);
static status_t stopOutput(audio_port_handle_t portId);
static void releaseOutput(audio_port_handle_t portId);
@@ -586,6 +590,16 @@
bool *canBeSpatialized);
/**
+ * Registers the sound dose callback with the audio server and returns the ISoundDose
+ * interface.
+ *
+ * \param callback to send messages to the audio server
+ * \param soundDose binder to send messages to the AudioService
+ **/
+ static status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose);
+
+ /**
* Query how the direct playback is currently supported on the device.
* @param attr audio attributes describing the playback use case
* @param config audio configuration for the playback
@@ -615,6 +629,19 @@
static status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes);
+ static status_t getSupportedMixerAttributes(audio_port_handle_t portId,
+ std::vector<audio_mixer_attributes_t> *mixerAttrs);
+ static status_t setPreferredMixerAttributes(const audio_attributes_t *attr,
+ audio_port_handle_t portId,
+ uid_t uid,
+ const audio_mixer_attributes_t *mixerAttr);
+ static status_t getPreferredMixerAttributes(const audio_attributes_t* attr,
+ audio_port_handle_t portId,
+ std::optional<audio_mixer_attributes_t>* mixerAttr);
+ static status_t clearPreferredMixerAttributes(const audio_attributes_t* attr,
+ audio_port_handle_t portId,
+ uid_t uid);
+
// A listener for capture state changes.
class CaptureStateListener : public virtual RefBase {
public:
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index e873607..31f81be 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -655,6 +655,15 @@
*/
uint32_t getOriginalSampleRate() const;
+ /* Return the sample rate from the AudioFlinger output thread. */
+ uint32_t getHalSampleRate() const;
+
+ /* Return the channel count from the AudioFlinger output thread. */
+ uint32_t getHalChannelCount() const;
+
+ /* Return the HAL format from the AudioFlinger output thread. */
+ audio_format_t getHalFormat() const;
+
/* Sets the Dual Mono mode presentation on the output device. */
status_t setDualMonoMode(audio_dual_mono_mode_t mode);
@@ -1270,12 +1279,14 @@
size_t mReqFrameCount; // frame count to request the first or next time
// a new IAudioTrack is needed, non-decreasing
- // The following AudioFlinger server-side values are cached in createAudioTrack_l().
+ // The following AudioFlinger server-side values are cached in createTrack_l().
// These values can be used for informational purposes until the track is invalidated,
// whereupon restoreTrack_l() calls createTrack_l() to update the values.
uint32_t mAfLatency; // AudioFlinger latency in ms
size_t mAfFrameCount; // AudioFlinger frame count
uint32_t mAfSampleRate; // AudioFlinger sample rate
+ uint32_t mAfChannelCount; // AudioFlinger channel count
+ audio_format_t mAfFormat; // AudioFlinger format
// constant after constructor or set()
audio_format_t mFormat; // as requested by client, not forced to 16-bit
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index c891ae6..6c89862 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -55,6 +55,8 @@
#include "android/media/IAudioTrackCallback.h"
#include "android/media/IEffect.h"
#include "android/media/IEffectClient.h"
+#include "android/media/ISoundDose.h"
+#include "android/media/ISoundDoseCallback.h"
#include "android/media/OpenInputRequest.h"
#include "android/media/OpenInputResponse.h"
#include "android/media/OpenOutputRequest.h"
@@ -116,6 +118,8 @@
size_t afFrameCount;
uint32_t afSampleRate;
uint32_t afLatencyMs;
+ audio_channel_mask_t afChannelMask;
+ audio_format_t afFormat;
audio_io_handle_t outputId;
audio_port_handle_t portId;
sp<media::IAudioTrack> audioTrack;
@@ -169,6 +173,7 @@
audio_port_handle_t portId;
sp<media::IAudioRecord> audioRecord;
audio_config_base_t serverConfig;
+ audio_config_base_t halConfig;
ConversionResult<media::CreateRecordResponse> toAidl() const;
static ConversionResult<CreateRecordOutput>
@@ -367,6 +372,8 @@
virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes) = 0;
+ virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose) = 0;
};
/**
@@ -473,6 +480,8 @@
audio_latency_mode_t mode) override;
status_t getSupportedLatencyModes(
audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) override;
+ status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose) override;
private:
const sp<media::IAudioFlingerService> mDelegate;
@@ -564,6 +573,7 @@
SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
+ GET_SOUND_DOSE_INTERFACE = media::BnAudioFlingerService::TRANSACTION_getSoundDoseInterface,
};
protected:
@@ -688,6 +698,8 @@
Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
Status getSupportedLatencyModes(int output,
std::vector<media::LatencyMode>* _aidl_return) override;
+ Status getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* _aidl_return) override;
private:
const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
};
diff --git a/media/libaudioclient/include/media/PolicyAidlConversion.h b/media/libaudioclient/include/media/PolicyAidlConversion.h
index 54e778e..ed9ddd6 100644
--- a/media/libaudioclient/include/media/PolicyAidlConversion.h
+++ b/media/libaudioclient/include/media/PolicyAidlConversion.h
@@ -22,6 +22,8 @@
#include <system/audio.h>
#include <android/media/AudioMix.h>
+#include <android/media/AudioMixerAttributesInternal.h>
+#include <android/media/AudioMixerBehavior.h>
#include <android/media/AudioMixCallbackFlag.h>
#include <android/media/AudioMixRouteFlag.h>
#include <android/media/AudioMixType.h>
@@ -102,4 +104,16 @@
ConversionResult<media::AudioOffloadMode>
legacy2aidl_audio_offload_mode_t_AudioOffloadMode(audio_offload_mode_t legacy);
+ConversionResult<audio_mixer_behavior_t>
+aidl2legacy_AudioMixerBehavior_audio_mixer_behavior_t(media::AudioMixerBehavior aidl);
+ConversionResult<media::AudioMixerBehavior>
+legacy2aidl_audio_mixer_behavior_t_AudioMixerBehavior(audio_mixer_behavior_t legacy);
+
+ConversionResult<audio_mixer_attributes_t>
+aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t(
+ const media::AudioMixerAttributesInternal& aidl);
+ConversionResult<media::AudioMixerAttributesInternal>
+legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal(
+ const audio_mixer_attributes_t& legacy);
+
} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index b6e6c84..bce131c 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -31,6 +31,7 @@
using DeviceTypeSet = std::set<audio_devices_t>;
using FormatSet = std::set<audio_format_t>;
using SampleRateSet = std::set<uint32_t>;
+using MixerBehaviorSet = std::set<audio_mixer_behavior_t>;
using FormatVector = std::vector<audio_format_t>;
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 5f63e8d..320c639 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -13,7 +13,7 @@
srcs: [
"DevicesFactoryHalInterface.cpp",
"EffectsFactoryHalInterface.cpp",
- "FactoryHalHidl.cpp",
+ "FactoryHal.cpp",
],
cflags: [
@@ -28,10 +28,12 @@
"libaudiohal@6.0",
"libaudiohal@7.0",
"libaudiohal@7.1",
+ "libaudiohal@aidl",
],
shared_libs: [
"audioclient-types-aidl-cpp",
+ "libbinder_ndk",
"libdl",
"libhidlbase",
"liblog",
@@ -65,7 +67,7 @@
header_libs: [
"libaudiohal_headers"
- ]
+ ],
}
cc_library_headers {
diff --git a/media/libaudiohal/DevicesFactoryHalInterface.cpp b/media/libaudiohal/DevicesFactoryHalInterface.cpp
index 5ad26fc..adce681 100644
--- a/media/libaudiohal/DevicesFactoryHalInterface.cpp
+++ b/media/libaudiohal/DevicesFactoryHalInterface.cpp
@@ -14,19 +14,14 @@
* limitations under the License.
*/
-#include <string>
-
#include <media/audiohal/DevicesFactoryHalInterface.h>
-#include <media/audiohal/FactoryHalHidl.h>
+#include <media/audiohal/FactoryHal.h>
namespace android {
// static
sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
- using namespace std::string_literals;
- return createPreferredImpl<DevicesFactoryHalInterface>(
- std::make_pair("android.hardware.audio"s, "IDevicesFactory"s),
- std::make_pair("android.hardware.audio.effect"s, "IEffectsFactory"s));
+ return createPreferredImpl<DevicesFactoryHalInterface>(true /* isCore */);
}
} // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
index 8a28f64..3a05f21 100644
--- a/media/libaudiohal/EffectsFactoryHalInterface.cpp
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -14,19 +14,14 @@
* limitations under the License.
*/
-#include <string>
-
#include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <media/audiohal/FactoryHalHidl.h>
+#include <media/audiohal/FactoryHal.h>
namespace android {
// static
sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
- using namespace std::string_literals;
- return createPreferredImpl<EffectsFactoryHalInterface>(
- std::make_pair("android.hardware.audio.effect"s, "IEffectsFactory"s),
- std::make_pair("android.hardware.audio"s, "IDevicesFactory"s));
+ return createPreferredImpl<EffectsFactoryHalInterface>(false /* isCore */);
}
// static
diff --git a/media/libaudiohal/FactoryHal.cpp b/media/libaudiohal/FactoryHal.cpp
new file mode 100644
index 0000000..16d591c
--- /dev/null
+++ b/media/libaudiohal/FactoryHal.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.
+ */
+
+#include <map>
+#include <memory>
+#define LOG_TAG "FactoryHal"
+
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <dlfcn.h>
+#include <utility>
+
+#include <android/binder_manager.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <utils/Log.h>
+
+#include "include/media/audiohal/AudioHalVersionInfo.h"
+#include "include/media/audiohal/FactoryHal.h"
+
+namespace android::detail {
+
+namespace {
+
+using ::android::detail::AudioHalVersionInfo;
+
+// The pair of the interface's package name and the interface name,
+// e.g. <"android.hardware.audio", "IDevicesFactory"> for HIDL, <"android.hardware.audio.core",
+// "IModule"> for AIDL.
+// Splitting is used for easier construction of versioned names (FQNs).
+using InterfaceName = std::pair<std::string, std::string>;
+
+/**
+ * Supported HAL versions, from most recent to least recent.
+ * This list need to keep sync with AudioHalVersionInfo.VERSIONS in
+ * media/java/android/media/AudioHalVersionInfo.java.
+ */
+static const std::array<AudioHalVersionInfo, 5> sAudioHALVersions = {
+ // TODO: remove this comment to get AIDL
+ // AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, 1, 0),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 0),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 5, 0),
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 4, 0),
+};
+
+static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
+ {AudioHalVersionInfo::Type::AIDL, std::make_pair("android.hardware.audio.core", "IModule")},
+ {AudioHalVersionInfo::Type::HIDL,
+ std::make_pair("android.hardware.audio", "IDevicesFactory")},
+};
+
+static const std::map<AudioHalVersionInfo::Type, InterfaceName> sEffectsHALInterfaces = {
+ {AudioHalVersionInfo::Type::AIDL,
+ std::make_pair("android.hardware.audio.effect", "IFactory")},
+ {AudioHalVersionInfo::Type::HIDL,
+ std::make_pair("android.hardware.audio.effect", "IEffectsFactory")},
+};
+
+bool createHalService(const AudioHalVersionInfo& version, bool isDevice, void** rawInterface) {
+ const std::string libName = "libaudiohal@" + version.toVersionString() + ".so";
+ const std::string factoryFunctionName =
+ isDevice ? "createIDevicesFactory" : "createIEffectsFactory";
+ constexpr int dlMode = RTLD_LAZY;
+ void* handle = nullptr;
+ dlerror(); // clear
+ handle = dlopen(libName.c_str(), dlMode);
+ if (handle == nullptr) {
+ const char* error = dlerror();
+ ALOGE("Failed to dlopen %s: %s", libName.c_str(),
+ error != nullptr ? error : "unknown error");
+ return false;
+ }
+ void* (*factoryFunction)();
+ *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
+ if (!factoryFunction) {
+ const char* error = dlerror();
+ ALOGE("Factory function %s not found in library %s: %s",
+ factoryFunctionName.c_str(), libName.c_str(),
+ error != nullptr ? error : "unknown error");
+ dlclose(handle);
+ return false;
+ }
+ *rawInterface = (*factoryFunction)();
+ ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
+ factoryFunctionName.c_str(), libName.c_str());
+ return true;
+}
+
+bool hasAidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+ const std::string name = interface.first + "." + interface.second + "/default";
+ AIBinder* binder = AServiceManager_checkService(name.c_str());
+ if (binder == nullptr) {
+ ALOGW("%s Service %s doesn't exist", __func__, name.c_str());
+ return false;
+ }
+ ALOGI("%s AIDL Service %s exist: %s", __func__, name.c_str(), version.toString().c_str());
+ return true;
+}
+
+bool hasHidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+ using ::android::hidl::manager::V1_0::IServiceManager;
+ sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
+ if (!sm) {
+ ALOGW("Failed to obtain HIDL ServiceManager");
+ return false;
+ }
+ // Since audio HAL doesn't support multiple clients, avoid instantiating
+ // the interface right away. Instead, query the transport type for it.
+ using ::android::hardware::Return;
+ using Transport = IServiceManager::Transport;
+ const std::string fqName =
+ interface.first + "@" + version.toVersionString() + "::" + interface.second;
+ const std::string instance = "default";
+ Return<Transport> transport = sm->getTransport(fqName, instance);
+ if (!transport.isOk()) {
+ ALOGW("Failed to obtain transport type for %s/%s: %s",
+ fqName.c_str(), instance.c_str(), transport.description().c_str());
+ return false;
+ }
+ return transport != Transport::EMPTY;
+}
+
+bool hasHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+ auto halType = version.getType();
+ if (halType == AudioHalVersionInfo::Type::AIDL) {
+ return hasAidlHalService(interface, version);
+ } else if (version.getType() == AudioHalVersionInfo::Type::HIDL) {
+ return hasHidlHalService(interface, version);
+ } else {
+ ALOGE("HalType not supported %s", version.toString().c_str());
+ return false;
+ }
+}
+
+} // namespace
+
+void *createPreferredImpl(bool isDevice) {
+ auto findMostRecentVersion = [](const auto& iMap) {
+ return std::find_if(sAudioHALVersions.begin(), sAudioHALVersions.end(),
+ [iMap](const auto& v) {
+ auto iface = iMap.find(v.getType());
+ return hasHalService(iface->second, v);
+ });
+ };
+
+ auto interfaceMap = isDevice ? sDevicesHALInterfaces : sEffectsHALInterfaces;
+ auto siblingInterfaceMap = isDevice ? sEffectsHALInterfaces : sDevicesHALInterfaces;
+ auto ifaceVersionIt = findMostRecentVersion(interfaceMap);
+ auto siblingVersionIt = findMostRecentVersion(siblingInterfaceMap);
+ if (ifaceVersionIt != sAudioHALVersions.end() &&
+ siblingVersionIt != sAudioHALVersions.end() &&
+ // same major version
+ ifaceVersionIt->getMajorVersion() == siblingVersionIt->getMajorVersion()) {
+ void* rawInterface;
+ if (createHalService(std::max(*ifaceVersionIt, *siblingVersionIt), isDevice,
+ &rawInterface)) {
+ return rawInterface;
+ } else {
+ ALOGE("Failed to create HAL services with major %s, sibling %s!",
+ ifaceVersionIt->toString().c_str(), siblingVersionIt->toString().c_str());
+ }
+ } else {
+ ALOGE("Found no HAL version, main(%s) %s %s!", isDevice ? "Device" : "Effect",
+ (ifaceVersionIt == sAudioHALVersions.end()) ? "null"
+ : ifaceVersionIt->toString().c_str(),
+ (siblingVersionIt == sAudioHALVersions.end()) ? "null"
+ : siblingVersionIt->toString().c_str());
+ }
+ return nullptr;
+}
+
+} // namespace android::detail
diff --git a/media/libaudiohal/FactoryHalHidl.cpp b/media/libaudiohal/FactoryHalHidl.cpp
deleted file mode 100644
index 590fec5..0000000
--- a/media/libaudiohal/FactoryHalHidl.cpp
+++ /dev/null
@@ -1,124 +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.
- */
-
-#define LOG_TAG "FactoryHalHidl"
-
-#include <algorithm>
-#include <array>
-#include <utility>
-
-#include <media/audiohal/FactoryHalHidl.h>
-
-#include <dlfcn.h>
-
-#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <hidl/ServiceManagement.h>
-#include <hidl/Status.h>
-#include <utils/Log.h>
-
-namespace android::detail {
-
-namespace {
-/** Supported HAL versions, from most recent to least recent.
- */
-#define CONC_VERSION(maj, min) #maj "." #min
-#define DECLARE_VERSION(maj, min) std::make_pair(std::make_pair(maj, min), CONC_VERSION(maj, min))
-static constexpr std::array<std::pair<std::pair<int, int>, const char*>, 5> sAudioHALVersions = {
- DECLARE_VERSION(7, 1),
- DECLARE_VERSION(7, 0),
- DECLARE_VERSION(6, 0),
- DECLARE_VERSION(5, 0),
- DECLARE_VERSION(4, 0)
-};
-
-bool createHalService(const std::string& version, const std::string& interface,
- void** rawInterface) {
- const std::string libName = "libaudiohal@" + version + ".so";
- const std::string factoryFunctionName = "create" + interface;
- constexpr int dlMode = RTLD_LAZY;
- void* handle = nullptr;
- dlerror(); // clear
- handle = dlopen(libName.c_str(), dlMode);
- if (handle == nullptr) {
- const char* error = dlerror();
- ALOGE("Failed to dlopen %s: %s", libName.c_str(),
- error != nullptr ? error : "unknown error");
- return false;
- }
- void* (*factoryFunction)();
- *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
- if (!factoryFunction) {
- const char* error = dlerror();
- ALOGE("Factory function %s not found in library %s: %s",
- factoryFunctionName.c_str(), libName.c_str(),
- error != nullptr ? error : "unknown error");
- dlclose(handle);
- return false;
- }
- *rawInterface = (*factoryFunction)();
- ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
- factoryFunctionName.c_str(), libName.c_str());
- return true;
-}
-
-bool hasHalService(const std::string& package, const std::string& version,
- const std::string& interface) {
- using ::android::hidl::manager::V1_0::IServiceManager;
- sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
- if (!sm) {
- ALOGE("Failed to obtain HIDL ServiceManager");
- return false;
- }
- // Since audio HAL doesn't support multiple clients, avoid instantiating
- // the interface right away. Instead, query the transport type for it.
- using ::android::hardware::Return;
- using Transport = IServiceManager::Transport;
- const std::string fqName = package + "@" + version + "::" + interface;
- const std::string instance = "default";
- Return<Transport> transport = sm->getTransport(fqName, instance);
- if (!transport.isOk()) {
- ALOGE("Failed to obtain transport type for %s/%s: %s",
- fqName.c_str(), instance.c_str(), transport.description().c_str());
- return false;
- }
- return transport != Transport::EMPTY;
-}
-
-} // namespace
-
-void* createPreferredImpl(const InterfaceName& iface, const InterfaceName& siblingIface) {
- auto findMostRecentVersion = [](const InterfaceName& iface) {
- return std::find_if(detail::sAudioHALVersions.begin(), detail::sAudioHALVersions.end(),
- [&](const auto& v) { return hasHalService(iface.first, v.second, iface.second); });
- };
- auto ifaceVersionIt = findMostRecentVersion(iface);
- auto siblingVersionIt = findMostRecentVersion(siblingIface);
- if (ifaceVersionIt != detail::sAudioHALVersions.end() &&
- siblingVersionIt != detail::sAudioHALVersions.end() &&
- // same major version
- ifaceVersionIt->first.first == siblingVersionIt->first.first) {
- std::string libraryVersion =
- ifaceVersionIt->first >= siblingVersionIt->first ?
- ifaceVersionIt->second : siblingVersionIt->second;
- void* rawInterface;
- if (createHalService(libraryVersion, iface.second, &rawInterface)) {
- return rawInterface;
- }
- }
- return nullptr;
-}
-
-} // namespace android::detail
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index d30883a..bb5601f 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -12,13 +12,14 @@
srcs: [
"CoreConversionHelperHidl.cpp",
"DeviceHalHidl.cpp",
+ "DevicesFactoryHalEntry.cpp",
"DevicesFactoryHalHidl.cpp",
"StreamHalHidl.cpp",
],
}
filegroup {
- name: "audio_effect_hal_client_sources",
+ name: "audio_effect_hidl_hal_client_sources",
srcs: [
"EffectBufferHalHidl.cpp",
"EffectConversionHelperHidl.cpp",
@@ -28,6 +29,21 @@
}
cc_defaults {
+ name: "libaudiohal_hidl_default",
+ shared_libs: [
+ "android.hardware.audio.common-util",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "libaudiohal_deathhandler",
+ "libhidlbase",
+ "libhidlmemory",
+ ],
+ header_libs: [
+ "android.hardware.audio.common.util@all-versions",
+ ]
+}
+
+cc_defaults {
name: "libaudiohal_default",
cflags: [
@@ -37,28 +53,21 @@
"-fvisibility=hidden",
],
shared_libs: [
- "android.hardware.audio.common-util",
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
+ "audioclient-types-aidl-cpp",
"av-types-aidl-cpp",
"libaudiofoundation",
- "libaudiohal_deathhandler",
"libaudioutils",
"libbase",
"libbinder",
"libcutils",
"libfmq",
"libhardware",
- "libhidlbase",
- "libhidlmemory",
"liblog",
"libmedia_helper",
"libmediautils",
"libutils",
- "audioclient-types-aidl-cpp",
],
header_libs: [
- "android.hardware.audio.common.util@all-versions",
"libaudioclient_headers",
"libaudiohal_headers"
],
@@ -70,11 +79,14 @@
cc_library_shared {
name: "libaudiohal@4.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- ":audio_effect_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ ":audio_effect_hidl_hal_client_sources",
+ "EffectsFactoryHalEntry.cpp",
],
shared_libs: [
"android.hardware.audio.common@4.0",
@@ -93,11 +105,14 @@
cc_library_shared {
name: "libaudiohal@5.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- ":audio_effect_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ ":audio_effect_hidl_hal_client_sources",
+ "EffectsFactoryHalEntry.cpp",
],
shared_libs: [
"android.hardware.audio.common@5.0",
@@ -116,11 +131,14 @@
cc_library_shared {
name: "libaudiohal@6.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- ":audio_effect_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ ":audio_effect_hidl_hal_client_sources",
+ "EffectsFactoryHalEntry.cpp",
],
shared_libs: [
"android.hardware.audio.common@6.0",
@@ -139,9 +157,12 @@
cc_library_static {
name: "libaudiohal.effect@7.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
- ":audio_effect_hal_client_sources",
+ ":audio_effect_hidl_hal_client_sources",
],
static_libs: [
"android.hardware.audio.common@7.0",
@@ -158,10 +179,13 @@
cc_library_shared {
name: "libaudiohal@7.0",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ "EffectsFactoryHalEntry.cpp",
],
static_libs: [
"android.hardware.audio.common@7.0",
@@ -182,10 +206,13 @@
cc_library_shared {
name: "libaudiohal@7.1",
- defaults: ["libaudiohal_default"],
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_hidl_default"
+ ],
srcs: [
":audio_core_hal_client_sources",
- "EffectsFactoryHalHidlEntry.cpp",
+ "EffectsFactoryHalEntry.cpp",
],
static_libs: [
"android.hardware.audio.common@7.0",
@@ -207,3 +234,22 @@
"-include common/all-versions/VersionMacro.h",
]
}
+
+cc_library_shared {
+ name: "libaudiohal@aidl",
+ defaults: [
+ "libaudiohal_default",
+ "latest_android_hardware_audio_common_ndk_shared",
+ "latest_android_hardware_audio_core_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "DevicesFactoryHalEntry.cpp",
+ "DevicesFactoryHalAidl.cpp",
+ "EffectsFactoryHalAidl.cpp",
+ "EffectsFactoryHalEntry.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ]
+}
\ No newline at end of file
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
new file mode 100644
index 0000000..29fb558
--- /dev/null
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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 "DevicesFactoryHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <android/binder_manager.h>
+#include <utils/Log.h>
+
+#include "DevicesFactoryHalAidl.h"
+
+using ::android::detail::AudioHalVersionInfo;
+
+namespace android {
+
+DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> iconfig) {
+ ALOG_ASSERT(iconfig != nullptr, "Provided default IConfig service is NULL");
+ mIConfig = std::move(iconfig);
+}
+
+void DevicesFactoryHalAidl::onFirstRef() {
+ ALOGE("%s not implemented yet", __func__);
+}
+
+// Opens a device with the specified name. To close the device, it is
+// necessary to release references to the returned object.
+status_t DevicesFactoryHalAidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
+ if (name == nullptr || device == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t DevicesFactoryHalAidl::getHalPids(std::vector<pid_t> *pids) {
+ if (pids == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t DevicesFactoryHalAidl::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
+ if (callback == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+AudioHalVersionInfo DevicesFactoryHalAidl::getHalVersion() const {
+ int32_t versionNumber = 0;
+ if (mIConfig) {
+ if (!mIConfig->getInterfaceVersion(&versionNumber).isOk()) {
+ ALOGE("%s getInterfaceVersion failed", __func__);
+ } else {
+ ALOGI("%s getInterfaceVersion %d", __func__, versionNumber);
+ }
+ }
+ // AIDL does not have minor version, fill 0 for all versions
+ return AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, versionNumber);
+}
+
+// Main entry-point to the shared library.
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
+ auto service = IConfig::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(IConfig::descriptor)));
+ return service ? new DevicesFactoryHalAidl(service) : nullptr;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
new file mode 100644
index 0000000..f4812af
--- /dev/null
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -0,0 +1,48 @@
+/*
+ * 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/core/IConfig.h>
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <utils/RefBase.h>
+
+using namespace ::aidl::android::hardware::audio::core;
+
+namespace android {
+
+class DevicesFactoryHalAidl : public DevicesFactoryHalInterface
+{
+ public:
+ explicit DevicesFactoryHalAidl(std::shared_ptr<IConfig> iConfig);
+ void onFirstRef() override;
+
+ // Opens a device with the specified name. To close the device, it is
+ // necessary to release references to the returned object.
+ status_t openDevice(const char *name, sp<DeviceHalInterface> *device) override;
+
+ status_t getHalPids(std::vector<pid_t> *pids) override;
+
+ status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
+
+ android::detail::AudioHalVersionInfo getHalVersion() const override;
+
+ private:
+ std::shared_ptr<IConfig> mIConfig;
+ virtual ~DevicesFactoryHalAidl() = default;
+};
+
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp b/media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
similarity index 74%
copy from media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
copy to media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
index 2c6f2c6..5bf6d89 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
@@ -14,8 +14,10 @@
* limitations under the License.
*/
-extern "C" void* createIEffectsFactoryImpl();
+#include "android/media/AudioHalVersion.h"
-extern "C" __attribute__((visibility("default"))) void* createIEffectsFactory() {
- return createIEffectsFactoryImpl();
+extern "C" void* createIDevicesFactoryImpl();
+
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
+ return createIDevicesFactoryImpl();
}
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
index 4069a6b..9f06f83 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
@@ -29,6 +29,7 @@
#include "DeviceHalHidl.h"
#include "DevicesFactoryHalHidl.h"
+using ::android::detail::AudioHalVersionInfo;
using ::android::hardware::audio::CPP_VERSION::IDevice;
using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::Result;
using ::android::hardware::Return;
@@ -226,8 +227,13 @@
return mDeviceFactories;
}
+
+AudioHalVersionInfo DevicesFactoryHalHidl::getHalVersion() const {
+ return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
+}
+
// Main entry-point to the shared library.
-extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
return service ? new DevicesFactoryHalHidl(service) : nullptr;
}
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index ffd229d..5294728 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -45,7 +45,7 @@
status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
- float getHalVersion() const override { return MAJOR_VERSION + (float)MINOR_VERSION / 10; }
+ android::detail::AudioHalVersionInfo getHalVersion() const override;
private:
friend class ServiceNotificationListener;
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
new file mode 100644
index 0000000..7aec859
--- /dev/null
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -0,0 +1,128 @@
+/*
+ * 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 <random>
+#define LOG_TAG "EffectsFactoryHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <android/binder_manager.h>
+#include <utils/Log.h>
+
+#include "EffectsFactoryHalAidl.h"
+
+using aidl::android::hardware::audio::effect::IFactory;
+using android::detail::AudioHalVersionInfo;
+
+namespace android {
+namespace effect {
+
+EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory) {
+ ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
+ mEffectsFactory = effectsFactory;
+}
+
+status_t EffectsFactoryHalAidl::queryNumberEffects(uint32_t *pNumEffects) {
+ if (pNumEffects == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t EffectsFactoryHalAidl::getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) {
+ if (index < 0 || pDescriptor == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t EffectsFactoryHalAidl::getDescriptor(const effect_uuid_t* pEffectUuid,
+ effect_descriptor_t* pDescriptor) {
+ if (pEffectUuid == nullptr || pDescriptor == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t EffectsFactoryHalAidl::getDescriptors(const effect_uuid_t* pEffectType,
+ std::vector<effect_descriptor_t>* descriptors) {
+ if (pEffectType == nullptr || descriptors == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId,
+ int32_t ioId, int32_t deviceId __unused,
+ sp<EffectHalInterface>* effect) {
+ if (pEffectUuid == nullptr || effect == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet %d %d", __func__, sessionId, ioId);
+ return INVALID_OPERATION;
+}
+
+status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
+ ALOGE("%s not implemented yet, fd %d", __func__, fd);
+ return INVALID_OPERATION;
+}
+
+status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
+ if (size <= 0 || buffer == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+status_t EffectsFactoryHalAidl::mirrorBuffer(void* external, size_t size,
+ sp<EffectBufferHalInterface>* buffer) {
+ if (external == nullptr || size <= 0 || buffer == nullptr) {
+ return BAD_VALUE;
+ }
+ ALOGE("%s not implemented yet", __func__);
+ return INVALID_OPERATION;
+}
+
+AudioHalVersionInfo EffectsFactoryHalAidl::getHalVersion() const {
+ int32_t versionNumber = 0;
+ if (mEffectsFactory) {
+ if (!mEffectsFactory->getInterfaceVersion(&versionNumber).isOk()) {
+ ALOGE("%s getInterfaceVersion failed", __func__);
+ } else {
+ ALOGI("%s getInterfaceVersion %d", __func__, versionNumber);
+ }
+ }
+ // AIDL does not have minor version, fill 0 for all versions
+ return AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, versionNumber);
+}
+
+} // namespace effect
+
+// When a shared library is built from a static library, even explicit
+// exports from a static library are optimized out unless actually used by
+// the shared library. See EffectsFactoryHalEntry.cpp.
+extern "C" void* createIEffectsFactoryImpl() {
+ auto factory = IFactory::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(IFactory::descriptor)));
+ return factory ? new effect::EffectsFactoryHalAidl(factory) : nullptr;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
new file mode 100644
index 0000000..d6b5684
--- /dev/null
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -0,0 +1,62 @@
+/*
+ * 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 <media/audiohal/EffectsFactoryHalInterface.h>
+
+namespace android {
+namespace effect {
+
+using namespace aidl::android::hardware::audio::effect;
+
+class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface {
+ public:
+ explicit EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory);
+
+ // Returns the number of different effects in all loaded libraries.
+ status_t queryNumberEffects(uint32_t *pNumEffects) override;
+
+ // Returns a descriptor of the next available effect.
+ status_t getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) override;
+
+ status_t getDescriptor(const effect_uuid_t* pEffectUuid,
+ effect_descriptor_t* pDescriptor) override;
+
+ status_t getDescriptors(const effect_uuid_t* pEffectType,
+ std::vector<effect_descriptor_t>* descriptors) override;
+
+ // Creates an effect engine of the specified type.
+ // To release the effect engine, it is necessary to release references
+ // to the returned effect object.
+ status_t createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId, int32_t ioId,
+ int32_t deviceId, sp<EffectHalInterface>* effect) override;
+
+ status_t dumpEffects(int fd) override;
+
+ status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
+ status_t mirrorBuffer(void* external, size_t size,
+ sp<EffectBufferHalInterface>* buffer) override;
+
+ android::detail::AudioHalVersionInfo getHalVersion() const override;
+
+ private:
+ std::shared_ptr<IFactory> mEffectsFactory;
+ virtual ~EffectsFactoryHalAidl() = default;
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp b/media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
similarity index 94%
rename from media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
rename to media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
index 2c6f2c6..f6ad99a 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "android/media/AudioHalVersion.h"
+
extern "C" void* createIEffectsFactoryImpl();
extern "C" __attribute__((visibility("default"))) void* createIEffectsFactory() {
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 3470380..172ebdf 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -31,6 +31,9 @@
#include "EffectHalHidl.h"
#include "EffectsFactoryHalHidl.h"
+#include "android/media/AudioHalVersion.h"
+
+using ::android::detail::AudioHalVersionInfo;
using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
using ::android::hardware::Return;
@@ -77,7 +80,7 @@
EffectsFactoryHalHidl::EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory)
: EffectConversionHelperHidl("EffectsFactory"), mCache(new EffectDescriptorCache) {
ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
- mEffectsFactory = effectsFactory;
+ mEffectsFactory = std::move(effectsFactory);
}
status_t EffectsFactoryHalHidl::queryNumberEffects(uint32_t *pNumEffects) {
@@ -221,11 +224,15 @@
return EffectBufferHalHidl::mirror(external, size, buffer);
}
+AudioHalVersionInfo EffectsFactoryHalHidl::getHalVersion() const {
+ return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
+}
+
} // namespace effect
// When a shared library is built from a static library, even explicit
// exports from a static library are optimized out unless actually used by
-// the shared library. See EffectsFactoryHalHidlEntry.cpp.
+// the shared library. See EffectsFactoryHalEntry.cpp.
extern "C" void* createIEffectsFactoryImpl() {
auto service = hardware::audio::effect::CPP_VERSION::IEffectsFactory::getService();
return service ? new effect::EffectsFactoryHalHidl(service) : nullptr;
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 7ccddc6..9875154 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
-#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
+#pragma once
#include <memory>
@@ -32,39 +31,37 @@
class EffectDescriptorCache;
-class EffectsFactoryHalHidl : public EffectsFactoryHalInterface, public EffectConversionHelperHidl
-{
+class EffectsFactoryHalHidl final : public EffectsFactoryHalInterface,
+ public EffectConversionHelperHidl {
public:
EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory);
// Returns the number of different effects in all loaded libraries.
- virtual status_t queryNumberEffects(uint32_t *pNumEffects);
+ status_t queryNumberEffects(uint32_t *pNumEffects) override;
// Returns a descriptor of the next available effect.
- virtual status_t getDescriptor(uint32_t index,
- effect_descriptor_t *pDescriptor);
+ status_t getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) override;
- virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
- effect_descriptor_t *pDescriptor);
+ status_t getDescriptor(const effect_uuid_t* pEffectUuid,
+ effect_descriptor_t* pDescriptor) override;
- virtual status_t getDescriptors(const effect_uuid_t *pEffectType,
- std::vector<effect_descriptor_t> *descriptors);
+ status_t getDescriptors(const effect_uuid_t* pEffectType,
+ std::vector<effect_descriptor_t>* descriptors) override;
// Creates an effect engine of the specified type.
// To release the effect engine, it is necessary to release references
// to the returned effect object.
- virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
- int32_t sessionId, int32_t ioId, int32_t deviceId,
- sp<EffectHalInterface> *effect);
+ status_t createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId, int32_t ioId,
+ int32_t deviceId, sp<EffectHalInterface>* effect) override;
- virtual status_t dumpEffects(int fd);
-
- virtual float getHalVersion() { return MAJOR_VERSION + (float)MINOR_VERSION / 10; }
+ status_t dumpEffects(int fd) override;
status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
status_t mirrorBuffer(void* external, size_t size,
sp<EffectBufferHalInterface>* buffer) override;
+ android::detail::AudioHalVersionInfo getHalVersion() const override;
+
private:
sp<IEffectsFactory> mEffectsFactory;
std::unique_ptr<EffectDescriptorCache> mCache;
@@ -72,5 +69,3 @@
} // namespace effect
} // namespace android
-
-#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h b/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h
new file mode 100644
index 0000000..6e09463
--- /dev/null
+++ b/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h
@@ -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.
+ */
+
+#pragma once
+
+#include <string>
+#include <utility>
+#include <android/media/AudioHalVersion.h>
+
+namespace android::detail {
+
+class AudioHalVersionInfo : public android::media::AudioHalVersion {
+ public:
+ AudioHalVersionInfo(Type halType, int halMajor, int halMinor = 0) {
+ type = halType;
+ major = halMajor;
+ minor = halMinor;
+ }
+
+ Type getType() const { return type; }
+
+ int getMajorVersion() const { return major; }
+
+ int getMinorVersion() const { return minor; }
+
+ /** Keep HIDL version format as is for backward compatibility, only add prefix for AIDL. */
+ std::string toVersionString() const {
+ std::string versionStr =
+ android::internal::ToString(major) + "." + android::internal::ToString(minor);
+ if (type == Type::AIDL) {
+ return "aidl";
+ } else {
+ return versionStr;
+ }
+ }
+};
+
+} // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index 17010e6..be3a723 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
-#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
+#pragma once
#include <media/audiohal/DeviceHalInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <vector>
+#include "AudioHalVersionInfo.h"
+
namespace android {
class DevicesFactoryHalCallback : public RefBase
@@ -43,7 +44,7 @@
// The callback can be only set once.
virtual status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) = 0;
- virtual float getHalVersion() const = 0;
+ virtual android::detail::AudioHalVersionInfo getHalVersion() const = 0;
static sp<DevicesFactoryHalInterface> create();
@@ -55,5 +56,3 @@
};
} // namespace android
-
-#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
diff --git a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
index 3e505bd..d740fe9 100644
--- a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -14,14 +14,16 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
-#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
+#pragma once
#include <media/audiohal/EffectHalInterface.h>
#include <system/audio_effect.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include "AudioHalVersionInfo.h"
+#include "FactoryHal.h"
+
namespace android {
class EffectsFactoryHalInterface : public RefBase
@@ -49,16 +51,16 @@
virtual status_t dumpEffects(int fd) = 0;
- virtual float getHalVersion() = 0;
-
static sp<EffectsFactoryHalInterface> create();
virtual status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
virtual status_t mirrorBuffer(void* external, size_t size,
sp<EffectBufferHalInterface>* buffer) = 0;
+ virtual android::detail::AudioHalVersionInfo getHalVersion() const = 0;
+
// Helper function to compare effect uuid to EFFECT_UUID_NULL.
- static bool isNullUuid(const effect_uuid_t *pEffectUuid);
+ static bool isNullUuid(const effect_uuid_t* pEffectUuid);
protected:
// Subclasses can not be constructed directly by clients.
@@ -68,5 +70,3 @@
};
} // namespace android
-
-#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
diff --git a/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h b/media/libaudiohal/include/media/audiohal/FactoryHal.h
similarity index 62%
rename from media/libaudiohal/include/media/audiohal/FactoryHalHidl.h
rename to media/libaudiohal/include/media/audiohal/FactoryHal.h
index 866dd3e..4776d98 100644
--- a/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h
+++ b/media/libaudiohal/include/media/audiohal/FactoryHal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,24 +14,19 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
-#define ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
+#pragma once
#include <string>
#include <utility>
-
#include <utils/StrongPointer.h>
+#include "AudioHalVersionInfo.h"
+
namespace android {
-// The pair of the interface's package name and the interface name,
-// e.g. <"android.hardware.audio", "IDevicesFactory">.
-// Splitting is used for easier construction of versioned names (FQNs).
-using InterfaceName = std::pair<std::string, std::string>;
-
namespace detail {
-void* createPreferredImpl(const InterfaceName& iface, const InterfaceName& siblingIface);
+void* createPreferredImpl(bool isCore);
} // namespace detail
@@ -45,17 +40,12 @@
* shared libraries the loader function considers which interface among two has the most
* recent version. Thus, a pair of interface names must be passed in.
*
- * @param iface the interface that needs to be created.
- * @param siblingIface the interface which occupies the same shared library.
+ * @param isCore Indicating if this is audio Core HAL service interface.
* @return the preferred available implementation or nullptr if none are available.
*/
+
template <class Interface>
-static sp<Interface> createPreferredImpl(
- const InterfaceName& iface, const InterfaceName& siblingIface) {
- return sp<Interface>{
- static_cast<Interface*>(detail::createPreferredImpl(iface, siblingIface))};
+static sp<Interface> createPreferredImpl(bool isCore) {
+ return sp<Interface>{static_cast<Interface*>(detail::createPreferredImpl(isCore))};
}
-
} // namespace android
-
-#endif // ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index e6fdb1d..c2b82d1 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -297,6 +297,27 @@
return NO_ERROR;
}
+void AudioMixer::Track::unprepareForTee() {
+ ALOGV("AudioMixer::%s", __func__);
+ if (mTeeBufferProvider.get() != nullptr) {
+ mTeeBufferProvider.reset(nullptr);
+ reconfigureBufferProviders();
+ }
+}
+
+status_t AudioMixer::Track::prepareForTee() {
+ ALOGV("AudioMixer::%s(%p) teeBuffer=%p", __func__, this, teeBuffer);
+ unprepareForTee();
+ if (teeBuffer != nullptr) {
+ const size_t frameSize = audio_bytes_per_frame(channelCount + mHapticChannelCount, mFormat);
+ mTeeBufferProvider.reset(new TeeBufferProvider(
+ frameSize, frameSize, kCopyBufferFrameCount,
+ (uint8_t*)teeBuffer, mTeeBufferFrameCount));
+ reconfigureBufferProviders();
+ }
+ return NO_ERROR;
+}
+
void AudioMixer::Track::clearContractedBuffer()
{
if (mAdjustChannelsBufferProvider.get() != nullptr) {
@@ -305,10 +326,20 @@
}
}
+void AudioMixer::Track::clearTeeFrameCopied() {
+ if (mTeeBufferProvider.get() != nullptr) {
+ static_cast<TeeBufferProvider*>(mTeeBufferProvider.get())->clearFramesCopied();
+ }
+}
+
void AudioMixer::Track::reconfigureBufferProviders()
{
// configure from upstream to downstream buffer providers.
bufferProvider = mInputBufferProvider;
+ if (mTeeBufferProvider != nullptr) {
+ mTeeBufferProvider->setBufferProvider(bufferProvider);
+ bufferProvider = mTeeBufferProvider.get();
+ }
if (mAdjustChannelsBufferProvider.get() != nullptr) {
mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
bufferProvider = mAdjustChannelsBufferProvider.get();
@@ -420,6 +451,20 @@
track->mHapticMaxAmplitude = hapticMaxAmplitude;
}
} break;
+ case TEE_BUFFER:
+ if (track->teeBuffer != valueBuf) {
+ track->teeBuffer = valueBuf;
+ ALOGV("setParameter(TRACK, TEE_BUFFER, %p)", valueBuf);
+ track->prepareForTee();
+ }
+ break;
+ case TEE_BUFFER_FRAME_COUNT:
+ if (track->mTeeBufferFrameCount != valueInt) {
+ track->mTeeBufferFrameCount = valueInt;
+ ALOGV("setParameter(TRACK, TEE_BUFFER_FRAME_COUNT, %i)", valueInt);
+ track->prepareForTee();
+ }
+ break;
default:
LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
}
@@ -500,6 +545,8 @@
track->mReformatBufferProvider->reset();
} else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
track->mAdjustChannelsBufferProvider->reset();
+ } else if (track->mTeeBufferProvider.get() != nullptr) {
+ track->mTeeBufferProvider->reset();
}
track->mInputBufferProvider = bufferProvider;
@@ -565,6 +612,7 @@
if (t->mKeepContractedChannels) {
t->clearContractedBuffer();
}
+ t->clearTeeFrameCopied();
}
}
diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp
index f30eb54..fd06991 100644
--- a/media/libaudioprocessing/AudioMixerBase.cpp
+++ b/media/libaudioprocessing/AudioMixerBase.cpp
@@ -143,6 +143,7 @@
// setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
t->mainBuffer = NULL;
t->auxBuffer = NULL;
+ t->teeBuffer = nullptr;
t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
t->mFormat = format;
t->mMixerInFormat = kUseFloat && kUseNewMixer ?
@@ -150,6 +151,7 @@
t->mMixerChannelMask = audio_channel_mask_from_representation_and_bits(
AUDIO_CHANNEL_REPRESENTATION_POSITION, AUDIO_CHANNEL_OUT_STEREO);
t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask);
+ t->mTeeBufferFrameCount = 0;
status_t status = postCreateTrack(t.get());
if (status != OK) return status;
mTracks[name] = t;
@@ -401,6 +403,20 @@
invalidate();
}
} break;
+ case TEE_BUFFER:
+ if (track->teeBuffer != valueBuf) {
+ track->teeBuffer = valueBuf;
+ ALOGV("setParameter(TRACK, TEE_BUFFER, %p)", valueBuf);
+ invalidate();
+ }
+ break;
+ case TEE_BUFFER_FRAME_COUNT:
+ if (track->mTeeBufferFrameCount != valueInt) {
+ track->mTeeBufferFrameCount = valueInt;
+ ALOGV("setParameter(TRACK, TEE_BUFFER_FRAME_COUNT, %i)", valueInt);
+ invalidate();
+ }
+ break;
default:
LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
}
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index 4658db8..a9944fb 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -739,5 +739,21 @@
mContractedWrittenFrames = 0;
CopyBufferProvider::reset();
}
+
+void TeeBufferProvider::copyFrames(void *dst, const void *src, size_t frames) {
+ memcpy(dst, src, frames * mInputFrameSize);
+ if (int teeBufferFrameLeft = mTeeBufferFrameCount - mFrameCopied; teeBufferFrameLeft < frames) {
+ ALOGW("Unable to copy all frames to tee buffer, %d frames dropped",
+ (int)frames - teeBufferFrameLeft);
+ frames = teeBufferFrameLeft;
+ }
+ memcpy(mTeeBuffer + mFrameCopied * mInputFrameSize, src, frames * mInputFrameSize);
+ mFrameCopied += frames;
+}
+
+void TeeBufferProvider::clearFramesCopied() {
+ mFrameCopied = 0;
+}
+
// ----------------------------------------------------------------------------
} // namespace android
diff --git a/media/libaudioprocessing/include/media/AudioMixer.h b/media/libaudioprocessing/include/media/AudioMixer.h
index 2993a60..b39fb92 100644
--- a/media/libaudioprocessing/include/media/AudioMixer.h
+++ b/media/libaudioprocessing/include/media/AudioMixer.h
@@ -96,7 +96,10 @@
void unprepareForReformat();
status_t prepareForAdjustChannels(size_t frames);
void unprepareForAdjustChannels();
+ void unprepareForTee();
+ status_t prepareForTee();
void clearContractedBuffer();
+ void clearTeeFrameCopied();
bool setPlaybackRate(const AudioPlaybackRate &playbackRate);
void reconfigureBufferProviders();
@@ -108,20 +111,22 @@
* all pre-mixer track buffer conversions outside the AudioMixer class.
*
* 1) mInputBufferProvider: The AudioTrack buffer provider.
- * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
+ * 2) mTeeBufferProvider: If not NULL, copy the data to tee buffer.
+ * 3) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
* channel format to another. Expanded channels are filled with zeros and put at the end
* of each audio frame. Contracted channels are copied to the end of the buffer.
- * 3) mReformatBufferProvider: If not NULL, performs the audio reformat to
+ * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
* match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
* requires reformat. For example, it may convert floating point input to
* PCM_16_bit if that's required by the downmixer.
- * 4) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
+ * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
* the number of channels required by the mixer sink.
- * 5) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
+ * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
* the downmixer requirements to the mixer engine input requirements.
- * 6) mTimestretchBufferProvider: Adds timestretching for playback rate
+ * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
*/
AudioBufferProvider* mInputBufferProvider; // externally provided buffer provider.
+ std::unique_ptr<PassthruBufferProvider> mTeeBufferProvider;
std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
diff --git a/media/libaudioprocessing/include/media/AudioMixerBase.h b/media/libaudioprocessing/include/media/AudioMixerBase.h
index 3419816..caccb6a 100644
--- a/media/libaudioprocessing/include/media/AudioMixerBase.h
+++ b/media/libaudioprocessing/include/media/AudioMixerBase.h
@@ -68,6 +68,10 @@
// 0x4004 reserved
MIXER_FORMAT = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output
+ // 0x4007, 0x4008, 0x4009 is defined for haptic stuff in AudioMixer.h
+ TEE_BUFFER = 0x400A,
+ TEE_BUFFER_FORMAT = 0x400B,
+ TEE_BUFFER_FRAME_COUNT = 0x400C,
// for target RESAMPLE
SAMPLE_RATE = 0x4100, // Configure sample rate conversion on this track name;
// parameter 'value' is the new sample rate in Hz.
@@ -271,6 +275,7 @@
uint32_t sampleRate;
int32_t* mainBuffer;
int32_t* auxBuffer;
+ int32_t* teeBuffer;
int32_t sessionId;
@@ -290,6 +295,8 @@
audio_channel_mask_t mMixerChannelMask;
uint32_t mMixerChannelCount;
+ int32_t mTeeBufferFrameCount;
+
protected:
// hooks
diff --git a/media/libaudioprocessing/include/media/BufferProviders.h b/media/libaudioprocessing/include/media/BufferProviders.h
index b3ab8a5..7a41002 100644
--- a/media/libaudioprocessing/include/media/BufferProviders.h
+++ b/media/libaudioprocessing/include/media/BufferProviders.h
@@ -279,6 +279,27 @@
size_t mContractedWrittenFrames;
size_t mContractedOutputFrameSize; // contracted output frame size
};
+
+class TeeBufferProvider : public CopyBufferProvider {
+public:
+ TeeBufferProvider(
+ size_t inputFrameSize, size_t outputFrameSize,
+ size_t bufferFrameCount, uint8_t* teeBuffer, int teeBufferFrameCount)
+ : CopyBufferProvider(inputFrameSize, outputFrameSize, bufferFrameCount),
+ mTeeBuffer(teeBuffer), mTeeBufferFrameCount(teeBufferFrameCount),
+ mFrameCopied(0) {};
+
+ void copyFrames(void *dst, const void *src, size_t frames) override;
+
+ void clearFramesCopied();
+
+protected:
+ AudioBufferProvider *mTrackBufferProvider;
+ uint8_t* mTeeBuffer;
+ const int mTeeBufferFrameCount;
+ int mFrameCopied;
+};
+
// ----------------------------------------------------------------------------
} // namespace android
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index 2defa4e..fa26e60 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <cstddef>
#define LOG_TAG "BundleContext"
#include <Utils.h>
@@ -23,8 +24,9 @@
namespace aidl::android::hardware::audio::effect {
RetCode BundleContext::init() {
+ std::lock_guard lg(mMutex);
// init with pre-defined preset NORMAL
- for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
mBandGaindB[i] = lvm::kSoftPresets[0 /* normal */][i];
}
@@ -57,6 +59,7 @@
}
void BundleContext::deInit() {
+ std::lock_guard lg(mMutex);
if (mInstance) {
LVM_DelInstanceHandle(&mInstance);
mInstance = nullptr;
@@ -65,14 +68,17 @@
RetCode BundleContext::enable() {
LVM_ControlParams_t params;
- 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;
+ {
+ 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;
+ }
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
}
- RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
- RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
mEnabled = true;
// LvmEffect_limitLevel(pContext);
return RetCode::SUCCESS;
@@ -80,14 +86,17 @@
RetCode BundleContext::disable() {
LVM_ControlParams_t params;
- 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;
+ {
+ 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;
+ }
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
}
- RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
- RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
mEnabled = false;
// LvmEffect_limitLevel(pContext);
return RetCode::SUCCESS;
@@ -148,27 +157,29 @@
// android::VolumeSetVolumeLevel(pContext, (int16_t)(maxdB * 100));
LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
- RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
- RetCode::ERROR_EFFECT_LIB_ERROR, "");
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "");
+ params.VC_Balance = pandB;
- params.VC_Balance = pandB;
-
- RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
- RetCode::ERROR_EFFECT_LIB_ERROR, "");
-
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, "");
+ }
mVolumeStereo = volume;
return RetCode::SUCCESS;
}
-RetCode BundleContext::setEqualizerPreset(const int presetIdx) {
+RetCode BundleContext::setEqualizerPreset(const std::size_t presetIdx) {
if (presetIdx < 0 || presetIdx >= lvm::MAX_NUM_PRESETS) {
return RetCode::ERROR_ILLEGAL_PARAMETER;
}
std::vector<Equalizer::BandLevel> bandLevels;
bandLevels.reserve(lvm::MAX_NUM_BANDS);
- for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- bandLevels.emplace_back(Equalizer::BandLevel{i, lvm::kSoftPresets[presetIdx][i]});
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ bandLevels.emplace_back(
+ Equalizer::BandLevel{static_cast<int32_t>(i), lvm::kSoftPresets[presetIdx][i]});
}
RetCode ret = updateControlParameter(bandLevels);
@@ -197,8 +208,8 @@
std::vector<Equalizer::BandLevel> BundleContext::getEqualizerBandLevels() const {
std::vector<Equalizer::BandLevel> bandLevels;
bandLevels.reserve(lvm::MAX_NUM_BANDS);
- for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- bandLevels.emplace_back(Equalizer::BandLevel{i, mBandGaindB[i]});
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i), mBandGaindB[i]});
}
return bandLevels;
}
@@ -221,17 +232,20 @@
}
LVM_ControlParams_t params;
- RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
- RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
- for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
- params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
- params.pEQNB_BandDefinition[i].Gain = tempLevel[i];
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
+ params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
+ params.pEQNB_BandDefinition[i].Gain = tempLevel[i];
+ }
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
}
-
- RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
- RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
mBandGaindB = tempLevel;
LOG(INFO) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGaindB);
@@ -296,7 +310,7 @@
static LVM_EQNB_BandDef_t* BandDefs = []() {
static LVM_EQNB_BandDef_t tempDefs[lvm::MAX_NUM_BANDS];
/* N-Band Equaliser parameters */
- for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+ for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
tempDefs[i].Frequency = lvm::kPresetsFrequencies[i];
tempDefs[i].QFactor = lvm::kPresetsQFactors[i];
tempDefs[i].Gain = lvm::kSoftPresets[0/* normal */][i];
@@ -323,4 +337,26 @@
return HeadroomBandDef;
}
+IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+
+ auto frameSize = getInputFrameSize();
+ RETURN_VALUE_IF(0== frameSize, status, "nullContext");
+
+ 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 (lvmStatus != LVM_SUCCESS) {
+ LOG(ERROR) << __func__ << lvmStatus;
+ return {EX_UNSUPPORTED_OPERATION, 0, 0};
+ }
+ LOG(DEBUG) << __func__ << " done processing";
+ return {STATUS_OK, samples, samples};
+}
+
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index 616ab78..7b38e66 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -17,7 +17,9 @@
#pragma once
#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
#include <array>
+#include <cstddef>
#include "BundleTypes.h"
#include "effect-impl/EffectContext.h"
@@ -43,8 +45,6 @@
RetCode enable();
RetCode disable();
- LVM_Handle_t getLvmInstance() const { return mInstance; }
-
void setSampleRate (const int sampleRate) { mSampleRate = sampleRate; }
int getSampleRate() const { return mSampleRate; }
@@ -55,18 +55,21 @@
return mChMask;
}
- RetCode setEqualizerPreset(const int presetIdx);
+ 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 setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
- Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; };
+ Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
private:
+ std::mutex mMutex;
const lvm::BundleEffectType mType;
bool mEnabled = false;
- LVM_Handle_t mInstance = nullptr;
+ LVM_Handle_t mInstance GUARDED_BY(mMutex);
aidl::android::media::audio::common::AudioDeviceDescription mVirtualizerForcedDevice;
aidl::android::media::audio::common::AudioChannelLayout mChMask;
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index 48ba598..b1bf04c 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -93,8 +93,8 @@
}
ndk::ScopedAStatus EffectBundleAidl::setParameterCommon(const Parameter& param) {
- std::lock_guard lg(mMutex);
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
auto tag = param.getTag();
switch (tag) {
case Parameter::common:
@@ -133,7 +133,7 @@
auto tag = specific.getTag();
RETURN_IF(tag != Parameter::Specific::equalizer, EX_ILLEGAL_ARGUMENT,
"specificParamNotSupported");
- RETURN_IF(mContext == nullptr, EX_NULL_POINTER , "nullContext");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
auto& eq = specific.get<Parameter::Specific::equalizer>();
auto eqTag = eq.getTag();
@@ -174,7 +174,6 @@
ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Tag& tag,
Parameter::Specific* specific) {
- std::lock_guard lg(mMutex);
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
Equalizer eqParam;
switch (tag) {
@@ -200,12 +199,16 @@
std::shared_ptr<EffectContext> EffectBundleAidl::createContext(const Parameter::Common& common) {
if (mContext) {
LOG(DEBUG) << __func__ << " context already exist";
- return mContext;
+ } else {
+ // GlobalSession is a singleton
+ mContext = GlobalSession::getGlobalSession().createSession(mType, 1 /* statusFmqDepth */,
+ common);
}
- // GlobalSession is a singleton
- mContext =
- GlobalSession::getGlobalSession().createSession(mType, 1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> EffectBundleAidl::getContext() {
return mContext;
}
@@ -217,29 +220,30 @@
return RetCode::SUCCESS;
}
+ndk::ScopedAStatus EffectBundleAidl::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();
+}
+
// Processing method running in EffectWorker thread.
IEffect::Status EffectBundleAidl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
- LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << sampleToProcess;
- if (!mContext) {
- LOG(ERROR) << __func__ << " nullContext";
- return {EX_NULL_POINTER, 0, 0};
- }
-
- auto frameSize = mContext->getInputFrameSize();
- if (0 == frameSize) {
- LOG(ERROR) << __func__ << " frameSizeIs0";
- return {EX_ILLEGAL_ARGUMENT, 0, 0};
- }
-
- LOG(DEBUG) << __func__ << " start processing";
- LVM_UINT16 frames = sampleToProcess * sizeof(float) / frameSize;
- LVM_ReturnStatus_en lvmStatus = LVM_Process(mContext->getLvmInstance(), in, out, frames, 0);
- if (lvmStatus != LVM_SUCCESS) {
- LOG(ERROR) << __func__ << lvmStatus;
- return {EX_UNSUPPORTED_OPERATION, 0, 0};
- }
- LOG(DEBUG) << __func__ << " done processing";
- return {STATUS_OK, sampleToProcess, sampleToProcess};
+ return mContext->lvmProcess(in, out, sampleToProcess);
}
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
index 5fdf301..9e2f656 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -18,7 +18,6 @@
#include <functional>
#include <map>
#include <memory>
-#include <mutex>
#include <aidl/android/hardware/audio/effect/BnEffect.h>
#include <android-base/logging.h>
@@ -42,28 +41,21 @@
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;
+ std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
- ndk::ScopedAStatus commandStart() override {
- mContext->enable();
- return ndk::ScopedAStatus::ok();
- }
- ndk::ScopedAStatus commandStop() override {
- mContext->disable();
- return ndk::ScopedAStatus::ok();
- }
- ndk::ScopedAStatus commandReset() override {
- mContext->disable();
- return ndk::ScopedAStatus::ok();
- }
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+
+ std::string getEffectName() override { return "EqualizerBundle"; }
private:
+ std::shared_ptr<BundleContext> mContext;
const Descriptor* mDescriptor;
lvm::BundleEffectType mType = lvm::BundleEffectType::EQUALIZER;
- std::shared_ptr<BundleContext> mContext;
IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
diff --git a/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h b/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
index 9226274..d31763b 100644
--- a/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
+++ b/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
@@ -21,6 +21,7 @@
#include <unordered_map>
#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
#include "BundleContext.h"
#include "BundleTypes.h"
@@ -40,7 +41,10 @@
return instance;
}
- bool isSessionIdExist(int sessionId) const { return mSessionMap.count(sessionId); }
+ bool isSessionIdExist(int sessionId) {
+ std::lock_guard lg(mMutex);
+ return mSessionMap.count(sessionId);
+ }
static bool findBundleTypeInList(std::vector<std::shared_ptr<BundleContext>>& list,
const lvm::BundleEffectType& type, bool remove = false) {
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index a32188a..aef9295 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -122,6 +122,9 @@
shared_libs: [
"liblog",
],
+ cflags: [
+ "-Wthread-safety",
+ ],
visibility: [
"//hardware/interfaces/audio/aidl/default",
],
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 691eede..7c78900 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -518,7 +518,6 @@
{
Mutex::Autolock _l(mRetrieverLock);
weakRetriever = mRetriever;
- mRetriever.clear();
}
for (size_t i = 1; i < mNumSlices; i++) {
@@ -551,6 +550,12 @@
}
}
// Hold on to mDataSource in case the client wants to redecode.
+
+ {
+ Mutex::Autolock _l(mRetrieverLock);
+ mRetriever.clear();
+ }
+
return false;
}
@@ -660,7 +665,10 @@
mFrameDecoded = true;
// Aggressively clear to avoid holding on to resources
- mRetriever.clear();
+ {
+ Mutex::Autolock _l(mRetrieverLock);
+ mRetriever.clear();
+ }
// Hold on to mDataSource in case the client wants to redecode.
return true;
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 27f987d..ba3df59 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -72,6 +72,7 @@
// Keys are strings used for MediaMetrics Item Keys
#define AMEDIAMETRICS_KEY_AUDIO_FLINGER AMEDIAMETRICS_KEY_PREFIX_AUDIO "flinger"
+#define AMEDIAMETRICS_KEY_AUDIO_MIDI AMEDIAMETRICS_KEY_PREFIX_AUDIO "midi"
#define AMEDIAMETRICS_KEY_AUDIO_POLICY AMEDIAMETRICS_KEY_PREFIX_AUDIO "policy"
// Error keys
@@ -124,9 +125,13 @@
#define AMEDIAMETRICS_PROP_CHANNELMASK "channelMask" // int32
#define AMEDIAMETRICS_PROP_CHANNELMASKS "channelMasks" // string with channelMask values
// separated by |.
+#define AMEDIAMETRICS_PROP_CLOSEDCOUNT "closedCount" // int32 (MIDI)
#define AMEDIAMETRICS_PROP_CONTENTTYPE "contentType" // string attributes (AudioTrack)
#define AMEDIAMETRICS_PROP_CUMULATIVETIMENS "cumulativeTimeNs" // int64_t playback/record time
// since start
+#define AMEDIAMETRICS_PROP_DEVICEDISCONNECTED "deviceDisconnected" // string true/false (MIDI)
+#define AMEDIAMETRICS_PROP_DEVICEID "deviceId" // int32 device id (MIDI)
+
// DEVICE values are averaged since starting on device
#define AMEDIAMETRICS_PROP_DEVICELATENCYMS "deviceLatencyMs" // double - avg latency time
#define AMEDIAMETRICS_PROP_DEVICESTARTUPMS "deviceStartupMs" // double - avg startup time
@@ -150,12 +155,15 @@
#define AMEDIAMETRICS_PROP_FLAGS "flags"
#define AMEDIAMETRICS_PROP_FRAMECOUNT "frameCount" // int32
+#define AMEDIAMETRICS_PROP_HARDWARETYPE "hardwareType" // int32 (MIDI)
#define AMEDIAMETRICS_PROP_HASHEADTRACKER "hasHeadTracker" // string true/false
#define AMEDIAMETRICS_PROP_HEADTRACKERENABLED "headTrackerEnabled" // string true/false
#define AMEDIAMETRICS_PROP_HEADTRACKINGMODES "headTrackingModes" // string |, like modes.
#define AMEDIAMETRICS_PROP_INPUTDEVICES "inputDevices" // string value
+#define AMEDIAMETRICS_PROP_INPUTPORTCOUNT "inputPortCount" // int32 (MIDI)
#define AMEDIAMETRICS_PROP_INTERNALTRACKID "internalTrackId" // int32
#define AMEDIAMETRICS_PROP_INTERVALCOUNT "intervalCount" // int32
+#define AMEDIAMETRICS_PROP_ISSHARED "isShared" // string true/false (MIDI)
#define AMEDIAMETRICS_PROP_LATENCYMS "latencyMs" // double value
#define AMEDIAMETRICS_PROP_LEVELS "levels" // string | with levels
#define AMEDIAMETRICS_PROP_LOGSESSIONID "logSessionId" // hex string, "" none
@@ -165,7 +173,9 @@
#define AMEDIAMETRICS_PROP_MODES "modes" // string | with modes
#define AMEDIAMETRICS_PROP_NAME "name" // string value
#define AMEDIAMETRICS_PROP_ORIGINALFLAGS "originalFlags" // int32
+#define AMEDIAMETRICS_PROP_OPENEDCOUNT "openedCount" // int32 (MIDI)
#define AMEDIAMETRICS_PROP_OUTPUTDEVICES "outputDevices" // string value
+#define AMEDIAMETRICS_PROP_OUTPUTPORTCOUNT "outputPortCount" // int32 (MIDI)
#define AMEDIAMETRICS_PROP_PERFORMANCEMODE "performanceMode" // string value, "none", lowLatency"
#define AMEDIAMETRICS_PROP_PLAYBACK_PITCH "playback.pitch" // double value (AudioTrack)
#define AMEDIAMETRICS_PROP_PLAYBACK_SPEED "playback.speed" // double value (AudioTrack)
@@ -194,6 +204,13 @@
// Treated as "debug" information.
#define AMEDIAMETRICS_PROP_STREAMTYPE "streamType" // string (AudioTrack)
+#define AMEDIAMETRICS_PROP_SUPPORTSMIDIUMP "supportsMidiUmp" // string true/false (MIDI).
+ // Universal MIDI Packets is a new
+ // format to transport packets.
+ // Raw byte streams are used if this
+ // is false.
+#define AMEDIAMETRICS_PROP_TOTALINPUTBYTES "totalInputBytes" // int32 (MIDI)
+#define AMEDIAMETRICS_PROP_TOTALOUTPUTBYTES "totalOutputBytes" // int32 (MIDI)
#define AMEDIAMETRICS_PROP_THREADID "threadId" // int32 value io handle
#define AMEDIAMETRICS_PROP_THROTTLEMS "throttleMs" // double
#define AMEDIAMETRICS_PROP_TRACKID "trackId" // int32 port id of track/record
@@ -202,6 +219,7 @@
#define AMEDIAMETRICS_PROP_UNDERRUN "underrun" // int32
#define AMEDIAMETRICS_PROP_UNDERRUNFRAMES "underrunFrames" // int64_t from Thread
#define AMEDIAMETRICS_PROP_USAGE "usage" // string attributes (ATrack)
+#define AMEDIAMETRICS_PROP_USINGALSA "usingAlsa" // string true/false (MIDI)
#define AMEDIAMETRICS_PROP_VOICEVOLUME "voiceVolume" // double (audio.flinger)
#define AMEDIAMETRICS_PROP_VOLUME_LEFT "volume.left" // double (AudioTrack)
#define AMEDIAMETRICS_PROP_VOLUME_RIGHT "volume.right" // double (AudioTrack)
@@ -226,6 +244,7 @@
#define AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE "create"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_CREATEAUDIOPATCH "createAudioPatch"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR "ctor"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_DEVICECLOSED "deviceClosed" // MIDI
#define AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT "disconnect"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR "dtor"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM "endAAudioStream" // AAudioStream
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index cced6b5..f3ef39e 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -354,8 +354,11 @@
}
//static
-Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies;
-std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies;
+// these are no_destroy to keep them from being destroyed at process exit
+// where some thread calls exit() while other threads are still running.
+// see b/194783918
+[[clang::no_destroy]] Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies;
+[[clang::no_destroy]] std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies;
//static
void MediaCodec::ResourceManagerServiceProxy::addCookie(void* cookie) {
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 27ac212..48d3e6f 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -87,6 +87,7 @@
"libmemunreachable",
"libmedia_helper",
"libshmemcompat",
+ "libsounddose",
"libvibrator",
"packagemanager_aidl-cpp",
],
@@ -103,6 +104,7 @@
"libaudiohal_headers",
"libaudioutils_headers",
"libmedia_headers",
+ "libsounddose_headers",
],
export_shared_lib_headers: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d5100fe..cf7e135 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -39,6 +39,7 @@
#include <utils/Log.h>
#include <utils/Trace.h>
#include <binder/Parcel.h>
+#include <media/audiohal/AudioHalVersionInfo.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
@@ -106,13 +107,15 @@
namespace android {
-#define MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION 7.1
-
using ::android::base::StringPrintf;
using media::IEffectClient;
using media::audio::common::AudioMMapPolicyInfo;
using media::audio::common::AudioMMapPolicyType;
using android::content::AttributionSourceState;
+using android::detail::AudioHalVersionInfo;
+
+static const AudioHalVersionInfo kMaxAAudioPropertyDeviceHalVersion =
+ AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1);
static constexpr char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
static constexpr char kHardwareLockedString[] = "Hardware lock is taken\n";
@@ -229,7 +232,7 @@
BINDER_METHOD_ENTRY(setDeviceConnectedState) \
BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
-
+BINDER_METHOD_ENTRY(getSoundDoseInterface) \
// singleton for Binder Method Statistics for IAudioFlinger
static auto& getIAudioFlingerStatistics() {
@@ -401,7 +404,7 @@
mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
- if (mDevicesFactoryHal->getHalVersion() <= MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+ if (mDevicesFactoryHal->getHalVersion() <= kMaxAAudioPropertyDeviceHalVersion) {
mAAudioBurstsPerBuffer = getAAudioMixerBurstCountFromSystemProperty();
mAAudioHwBurstMinMicros = getAAudioHardwareBurstMinUsecFromSystemProperty();
}
@@ -447,7 +450,7 @@
*policyInfos = it->second;
return NO_ERROR;
}
- if (mDevicesFactoryHal->getHalVersion() > MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+ if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
AutoMutex lock(mHardwareLock);
for (size_t i = 0; i < mAudioHwDevs.size(); ++i) {
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
@@ -618,13 +621,15 @@
fullConfig.format = config->format;
std::vector<audio_io_handle_t> secondaryOutputs;
bool isSpatialized;
+ bool isBitPerfect;
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
&streamType, adjAttributionSource,
&fullConfig,
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
- deviceId, &portId, &secondaryOutputs, &isSpatialized);
+ deviceId, &portId, &secondaryOutputs, &isSpatialized,
+ &isBitPerfect);
if (ret != NO_ERROR) {
config->sample_rate = fullConfig.sample_rate;
config->channel_mask = fullConfig.channel_mask;
@@ -1080,7 +1085,8 @@
audio_stream_type_t streamType;
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
std::vector<audio_io_handle_t> secondaryOutputs;
- bool isSpatialized = false;;
+ bool isSpatialized = false;
+ bool isBitPerfect = false;
// TODO b/182392553: refactor or make clearer
pid_t clientPid =
@@ -1127,7 +1133,7 @@
lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
adjAttributionSource, &input.config, input.flags,
&output.selectedDeviceId, &portId, &secondaryOutputs,
- &isSpatialized);
+ &isSpatialized, &isBitPerfect);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
@@ -1193,12 +1199,16 @@
input.notificationsPerBuffer, input.speed,
input.sharedBuffer, sessionId, &output.flags,
callingPid, adjAttributionSource, input.clientInfo.clientTid,
- &lStatus, portId, input.audioTrackCallback, isSpatialized);
+ &lStatus, portId, input.audioTrackCallback, isSpatialized,
+ isBitPerfect);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
output.afFrameCount = thread->frameCount();
output.afSampleRate = thread->sampleRate();
+ output.afChannelMask = static_cast<audio_channel_mask_t>(thread->channelMask() |
+ thread->hapticChannelMask());
+ output.afFormat = thread->format();
output.afLatencyMs = thread->latency();
output.portId = portId;
@@ -1657,6 +1667,16 @@
return thread->getSupportedLatencyModes(modes);
}
+status_t AudioFlinger::getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose) {
+ if (soundDose == nullptr) {
+ return BAD_VALUE;
+ }
+
+ *soundDose = mMelReporter->getSoundDoseInterface(callback);
+ return NO_ERROR;
+}
+
status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
{
// check calling permissions
@@ -2433,6 +2453,12 @@
};
}
+ output.halConfig = {
+ thread->sampleRate(),
+ thread->channelMask(),
+ thread->format()
+ };
+
// Check if one effect chain was awaiting for an AudioRecord to be created on this
// session and move it to this thread.
sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
@@ -2563,7 +2589,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
}
- if (mDevicesFactoryHal->getHalVersion() > MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+ if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
if (int32_t mixerBursts = dev->getAAudioMixerBurstCount();
mixerBursts > 0 && mixerBursts > mAAudioBurstsPerBuffer) {
mAAudioBurstsPerBuffer = mixerBursts;
@@ -2895,7 +2921,11 @@
return thread;
} else {
sp<PlaybackThread> thread;
- if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
+ if (flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
+ thread = sp<BitPerfectThread>::make(this, outputStream, *output, mSystemReady);
+ ALOGV("%s() created bit-perfect output: ID %d thread %p",
+ __func__, *output, thread.get());
+ } else if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
thread = new SpatializerThread(this, outputStream, *output,
mSystemReady, mixerConfig);
ALOGV("openOutput_l() created spatializer output: ID %d thread %p",
@@ -4613,6 +4643,7 @@
case TransactionCode::SET_MASTER_VOLUME:
case TransactionCode::SET_MASTER_MUTE:
case TransactionCode::MASTER_MUTE:
+ case TransactionCode::GET_SOUND_DOSE_INTERFACE:
case TransactionCode::SET_MODE:
case TransactionCode::SET_MIC_MUTE:
case TransactionCode::SET_LOW_RAM_DEVICE:
@@ -4624,7 +4655,7 @@
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
- // return status only for non void methods
+ // return status only for non-void methods
switch (code) {
case TransactionCode::SYSTEM_READY:
break;
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 6a94164..4d3c074 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -87,6 +87,8 @@
#include <audio_utils/SimpleLog.h>
#include <audio_utils/TimestampVerifier.h>
+#include <sounddose/SoundDoseManager.h>
+
#include "FastCapture.h"
#include "FastMixer.h"
#include <media/nbaio/NBAIO.h>
@@ -121,6 +123,7 @@
class EffectsFactoryHalInterface;
class FastMixer;
class IAudioManager;
+class ISoundDoseCallback;
class PassthruBufferProvider;
class RecordBufferConverter;
class ServerProxy;
@@ -303,6 +306,9 @@
virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes);
+ virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose);
+
status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
const std::function<status_t()>& delegate) override;
@@ -585,6 +591,7 @@
class OffloadThread;
class DuplicatingThread;
class AsyncCallbackThread;
+ class BitPerfectThread;
class Track;
class RecordTrack;
class EffectBase;
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index a614736..bd0d7fb 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -30,6 +30,7 @@
namespace android {
+using media::AudioHalVersion;
using media::IEffectClient;
void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
@@ -115,14 +116,19 @@
return BAD_VALUE;
}
- static const float sMinDeviceEffectHalVersion = 6.0;
- float halVersion = effectsFactory->getHalVersion();
+ static AudioHalVersion sMinDeviceEffectHalVersion;
+ sMinDeviceEffectHalVersion.type = AudioHalVersion::Type::HIDL;
+ sMinDeviceEffectHalVersion.major = 6;
+ sMinDeviceEffectHalVersion.minor = 0;
+ AudioHalVersion halVersion = effectsFactory->getHalVersion();
+ // We can trust AIDL generated AudioHalVersion comparison operator (based on std::tie) as long
+ // as the type, major and minor sequence doesn't change in the definition.
if (((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
&& (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC)
|| halVersion < sMinDeviceEffectHalVersion) {
- ALOGW("%s() non pre/post processing device effect %s or incompatible API version %f",
- __func__, desc->name, halVersion);
+ ALOGW("%s() non pre/post processing device effect %s or incompatible API version %s",
+ __func__, desc->name, halVersion.toString().c_str());
return BAD_VALUE;
}
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index ca1bba6..84b9c40 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;
@@ -2960,6 +2961,9 @@
if ((*flags & AUDIO_OUTPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
*flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
}
+ if ((*flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != 0 && !isBitPerfectCompatible()) {
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_BIT_PERFECT);
+ }
}
void AudioFlinger::EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
@@ -2997,6 +3001,18 @@
return true;
}
+bool AudioFlinger::EffectChain::isBitPerfectCompatible() const {
+ Mutex::Autolock _l(mLock);
+ for (const auto &effect : mEffects) {
+ if (effect->isProcessImplemented()
+ && effect->isImplementationSoftware()) {
+ return false;
+ }
+ }
+ // Allow effects without processing or hw accelerated effects.
+ return true;
+}
+
// isCompatibleWithThread_l() must be called with thread->mLock held
bool AudioFlinger::EffectChain::isCompatibleWithThread_l(const sp<ThreadBase>& thread) const
{
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 72ec0e5..7b71a85 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -545,6 +545,9 @@
// Is this EffectChain compatible with the FAST audio flag.
bool isFastCompatible() const;
+ // Is this EffectChain compatible with the bit-perfect audio flag.
+ bool isBitPerfectCompatible() const;
+
// isCompatibleWithThread_l() must be called with thread->mLock held
bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const;
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 9a579dd..8cc7eab 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -18,13 +18,12 @@
// #define LOG_NDEBUG 0
#define LOG_TAG "AudioFlinger::MelReporter"
-#include <cinttypes>
-#include <utils/Log.h>
-#include <android-base/stringprintf.h>
-#include <audio_utils/power.h>
-
#include "AudioFlinger.h"
+#include <android/media/ISoundDoseCallback.h>
+#include <audio_utils/power.h>
+#include <utils/Log.h>
+
namespace android {
bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
@@ -67,9 +66,12 @@
std::lock_guard _lAf(mAudioFlinger.mLock);
auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
if (thread != nullptr) {
- thread->startMelComputation(mMelAggregator.getOrCreateCallbackForDevice(
+ thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice(
deviceId,
- newPatch.streamHandle));
+ newPatch.streamHandle,
+ thread->mSampleRate,
+ thread->mChannelCount,
+ thread->mFormat));
}
}
}
@@ -99,28 +101,23 @@
// Stop MEL calculation for the PlaybackThread
std::lock_guard _lAf(mAudioFlinger.mLock);
+ mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle);
auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle);
if (thread != nullptr) {
thread->stopMelComputation();
}
- mMelAggregator.removeStreamCallback(melPatch.streamHandle);
+}
+
+sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
+ const sp<media::ISoundDoseCallback>& callback) {
+ // no need to lock since getSoundDoseInterface is synchronized
+ return mSoundDoseManager.getSoundDoseInterface(callback);
}
std::string AudioFlinger::MelReporter::dump() {
std::lock_guard _l(mLock);
- std::string output;
-
- base::StringAppendF(&output, "\nMel Reporter:\n");
- mMelAggregator.foreach([&output](const audio_utils::MelRecord& melRecord) {
- base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
- base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);
-
- for (const auto& mel : melRecord.mels) {
- base::StringAppendF(&output, "%d ", mel);
- }
- base::StringAppendF(&output, "\n");
- });
-
+ std::string output("\nSound Dose:\n");
+ output.append(mSoundDoseManager.dump());
return output;
}
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index 905a4cd..f73b3d6 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -19,8 +19,9 @@
#error This header file should only be included from AudioFlinger.h
#endif
-#include <unordered_map>
#include <mutex>
+#include <sounddose/SoundDoseManager.h>
+#include <unordered_map>
constexpr static int kMaxTimestampDeltaInSec = 120;
@@ -31,8 +32,7 @@
class MelReporter : public PatchCommandThread::PatchCommandListener {
public:
explicit MelReporter(AudioFlinger& audioFlinger)
- : mAudioFlinger(audioFlinger),
- mMelAggregator(kMaxTimestampDeltaInSec) {}
+ : mAudioFlinger(audioFlinger) {}
void onFirstRef() override {
mAudioFlinger.mPatchCommandThread->addListener(this);
@@ -44,6 +44,8 @@
// For now only support internal MelReporting
[[nodiscard]] bool isHalReportingEnabled() const { return false; }
+ sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
+
std::string dump();
// PatchCommandListener methods
@@ -54,7 +56,7 @@
private:
AudioFlinger& mAudioFlinger; // does not own the object
- audio_utils::MelAggregator mMelAggregator;
+ SoundDoseManager mSoundDoseManager;
struct ActiveMelPatch {
audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 0f1373d..ebbdf56 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -83,7 +83,8 @@
* ready as possible (aka. Buffer is full). */
size_t frameCountToBeReady = SIZE_MAX,
float speed = 1.0f,
- bool isSpatialized = false);
+ bool isSpatialized = false,
+ bool isBitPerfect = false);
virtual ~Track();
virtual status_t initCheck() const;
@@ -203,6 +204,7 @@
audio_output_flags_t getOutputFlags() const { return mFlags; }
float getSpeed() const { return mSpeed; }
bool isSpatialized() const override { return mIsSpatialized; }
+ bool isBitPerfect() const override { return mIsBitPerfect; }
/**
* Updates the mute state and notifies the audio service. Call this only when holding player
@@ -361,6 +363,7 @@
TeePatches mTeePatches;
const float mSpeed;
const bool mIsSpatialized;
+ const bool mIsBitPerfect;
// TODO: replace PersistableBundle with own struct
// access these two variables only when holding player thread lock.
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index f35944b..f917527 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -536,6 +536,8 @@
return "MMAP_CAPTURE";
case SPATIALIZER:
return "SPATIALIZER";
+ case BIT_PERFECT:
+ return "BIT_PERFECT";
default:
return "unknown";
}
@@ -1519,6 +1521,26 @@
}
}
break;
+ case BIT_PERFECT:
+ if ((desc->flags & EFFECT_FLAG_HW_ACC_TUNNEL) != 0) {
+ // Allow HW accelerated effects of tunnel type
+ break;
+ }
+ // As bit-perfect tracks will not be allowed to apply audio effect that will touch the audio
+ // data, effects will not be allowed on 1) global effects (AUDIO_SESSION_OUTPUT_MIX),
+ // 2) post-processing effects (AUDIO_SESSION_OUTPUT_STAGE or AUDIO_SESSION_DEVICE) and
+ // 3) there is any bit-perfect track with the given session id.
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX || sessionId == AUDIO_SESSION_OUTPUT_STAGE ||
+ sessionId == AUDIO_SESSION_DEVICE) {
+ ALOGW("%s: effect %s not supported on bit-perfect thread %s",
+ __func__, desc->name, mThreadName);
+ return BAD_VALUE;
+ } else if ((hasAudioSession_l(sessionId) & ThreadBase::BIT_PERFECT_SESSION) != 0) {
+ ALOGW("%s: effect %s not supported as there is a bit-perfect track with session as %d",
+ __func__, desc->name, sessionId);
+ return BAD_VALUE;
+ }
+ break;
default:
LOG_ALWAYS_FATAL("checkEffectCompatibility_l(): wrong thread type %d", mType);
}
@@ -2283,7 +2305,8 @@
status_t *status,
audio_port_handle_t portId,
const sp<media::IAudioTrackCallback>& callback,
- bool isSpatialized)
+ bool isSpatialized,
+ bool isBitPerfect)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2315,6 +2338,25 @@
*flags = (audio_output_flags_t)(*flags & outputFlags);
}
+ if (isBitPerfect) {
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ if (chain.get() != nullptr) {
+ // Bit-perfect is required according to the configuration and preferred mixer
+ // attributes, but it is not in the output flag from the client's request. Explicitly
+ // adding bit-perfect flag to check the compatibility
+ audio_output_flags_t flagsToCheck =
+ (audio_output_flags_t)(*flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT);
+ chain->checkOutputFlagCompatibility(&flagsToCheck);
+ if ((flagsToCheck & AUDIO_OUTPUT_FLAG_BIT_PERFECT) == AUDIO_OUTPUT_FLAG_NONE) {
+ ALOGE("%s cannot create track as there is data-processing effect attached to "
+ "given session id(%d)", __func__, sessionId);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ *flags = flagsToCheck;
+ }
+ }
+
// client expresses a preference for FAST, but we get the final say
if (*flags & AUDIO_OUTPUT_FLAG_FAST) {
if (
@@ -2495,6 +2537,18 @@
*pNotificationFrameCount = notificationFrameCount;
switch (mType) {
+ case BIT_PERFECT:
+ if (isBitPerfect) {
+ if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
+ ALOGE("%s, bad parameter when request streaming bit-perfect, sampleRate=%u, "
+ "format=%#x, channelMask=%#x, mSampleRate=%u, mFormat=%#x, mChannelMask=%#x",
+ __func__, sampleRate, format, channelMask, mSampleRate, mFormat,
+ mChannelMask);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
+ break;
case DIRECT:
if (audio_is_linear_pcm(format)) { // TODO maybe use audio_has_proportional_frames()?
@@ -2576,7 +2630,7 @@
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
sessionId, creatorPid, attributionSource, trackFlags,
TrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
- speed, isSpatialized);
+ speed, isSpatialized, isBitPerfect);
lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
if (lStatus != NO_ERROR) {
@@ -2732,7 +2786,11 @@
}
// abort if start is rejected by audio policy manager
if (status != NO_ERROR) {
- return PERMISSION_DENIED;
+ // Do not replace the error if it is DEAD_OBJECT. When this happens, it indicates
+ // current playback thread is reopened, which may happen when clients set preferred
+ // mixer configuration. Returning DEAD_OBJECT will make the client restore track
+ // immediately.
+ return status == DEAD_OBJECT ? status : PERMISSION_DENIED;
}
#ifdef ADD_BATTERY_DATA
// to track the speaker usage
@@ -3405,14 +3463,11 @@
return bytesWritten;
}
-void AudioFlinger::PlaybackThread::startMelComputation(const sp<
- audio_utils::MelProcessor::MelCallback>& callback)
+void AudioFlinger::PlaybackThread::startMelComputation(
+ const sp<audio_utils::MelProcessor>& processor)
{
- ALOGV("%s: creating new mel processor for thread %d", __func__, id());
- mMelProcessor = sp<audio_utils::MelProcessor>::make(mSampleRate,
- mChannelCount,
- mFormat,
- callback);
+ ALOGV("%s: starting mel processor for thread %d", __func__, id());
+ mMelProcessor = processor;
}
void AudioFlinger::PlaybackThread::stopMelComputation() {
@@ -4019,7 +4074,8 @@
// Either threadLoop_mix() or threadLoop_sleepTime() should have set
// mMixerBuffer with data if mMixerBufferValid is true and mSleepTimeUs == 0.
// Merge mMixerBuffer data into mEffectBuffer (if any effects are valid)
- // or mSinkBuffer (if there are no effects).
+ // or mSinkBuffer (if there are no effects and there is no data already copied to
+ // mSinkBuffer).
//
// This is done pre-effects computation; if effects change to
// support higher precision, this needs to move.
@@ -4028,7 +4084,7 @@
// TODO use mSleepTimeUs == 0 as an additional condition.
uint32_t mixerChannelCount = mEffectBufferValid ?
audio_channel_count_from_out_mask(mMixerChannelMask) : mChannelCount;
- if (mMixerBufferValid) {
+ if (mMixerBufferValid && (mEffectBufferValid || !mHasDataCopiedToSinkBuffer)) {
void *buffer = mEffectBufferValid ? mEffectBuffer : mSinkBuffer;
audio_format_t format = mEffectBufferValid ? mEffectBufferFormat : mFormat;
@@ -4119,7 +4175,7 @@
// Effects buffer (buffer valid), we need to
// copy into the sink buffer.
// TODO use mSleepTimeUs == 0 as an additional condition.
- if (mEffectBufferValid) {
+ if (mEffectBufferValid && !mHasDataCopiedToSinkBuffer) {
//ALOGV("writing effect buffer to sink buffer format %#x", mFormat);
void *effectBuffer = (mType == SPATIALIZER) ? mPostSpatializerBuffer : mEffectBuffer;
if (requireMonoBlend()) {
@@ -4800,7 +4856,7 @@
// initialize fast mixer depending on configuration
bool initFastMixer;
- if (mType == SPATIALIZER) {
+ if (mType == SPATIALIZER || mType == BIT_PERFECT) {
initFastMixer = false;
} else {
switch (kUseFastMixer) {
@@ -9780,6 +9836,7 @@
audio_port_handle_t deviceId = mDeviceId;
std::vector<audio_io_handle_t> secondaryOutputs;
bool isSpatialized;
+ bool isBitPerfect;
ret = AudioSystem::getOutputForAttr(&mAttr, &io,
mSessionId,
&stream,
@@ -9789,7 +9846,8 @@
&deviceId,
&portId,
&secondaryOutputs,
- &isSpatialized);
+ &isSpatialized,
+ &isBitPerfect);
ALOGD_IF(!secondaryOutputs.empty(),
"MmapThread::start does not support secondary outputs, ignoring them");
} else {
@@ -10736,4 +10794,40 @@
return mInput->getCapturePosition((int64_t*)position, timeNanos);
}
+// ----------------------------------------------------------------------------
+
+AudioFlinger::BitPerfectThread::BitPerfectThread(const sp<AudioFlinger> &audioflinger,
+ AudioStreamOut *output, audio_io_handle_t id, bool systemReady)
+ : MixerThread(audioflinger, output, id, systemReady, BIT_PERFECT) {}
+
+AudioFlinger::PlaybackThread::mixer_state AudioFlinger::BitPerfectThread::prepareTracks_l(
+ Vector<sp<Track>> *tracksToRemove) {
+ mixer_state result = MixerThread::prepareTracks_l(tracksToRemove);
+ // If there is only one active track and it is bit-perfect, enable tee buffer.
+ if (mActiveTracks.size() == 1 && mActiveTracks[0]->isBitPerfect()) {
+ const int trackId = mActiveTracks[0]->id();
+ mAudioMixer->setParameter(
+ trackId, AudioMixer::TRACK, AudioMixer::TEE_BUFFER, (void *)mSinkBuffer);
+ mAudioMixer->setParameter(
+ trackId, AudioMixer::TRACK, AudioMixer::TEE_BUFFER_FRAME_COUNT,
+ (void *)(uintptr_t)mNormalFrameCount);
+ mIsBitPerfect = true;
+ } else {
+ mIsBitPerfect = false;
+ // No need to copy bit-perfect data directly to sink buffer given there are multiple tracks
+ // active.
+ for (const auto& track : mActiveTracks) {
+ const int trackId = track->id();
+ mAudioMixer->setParameter(
+ trackId, AudioMixer::TRACK, AudioMixer::TEE_BUFFER, nullptr);
+ }
+ }
+ return result;
+}
+
+void AudioFlinger::BitPerfectThread::threadLoop_mix() {
+ MixerThread::threadLoop_mix();
+ mHasDataCopiedToSinkBuffer = mIsBitPerfect;
+}
+
} // namespace android
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index a7028ee..f1b82e4 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -33,6 +33,7 @@
MMAP_PLAYBACK, // Thread class for MMAP playback stream
MMAP_CAPTURE, // Thread class for MMAP capture stream
SPATIALIZER, //
+ BIT_PERFECT, // Thread class for BitPerfectThread
// If you add any values here, also update ThreadBase::threadTypeToString()
};
@@ -430,8 +431,10 @@
// track
FAST_SESSION = 0x4, // the audio session corresponds to at least one
// fast track
- SPATIALIZED_SESSION = 0x8 // the audio session corresponds to at least one
- // spatialized track
+ SPATIALIZED_SESSION = 0x8, // the audio session corresponds to at least one
+ // spatialized track
+ BIT_PERFECT_SESSION = 0x10 // the audio session corresponds to at least one
+ // bit-perfect track
};
// get effect chain corresponding to session Id.
@@ -497,6 +500,9 @@
if (track->isSpatialized()) {
result |= SPATIALIZED_SESSION; // caution, only first track.
}
+ if (track->isBitPerfect()) {
+ result |= BIT_PERFECT_SESSION;
+ }
break;
}
}
@@ -982,7 +988,8 @@
status_t *status /*non-NULL*/,
audio_port_handle_t portId,
const sp<media::IAudioTrackCallback>& callback,
- bool isSpatialized);
+ bool isSpatialized,
+ bool isBitPerfect);
AudioStreamOut* getOutput() const;
AudioStreamOut* clearOutput();
@@ -1091,8 +1098,7 @@
return INVALID_OPERATION;
}
- void startMelComputation(const sp
- <audio_utils::MelProcessor::MelCallback>& callback);
+ void startMelComputation(const sp<audio_utils::MelProcessor>& processor);
void stopMelComputation();
protected:
@@ -1164,6 +1170,9 @@
// for any processing (including output processing).
bool mEffectBufferValid;
+ // Set to "true" to enable when data has already copied to sink
+ bool mHasDataCopiedToSinkBuffer = false;
+
// Frame size aligned buffer used as input and output to all post processing effects
// except the Spatializer in a SPATIALIZER thread. Non spatialized tracks are mixed into
// this buffer so that post processing effects can be applied.
@@ -2274,3 +2283,16 @@
AudioStreamIn* mInput;
};
+
+class BitPerfectThread : public MixerThread {
+public:
+ BitPerfectThread(const sp<AudioFlinger>& audioflinger, AudioStreamOut *output,
+ audio_io_handle_t id, bool systemReady);
+
+protected:
+ mixer_state prepareTracks_l(Vector<sp<Track>> *tracksToRemove) override;
+ void threadLoop_mix() override;
+
+private:
+ bool mIsBitPerfect;
+};
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 20bfbb0..f305aa8 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -109,6 +109,8 @@
virtual bool isSpatialized() const { return false; }
+ virtual bool isBitPerfect() const { return false; }
+
#ifdef TEE_SINK
void dumpTee(int fd, const std::string &reason) const {
mTee.dump(fd, reason);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index e77bf9b..950d555 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -335,6 +335,7 @@
: BnAudioTrack(),
mTrack(track)
{
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
AudioFlinger::TrackHandle::~TrackHandle() {
@@ -632,7 +633,8 @@
audio_port_handle_t portId,
size_t frameCountToBeReady,
float speed,
- bool isSpatialized)
+ bool isSpatialized,
+ bool isBitPerfect)
: TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
@@ -667,7 +669,8 @@
mFlushHwPending(false),
mFlags(flags),
mSpeed(speed),
- mIsSpatialized(isSpatialized)
+ mIsSpatialized(isSpatialized),
+ mIsBitPerfect(isBitPerfect)
{
// client == 0 implies sharedBuffer == 0
ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
@@ -1115,10 +1118,10 @@
mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
}
status = playbackThread->addTrack_l(this);
- if (status == INVALID_OPERATION || status == PERMISSION_DENIED) {
+ if (status == INVALID_OPERATION || status == PERMISSION_DENIED || status == DEAD_OBJECT) {
triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
// restore previous state if start was rejected by policy manager
- if (status == PERMISSION_DENIED) {
+ if (status == PERMISSION_DENIED || status == DEAD_OBJECT) {
mState = state;
}
}
@@ -2358,6 +2361,7 @@
: BnAudioRecord(),
mRecordTrack(recordTrack)
{
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
AudioFlinger::RecordHandle::~RecordHandle() {
diff --git a/services/audioflinger/sounddose/Android.bp b/services/audioflinger/sounddose/Android.bp
new file mode 100644
index 0000000..0e409d3
--- /dev/null
+++ b/services/audioflinger/sounddose/Android.bp
@@ -0,0 +1,43 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+cc_library {
+ name: "libsounddose",
+
+ double_loadable: true,
+
+ srcs: [
+ "SoundDoseManager.cpp",
+ ],
+
+ shared_libs: [
+ "audioflinger-aidl-cpp",
+ "libaudioutils",
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+
+ header_libs: [
+ "libaudioutils_headers",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
+
+cc_library_headers {
+ name: "libsounddose_headers",
+ host_supported: true,
+ device_supported: true,
+ export_include_dirs: ["."],
+}
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
new file mode 100644
index 0000000..46f310c
--- /dev/null
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -0,0 +1,236 @@
+/*
+**
+** Copyright 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 "SoundDoseManager"
+
+#include "SoundDoseManager.h"
+
+#include <android-base/stringprintf.h>
+#include <time.h>
+#include <utils/Log.h>
+#include <cinttypes>
+#include "android/media/SoundDoseRecord.h"
+
+namespace android {
+
+namespace {
+
+int64_t getMonotonicSecond() {
+ struct timespec now_ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &now_ts) != 0) {
+ ALOGE("%s: cannot get timestamp", __func__);
+ return -1;
+ }
+ return now_ts.tv_sec;
+}
+
+} // namespace
+
+sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
+ audio_port_handle_t deviceId, audio_io_handle_t streamHandle, uint32_t sampleRate,
+ size_t channelCount, audio_format_t format) {
+ std::lock_guard _l(mLock);
+
+ auto streamProcessor = mActiveProcessors.find(streamHandle);
+ sp<audio_utils::MelProcessor> processor;
+ if (streamProcessor != mActiveProcessors.end() &&
+ (processor = streamProcessor->second.promote())) {
+ ALOGV("%s: found callback for stream %d", __func__, streamHandle);
+ processor->setDeviceId(deviceId);
+ processor->setOutputRs2(mRs2Value);
+ return processor;
+ } else {
+ ALOGV("%s: creating new callback for device %d", __func__, streamHandle);
+ sp<audio_utils::MelProcessor> melProcessor = sp<audio_utils::MelProcessor>::make(
+ sampleRate, channelCount, format, *this, deviceId, mRs2Value);
+ mActiveProcessors[streamHandle] = melProcessor;
+ return melProcessor;
+ }
+}
+
+void SoundDoseManager::setOutputRs2(float rs2Value) {
+ ALOGV("%s", __func__);
+ std::lock_guard _l(mLock);
+
+ mRs2Value = rs2Value;
+
+ for (auto& streamProcessor : mActiveProcessors) {
+ sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
+ if (processor != nullptr) {
+ status_t result = processor->setOutputRs2(mRs2Value);
+ if (result != NO_ERROR) {
+ ALOGW("%s: could not set RS2 value %f for stream %d", __func__, mRs2Value,
+ streamProcessor.first);
+ }
+ }
+ }
+}
+
+void SoundDoseManager::removeStreamProcessor(audio_io_handle_t streamHandle) {
+ std::lock_guard _l(mLock);
+ auto callbackToRemove = mActiveProcessors.find(streamHandle);
+ if (callbackToRemove != mActiveProcessors.end()) {
+ mActiveProcessors.erase(callbackToRemove);
+ }
+}
+
+void SoundDoseManager::SoundDose::binderDied(__unused const wp<IBinder>& who) {
+ ALOGV("%s", __func__);
+
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager != nullptr) {
+ soundDoseManager->resetSoundDose();
+ }
+}
+
+binder::Status SoundDoseManager::SoundDose::setOutputRs2(float value) {
+ ALOGV("%s", __func__);
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager != nullptr) {
+ soundDoseManager->setOutputRs2(value);
+ }
+ return binder::Status::ok();
+}
+
+binder::Status SoundDoseManager::SoundDose::resetCsd(
+ float currentCsd, const std::vector<media::SoundDoseRecord>& records) {
+ ALOGV("%s", __func__);
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager != nullptr) {
+ soundDoseManager->resetCsd(currentCsd, records);
+ }
+ return binder::Status::ok();
+}
+
+void SoundDoseManager::resetSoundDose() {
+ std::lock_guard lock(mLock);
+ mSoundDose = nullptr;
+}
+
+void SoundDoseManager::resetCsd(float currentCsd,
+ const std::vector<media::SoundDoseRecord>& records) {
+ std::lock_guard lock(mLock);
+ std::vector<audio_utils::CsdRecord> resetRecords;
+ for (const auto& record : records) {
+ resetRecords.emplace_back(record.timestamp, record.duration, record.value,
+ record.averageMel);
+ }
+
+ mMelAggregator->reset(currentCsd, resetRecords);
+}
+
+void SoundDoseManager::onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length,
+ audio_port_handle_t deviceId) const {
+ ALOGV("%s", __func__);
+
+ sp<media::ISoundDoseCallback> soundDoseCallback;
+ std::vector<audio_utils::CsdRecord> records;
+ float currentCsd;
+ {
+ std::lock_guard _l(mLock);
+
+ int64_t timestampSec = getMonotonicSecond();
+
+ // only for internal callbacks
+ records = mMelAggregator->aggregateAndAddNewMelRecord(audio_utils::MelRecord(
+ deviceId, std::vector<float>(mels.begin() + offset, mels.begin() + offset + length),
+ timestampSec - length));
+
+ currentCsd = mMelAggregator->getCsd();
+ }
+
+ soundDoseCallback = getSoundDoseCallback();
+
+ if (records.size() > 0 && soundDoseCallback != nullptr) {
+ std::vector<media::SoundDoseRecord> newRecordsToReport;
+ for (const auto& record : records) {
+ newRecordsToReport.emplace_back(csdRecordToSoundDoseRecord(record));
+ }
+
+ soundDoseCallback->onNewCsdValue(currentCsd, newRecordsToReport);
+ }
+}
+
+sp<media::ISoundDoseCallback> SoundDoseManager::getSoundDoseCallback() const {
+ std::lock_guard _l(mLock);
+ if (mSoundDose == nullptr) {
+ return nullptr;
+ }
+
+ return mSoundDose->mSoundDoseCallback;
+}
+
+void SoundDoseManager::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const {
+ ALOGV("%s: Momentary exposure for device %d triggered: %f MEL", __func__, deviceId, currentMel);
+
+ auto soundDoseCallback = getSoundDoseCallback();
+ if (soundDoseCallback != nullptr) {
+ soundDoseCallback->onMomentaryExposure(currentMel, deviceId);
+ }
+}
+
+sp<media::ISoundDose> SoundDoseManager::getSoundDoseInterface(
+ const sp<media::ISoundDoseCallback>& callback) {
+ ALOGV("%s: Register ISoundDoseCallback", __func__);
+
+ std::lock_guard _l(mLock);
+ if (mSoundDose == nullptr) {
+ mSoundDose = sp<SoundDose>::make(this, callback);
+ }
+ return mSoundDose;
+}
+
+std::string SoundDoseManager::dump() const {
+ std::string output;
+ mMelAggregator->foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
+ base::StringAppendF(&output,
+ "CSD %f with average MEL %f in interval [%" PRId64 ", %" PRId64 "]",
+ csdRecord.value, csdRecord.averageMel, csdRecord.timestamp,
+ csdRecord.timestamp + csdRecord.duration);
+ base::StringAppendF(&output, "\n");
+ });
+
+ base::StringAppendF(&output, "\nCached Mel Records:\n");
+ mMelAggregator->foreachCachedMel([&output](const audio_utils::MelRecord& melRecord) {
+ base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
+ base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);
+
+ for (const auto& mel : melRecord.mels) {
+ base::StringAppendF(&output, "%.2f ", mel);
+ }
+ base::StringAppendF(&output, "\n");
+ });
+
+ return output;
+}
+
+size_t SoundDoseManager::getCachedMelRecordsSize() const {
+ return mMelAggregator->getCachedMelRecordsSize();
+}
+
+media::SoundDoseRecord SoundDoseManager::csdRecordToSoundDoseRecord(
+ const audio_utils::CsdRecord& legacy) {
+ media::SoundDoseRecord soundDoseRecord{};
+ soundDoseRecord.timestamp = legacy.timestamp;
+ soundDoseRecord.duration = legacy.duration;
+ soundDoseRecord.value = legacy.value;
+ soundDoseRecord.averageMel = legacy.averageMel;
+ return soundDoseRecord;
+}
+
+} // namespace android
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
new file mode 100644
index 0000000..b0aa5d6
--- /dev/null
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -0,0 +1,134 @@
+/*
+**
+** Copyright 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/media/BnSoundDose.h>
+#include <android/media/ISoundDoseCallback.h>
+#include <audio_utils/MelAggregator.h>
+#include <audio_utils/MelProcessor.h>
+#include <binder/Status.h>
+#include <mutex>
+#include <unordered_map>
+
+namespace android {
+
+class SoundDoseManager : public audio_utils::MelProcessor::MelCallback {
+ public:
+ /** CSD is computed with a rolling window of 7 days. */
+ static constexpr int64_t kCsdWindowSeconds = 604800; // 60s * 60m * 24h * 7d
+ /** Default RS2 value in dBA as defined in IEC 62368-1 3rd edition. */
+ static constexpr float kDefaultRs2Value = 100.f;
+
+ SoundDoseManager()
+ : mMelAggregator(sp<audio_utils::MelAggregator>::make(kCsdWindowSeconds)),
+ mRs2Value(kDefaultRs2Value){};
+
+ /**
+ * \brief Creates or gets the MelProcessor assigned to the streamHandle
+ *
+ * \param deviceId id for the devices where the stream is active.
+ * \param streanHandle handle to the stream
+ * \param sampleRate sample rate for the processor
+ * \param channelCount number of channels to be processed.
+ * \param format format of the input samples.
+ *
+ * \return MelProcessor assigned to the stream and device id.
+ */
+ sp<audio_utils::MelProcessor> getOrCreateProcessorForDevice(audio_port_handle_t deviceId,
+ audio_io_handle_t streamHandle,
+ uint32_t sampleRate,
+ size_t channelCount,
+ audio_format_t format);
+
+ /**
+ * \brief Removes stream processor when MEL computation is not needed anymore
+ *
+ * \param streanHandle handle to the stream
+ */
+ void removeStreamProcessor(audio_io_handle_t streamHandle);
+
+ /**
+ * Sets the output RS2 value for momentary exposure warnings. Must not be
+ * higher than 100dBA and not lower than 80dBA.
+ *
+ * \param rs2Value value to use for momentary exposure
+ */
+ void setOutputRs2(float rs2Value);
+
+ /**
+ * \brief Registers the interface for passing callbacks to the AudioService and gets
+ * the ISoundDose interface.
+ *
+ * \returns the sound dose binder to send commands to the SoundDoseManager
+ **/
+ sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
+
+ std::string dump() const;
+
+ // used for testing
+ size_t getCachedMelRecordsSize() const;
+
+ /** Method for converting from audio_utils::CsdRecord to media::SoundDoseRecord. */
+ static media::SoundDoseRecord csdRecordToSoundDoseRecord(const audio_utils::CsdRecord& legacy);
+
+ // ------ Override audio_utils::MelProcessor::MelCallback ------
+ void onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length,
+ audio_port_handle_t deviceId) const override;
+
+ void onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const override;
+
+private:
+ class SoundDose : public media::BnSoundDose,
+ public IBinder::DeathRecipient {
+ public:
+ SoundDose(SoundDoseManager* manager, const sp<media::ISoundDoseCallback>& callback)
+ : mSoundDoseManager(manager),
+ mSoundDoseCallback(callback) {};
+
+ /** IBinder::DeathRecipient. Listen to the death of ISoundDoseCallback. */
+ virtual void binderDied(const wp<IBinder>& who);
+
+ /** BnSoundDose override */
+ binder::Status setOutputRs2(float value) override;
+ binder::Status resetCsd(float currentCsd,
+ const std::vector<media::SoundDoseRecord>& records) override;
+
+ wp<SoundDoseManager> mSoundDoseManager;
+ const sp<media::ISoundDoseCallback> mSoundDoseCallback;
+ };
+
+ void resetSoundDose();
+
+ void resetCsd(float currentCsd, const std::vector<media::SoundDoseRecord>& records);
+
+ sp<media::ISoundDoseCallback> getSoundDoseCallback() const;
+
+ mutable std::mutex mLock;
+
+ // no need for lock since MelAggregator is thread-safe
+ const sp<audio_utils::MelAggregator> mMelAggregator;
+
+ std::unordered_map<audio_io_handle_t, wp<audio_utils::MelProcessor>> mActiveProcessors
+ GUARDED_BY(mLock);
+
+ float mRs2Value GUARDED_BY(mLock);
+
+ sp<SoundDose> mSoundDose GUARDED_BY(mLock);
+};
+
+} // namespace android
diff --git a/services/audioflinger/sounddose/tests/Android.bp b/services/audioflinger/sounddose/tests/Android.bp
new file mode 100644
index 0000000..a886663
--- /dev/null
+++ b/services/audioflinger/sounddose/tests/Android.bp
@@ -0,0 +1,40 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+cc_test {
+ name: "sounddosemanager_tests",
+
+ srcs: [
+ "sounddosemanager_tests.cpp"
+ ],
+
+ shared_libs: [
+ "audioflinger-aidl-cpp",
+ "libaudioutils",
+ "libbase",
+ "liblog",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libgmock",
+ "libsounddose",
+ ],
+
+ header_libs: [
+ "libaudioutils_headers",
+ "libsounddose_headers",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
\ No newline at end of file
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
new file mode 100644
index 0000000..0aa5a20
--- /dev/null
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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 "sounddosemanager_tests"
+
+#include <SoundDoseManager.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace {
+
+TEST(SoundDoseManagerTest, GetProcessorForExistingStream) {
+ SoundDoseManager soundDoseManager;
+ sp<audio_utils::MelProcessor> processor1 =
+ soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/1,
+ /*streamHandle=*/1,
+ /*sampleRate*/44100,
+ /*channelCount*/2,
+ /*format*/AUDIO_FORMAT_PCM_FLOAT);
+ sp<audio_utils::MelProcessor> processor2 =
+ soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/2,
+ /*streamHandle=*/1,
+ /*sampleRate*/44100,
+ /*channelCount*/2,
+ /*format*/AUDIO_FORMAT_PCM_FLOAT);
+
+ EXPECT_EQ(processor1, processor2);
+}
+
+TEST(SoundDoseManagerTest, RemoveExistingStream) {
+ SoundDoseManager soundDoseManager;
+ sp<audio_utils::MelProcessor> processor1 =
+ soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/1,
+ /*streamHandle=*/1,
+ /*sampleRate*/44100,
+ /*channelCount*/2,
+ /*format*/AUDIO_FORMAT_PCM_FLOAT);
+
+ soundDoseManager.removeStreamProcessor(1);
+ sp<audio_utils::MelProcessor> processor2 =
+ soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/2,
+ /*streamHandle=*/1,
+ /*sampleRate*/44100,
+ /*channelCount*/2,
+ /*format*/AUDIO_FORMAT_PCM_FLOAT);
+
+ EXPECT_NE(processor1, processor2);
+}
+
+TEST(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
+ SoundDoseManager soundDoseManager;
+ std::vector<float>mels{1, 1};
+
+ soundDoseManager.onNewMelValues(mels, 0, mels.size(), /*deviceId=*/1);
+
+ EXPECT_EQ(soundDoseManager.getCachedMelRecordsSize(), size_t{1});
+}
+
+} // namespace
+} // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index b85382e..a5fa78b 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -144,7 +144,8 @@
audio_port_handle_t *portId,
std::vector<audio_io_handle_t> *secondaryOutputs,
output_type_t *outputType,
- bool *isSpatialized) = 0;
+ bool *isSpatialized,
+ bool *isBitPerfect) = 0;
// indicates to the audio policy manager that the output starts being used by corresponding
// stream.
virtual status_t startOutput(audio_port_handle_t portId) = 0;
@@ -407,6 +408,20 @@
// retrieves the list of available direct audio profiles for the given audio attributes
virtual status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
AudioProfileVector& audioProfiles) = 0;
+
+ virtual status_t getSupportedMixerAttributes(
+ audio_port_handle_t portId, std::vector<audio_mixer_attributes_t>& mixerAttrs) = 0;
+ virtual status_t setPreferredMixerAttributes(
+ const audio_attributes_t* attr,
+ audio_port_handle_t portId,
+ uid_t uid,
+ const audio_mixer_attributes_t* mixerAttributes) = 0;
+ virtual status_t getPreferredMixerAttributes(const audio_attributes_t* attr,
+ audio_port_handle_t portId,
+ audio_mixer_attributes_t* mixerAttributes) = 0;
+ virtual status_t clearPreferredMixerAttributes(const audio_attributes_t* attr,
+ audio_port_handle_t portId,
+ uid_t uid) = 0;
};
// Audio Policy client Interface
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 3d3e0cf..de8e77f 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -246,3 +246,16 @@
}
}
}
+
+/**
+ * Indicates if two given audio output flags are considered as matched, which means that
+ * 1) the `supersetFlags` and `subsetFlags` both contain or both don't contain must match flags and
+ * 2) `supersetFlags` contains all flags from `subsetFlags`.
+ */
+static inline bool audio_output_flags_is_subset(audio_output_flags_t supersetFlags,
+ audio_output_flags_t subsetFlags,
+ uint32_t mustMatchFlags)
+{
+ return ((supersetFlags ^ subsetFlags) & mustMatchFlags) == AUDIO_OUTPUT_FLAG_NONE
+ && (supersetFlags & subsetFlags) == subsetFlags;
+}
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 1f23ae3..92a5628 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -24,6 +24,7 @@
"src/HwModule.cpp",
"src/IOProfile.cpp",
"src/PolicyAudioPort.cpp",
+ "src/PreferredMixerAttributesInfo.cpp",
"src/Serializer.cpp",
"src/SoundTriggerSession.cpp",
"src/TypeConverter.cpp",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 75fa595..9bece23 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -440,6 +440,8 @@
void setTracksInvalidatedStatusByStrategy(product_strategy_t strategy);
+ bool isConfigurationMatched(const audio_config_base_t& config, audio_output_flags_t flags);
+
const sp<IOProfile> mProfile; // I/O profile this output derives from
audio_io_handle_t mIoHandle; // output handle
uint32_t mLatency; //
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 3d35e0e..a62d3f0 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -193,8 +193,10 @@
{AUDIO_FORMAT_AC3, {}},
{AUDIO_FORMAT_E_AC3, {}},
{AUDIO_FORMAT_DTS, {}},
- {AUDIO_FORMAT_DTS_HD, {AUDIO_FORMAT_DTS_HD_MA}},
- {AUDIO_FORMAT_DTS_UHD, {AUDIO_FORMAT_DTS_UHD_P2}},
+ {AUDIO_FORMAT_DTS_HD, {}},
+ {AUDIO_FORMAT_DTS_HD_MA, {}},
+ {AUDIO_FORMAT_DTS_UHD, {}},
+ {AUDIO_FORMAT_DTS_UHD_P2, {}},
{AUDIO_FORMAT_AAC_LC, {
AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
AUDIO_FORMAT_AAC_XHE}},
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 4adc920..80e098b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -183,6 +183,10 @@
return isSingleDeviceType(mDeviceTypes, deviceType);
}
+ bool onlyContainsDevice(const sp<DeviceDescriptor>& item) const {
+ return this->size() == 1 && contains(item);
+ }
+
bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; }
/**
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 37443ab..c489eed 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -35,10 +35,7 @@
class IOProfile : public AudioPort, public PolicyAudioPort
{
public:
- IOProfile(const std::string &name, audio_port_role_t role)
- : AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
- curOpenCount(0),
- curActiveCount(0) {}
+ IOProfile(const std::string &name, audio_port_role_t role);
virtual ~IOProfile() = default;
@@ -66,6 +63,17 @@
if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
maxActiveCount = 0;
}
+ if (getRole() == AUDIO_PORT_ROLE_SOURCE) {
+ mMixerBehaviors.clear();
+ mMixerBehaviors.insert(AUDIO_MIXER_BEHAVIOR_DEFAULT);
+ if (mFlags.output & AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
+ mMixerBehaviors.insert(AUDIO_MIXER_BEHAVIOR_BIT_PERFECT);
+ }
+ }
+ }
+
+ const MixerBehaviorSet& getMixerBehaviors() const {
+ return mMixerBehaviors;
}
/**
@@ -212,6 +220,8 @@
return false;
}
+ void toSupportedMixerAttributes(std::vector<audio_mixer_attributes_t>* mixerAttributes) const;
+
// Number of streams currently opened for this profile.
uint32_t curOpenCount;
// Number of streams currently active for this profile. This is not the number of active clients
@@ -220,6 +230,8 @@
private:
DeviceVector mSupportedDevices; // supported devices: this input/output can be routed from/to
+
+ MixerBehaviorSet mMixerBehaviors;
};
class InputProfile : public IOProfile
diff --git a/services/audiopolicy/common/managerdefinitions/include/PreferredMixerAttributesInfo.h b/services/audiopolicy/common/managerdefinitions/include/PreferredMixerAttributesInfo.h
new file mode 100644
index 0000000..9472481
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/PreferredMixerAttributesInfo.h
@@ -0,0 +1,59 @@
+/*
+ * 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 <map>
+
+#include <utils/RefBase.h>
+
+#include "AudioRoute.h"
+#include "HwModule.h"
+#include "IOProfile.h"
+
+namespace android {
+
+class PreferredMixerAttributesInfo : public RefBase {
+public:
+ PreferredMixerAttributesInfo(uid_t uid, audio_port_handle_t devicePortId,
+ const sp<IOProfile>& profile, audio_output_flags_t flags,
+ const audio_mixer_attributes_t& mixerAttributes)
+ : mDevicePortId(devicePortId), mUid(uid), mProfile(profile),
+ mOutputFlags(flags), mMixerAttributes(mixerAttributes) { }
+
+ audio_port_handle_t getDeviceId() const { return mDevicePortId; }
+ const audio_config_base_t& getConfigBase() const { return mMixerAttributes.config; }
+ uid_t getUid() const { return mUid; }
+ int getActiveClientCount() const { return mActiveClientsCount; }
+ const sp<IOProfile> getProfile() const { return mProfile; };
+ audio_output_flags_t getFlags() const { return mOutputFlags; }
+ const audio_mixer_attributes_t& getMixerAttributes() const { return mMixerAttributes; }
+
+ void increaseActiveClient() { mActiveClientsCount++; }
+ void decreaseActiveClient() { mActiveClientsCount--; }
+
+ void dump(String8 *dst);
+
+private:
+ const audio_port_handle_t mDevicePortId;
+ const uid_t mUid;
+ const sp<IOProfile> mProfile;
+ const audio_output_flags_t mOutputFlags;
+ const audio_mixer_attributes_t mMixerAttributes;
+ int mActiveClientsCount = 0;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 8eefe77..c7296e9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -26,6 +26,7 @@
#include "Volume.h"
#include "HwModule.h"
#include "TypeConverter.h"
+#include "policy.h"
#include <media/AudioGain.h>
#include <media/AudioParameter.h>
#include <media/AudioPolicy.h>
@@ -301,7 +302,9 @@
mDirectClientSession(AUDIO_SESSION_NONE)
{
if (profile != NULL) {
- mFlags = (audio_output_flags_t)profile->getFlags();
+ // By default, opening the output without immutable flags, the bit-perfect flags should be
+ // applied when the apps explicitly request.
+ mFlags = (audio_output_flags_t)(profile->getFlags() & (~AUDIO_OUTPUT_FLAG_BIT_PERFECT));
}
}
@@ -311,6 +314,9 @@
if (extraInfo != nullptr) {
allExtraInfo.appendFormat("%s; ", extraInfo);
}
+ if (mProfile != nullptr) {
+ allExtraInfo.appendFormat("IOProfile name:%s; ", mProfile->getName().c_str());
+ }
std::string flagsLiteral = toString(mFlags);
allExtraInfo.appendFormat("Latency: %d; 0x%04x", mLatency, mFlags);
if (!flagsLiteral.empty()) {
@@ -931,6 +937,16 @@
return false;
}
+bool SwAudioOutputDescriptor::isConfigurationMatched(const audio_config_base_t &config,
+ audio_output_flags_t flags) {
+ const uint32_t mustMatchOutputFlags =
+ AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ return audio_output_flags_is_subset(AudioOutputDescriptor::mFlags, flags, mustMatchOutputFlags)
+ && mSamplingRate == config.sample_rate
+ && mChannelMask == config.channel_mask
+ && mFormat == config.format;
+}
+
void SwAudioOutputCollection::dump(String8 *dst) const
{
dst->appendFormat("\n Outputs (%zu):\n", size());
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 7b4cecf..98d7d59 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -24,6 +24,15 @@
namespace android {
+IOProfile::IOProfile(const std::string &name, audio_port_role_t role)
+ : AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
+ curOpenCount(0),
+ curActiveCount(0) {
+ if (role == AUDIO_PORT_ROLE_SOURCE) {
+ mMixerBehaviors.insert(AUDIO_MIXER_BEHAVIOR_DEFAULT);
+ }
+}
+
bool IOProfile::isCompatibleProfile(const DeviceVector &devices,
uint32_t samplingRate,
uint32_t *updatedSamplingRate,
@@ -105,8 +114,10 @@
const uint32_t mustMatchOutputFlags =
AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
- if (isPlaybackThread && (((getFlags() ^ flags) & mustMatchOutputFlags)
- || (getFlags() & flags) != flags)) {
+ if (isPlaybackThread &&
+ !audio_output_flags_is_subset((audio_output_flags_t)getFlags(),
+ (audio_output_flags_t)flags,
+ mustMatchOutputFlags)) {
return false;
}
// The only input flag that is allowed to be different is the fast flag.
@@ -132,6 +143,34 @@
return device == deviceDesc && deviceDesc->hasCurrentEncodedFormat(); }) == 1;
}
+void IOProfile::toSupportedMixerAttributes(
+ std::vector<audio_mixer_attributes_t> *mixerAttributes) const {
+ if (!hasDynamicAudioProfile()) {
+ // The mixer attributes is only supported when there is a dynamic profile.
+ return;
+ }
+ for (const auto& profile : mProfiles) {
+ if (!profile->isValid()) {
+ continue;
+ }
+ for (const auto sampleRate : profile->getSampleRates()) {
+ for (const auto channelMask : profile->getChannels()) {
+ const audio_config_base_t config = {
+ .format = profile->getFormat(),
+ .sample_rate = sampleRate,
+ .channel_mask = channelMask
+ };
+ for (const auto mixerBehavior : mMixerBehaviors) {
+ mixerAttributes->push_back({
+ .config = config,
+ .mixer_behavior = mixerBehavior
+ });
+ }
+ }
+ }
+ }
+}
+
void IOProfile::dump(String8 *dst, int spaces) const
{
String8 extraInfo;
diff --git a/services/audiopolicy/common/managerdefinitions/src/PreferredMixerAttributesInfo.cpp b/services/audiopolicy/common/managerdefinitions/src/PreferredMixerAttributesInfo.cpp
new file mode 100644
index 0000000..edb2c6d
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/PreferredMixerAttributesInfo.cpp
@@ -0,0 +1,31 @@
+/*
+ * 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 "PreferredMixerAttributesInfo.h"
+
+namespace android {
+
+void PreferredMixerAttributesInfo::dump(String8 *dst) {
+ dst->appendFormat("device port ID: %d; owner uid: %d; profile name: %s; flags: %#x; "
+ "sample rate: %u; channel mask: %#x; format: %#x; mixer behavior: %d; "
+ "active clients count: %d\n",
+ mDevicePortId, mUid, mProfile->getName().c_str(), mOutputFlags,
+ mMixerAttributes.config.sample_rate, mMixerAttributes.config.channel_mask,
+ mMixerAttributes.config.format, mMixerAttributes.mixer_behavior,
+ mActiveClientsCount);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/config/surround_sound_configuration_aidl.xml b/services/audiopolicy/config/surround_sound_configuration_aidl.xml
new file mode 100644
index 0000000..cf15711
--- /dev/null
+++ b/services/audiopolicy/config/surround_sound_configuration_aidl.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<surroundSound>
+ <!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
+ There must be a corresponding Java ENCODING_... constant defined in AudioFormat.java,
+ and a display name defined in AudioFormat.toDisplayName. For the formats that don't
+ need a dedicated Surround Settings dialog entry, a subformats list has to be used. -->
+ <formats>
+ <format name="AUDIO_FORMAT_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3_JOC" />
+ <format name="AUDIO_FORMAT_DOLBY_TRUEHD" />
+ <format name="AUDIO_FORMAT_DTS" />
+ <format name="AUDIO_FORMAT_DTS_HD" />
+ <format name="AUDIO_FORMAT_DTS_HD_MA" />
+ <format name="AUDIO_FORMAT_DTS_UHD" />
+ <format name="AUDIO_FORMAT_DTS_UHD_P2" />
+ <format name="AUDIO_FORMAT_AAC_LC" subformats="AUDIO_FORMAT_AAC_HE_V1 AUDIO_FORMAT_AAC_HE_V2 AUDIO_FORMAT_AAC_ELD AUDIO_FORMAT_AAC_XHE" />
+ <format name="AUDIO_FORMAT_AC4" />
+ </formats>
+</surroundSound>
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 28268c9..14f565b 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -259,13 +259,15 @@
*portId = AUDIO_PORT_HANDLE_NONE;
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized;
+ bool isBitPerfect;
// TODO b/182392769: use attribution source util
AttributionSourceState attributionSource;
attributionSource.uid = 0;
attributionSource.token = sp<BBinder>::make();
if (mManager->getOutputForAttr(&attr, output, AUDIO_SESSION_NONE, &stream, attributionSource,
- &config, &flags, selectedDeviceId, portId, {}, &outputType, &isSpatialized) != OK) {
+ &config, &flags, selectedDeviceId, portId, {}, &outputType, &isSpatialized,
+ &isBitPerfect) != OK) {
return false;
}
if (*output == AUDIO_IO_HANDLE_NONE || *portId == AUDIO_PORT_HANDLE_NONE) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 4c8aec7..5d5e4cd 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -260,6 +260,9 @@
// remove device from mReportedFormatsMap cache
mReportedFormatsMap.erase(device);
+ // remove preferred mixer configurations
+ mPreferredMixerAttrInfos.erase(device->getId());
+
} break;
default:
@@ -1139,7 +1142,8 @@
bool *isRequestedDeviceForExclusiveUse,
std::vector<sp<AudioPolicyMix>> *secondaryMixes,
output_type_t *outputType,
- bool *isSpatialized)
+ bool *isSpatialized,
+ bool *isBitPerfect)
{
DeviceVector outputDevices;
const audio_port_handle_t requestedPortId = *selectedDeviceId;
@@ -1270,8 +1274,22 @@
}
}
if (*output == AUDIO_IO_HANDLE_NONE) {
+ sp<PreferredMixerAttributesInfo> info = nullptr;
+ if (outputDevices.size() == 1) {
+ info = getPreferredMixerAttributesInfo(
+ outputDevices.itemAt(0)->getId(),
+ mEngine->getProductStrategyForAttributes(*resultAttr));
+ if (info != nullptr && info->getUid() != uid && info->getActiveClientCount() == 0) {
+ // Only use preferred mixer when the requested uid matched or
+ // there is active client on preferred mixer.
+ info = nullptr;
+ }
+ }
*output = getOutputForDevices(outputDevices, session, resultAttr, config,
- flags, isSpatialized, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);
+ flags, isSpatialized, info, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);
+ *isBitPerfect = (info != nullptr
+ && (info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE
+ && *output != AUDIO_IO_HANDLE_NONE);
}
if (*output == AUDIO_IO_HANDLE_NONE) {
AudioProfileVector profiles;
@@ -1316,7 +1334,8 @@
audio_port_handle_t *portId,
std::vector<audio_io_handle_t> *secondaryOutputs,
output_type_t *outputType,
- bool *isSpatialized)
+ bool *isSpatialized,
+ bool *isBitPerfect)
{
// The supplied portId must be AUDIO_PORT_HANDLE_NONE
if (*portId != AUDIO_PORT_HANDLE_NONE) {
@@ -1338,7 +1357,8 @@
status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
config, flags, selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- secondaryOutputs != nullptr ? &secondaryMixes : nullptr, outputType, isSpatialized);
+ secondaryOutputs != nullptr ? &secondaryMixes : nullptr, outputType, isSpatialized,
+ isBitPerfect);
if (status != NO_ERROR) {
return status;
}
@@ -1482,6 +1502,7 @@
const audio_config_t *config,
audio_output_flags_t *flags,
bool *isSpatialized,
+ sp<PreferredMixerAttributesInfo> prefMixerConfigInfo,
bool forceMutingHaptic)
{
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
@@ -1557,11 +1578,36 @@
// get which output is suitable for the specified stream. The actual
// routing change will happen when startOutput() will be called
SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
-
- // at this stage we should ignore the DIRECT flag as no direct output could be found earlier
- *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
- output = selectOutput(
- outputs, *flags, config->format, channelMask, config->sample_rate, session);
+ if (prefMixerConfigInfo != nullptr) {
+ for (audio_io_handle_t outputHandle : outputs) {
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputHandle);
+ if (outputDesc->mProfile == prefMixerConfigInfo->getProfile()) {
+ output = outputHandle;
+ break;
+ }
+ }
+ if (output == AUDIO_IO_HANDLE_NONE) {
+ // No output open with the preferred profile. Open a new one.
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.channel_mask = prefMixerConfigInfo->getConfigBase().channel_mask;
+ config.sample_rate = prefMixerConfigInfo->getConfigBase().sample_rate;
+ config.format = prefMixerConfigInfo->getConfigBase().format;
+ sp<SwAudioOutputDescriptor> preferredOutput = openOutputWithProfileAndDevice(
+ prefMixerConfigInfo->getProfile(), devices, nullptr /*mixerConfig*/,
+ &config, prefMixerConfigInfo->getFlags());
+ if (preferredOutput == nullptr) {
+ ALOGE("%s failed to open output with preferred mixer config", __func__);
+ } else {
+ output = preferredOutput->mIoHandle;
+ }
+ }
+ } else {
+ // at this stage we should ignore the DIRECT flag as no direct output could be
+ // found earlier
+ *flags = (audio_output_flags_t) (*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
+ output = selectOutput(
+ outputs, *flags, config->format, channelMask, config->sample_rate, session);
+ }
}
ALOGW_IF((output == 0), "getOutputForDevices() could not find output for stream %d, "
"sampling rate %d, format %#x, channels %#x, flags %#x",
@@ -2015,6 +2061,33 @@
outputDesc->stop();
return status;
}
+
+ // If the client is the first one active on preferred mixer parameters, reopen the output
+ // if the current mixer parameters doesn't match the preferred one.
+ if (outputDesc->devices().size() == 1) {
+ sp<PreferredMixerAttributesInfo> info = getPreferredMixerAttributesInfo(
+ outputDesc->devices()[0]->getId(), client->strategy());
+ if (info != nullptr && info->getUid() == client->uid()) {
+ if (info->getActiveClientCount() == 0 && !outputDesc->isConfigurationMatched(
+ info->getConfigBase(), info->getFlags())) {
+ stopSource(outputDesc, client);
+ outputDesc->stop();
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.channel_mask = info->getConfigBase().channel_mask;
+ config.sample_rate = info->getConfigBase().sample_rate;
+ config.format = info->getConfigBase().format;
+ status_t status = reopenOutput(outputDesc, &config, info->getFlags(), __func__);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ // Intentionally return error to let the client side resending request for
+ // creating and starting.
+ return DEAD_OBJECT;
+ }
+ info->increaseActiveClient();
+ }
+ }
+
if (delayMs != 0) {
usleep(delayMs * 1000);
}
@@ -2267,6 +2340,19 @@
if (status == NO_ERROR ) {
outputDesc->stop();
+ } else {
+ return status;
+ }
+
+ if (outputDesc->devices().size() == 1) {
+ sp<PreferredMixerAttributesInfo> info = getPreferredMixerAttributesInfo(
+ outputDesc->devices()[0]->getId(), client->strategy());
+ if (info != nullptr && info->getUid() == client->uid()) {
+ info->decreaseActiveClient();
+ if (info->getActiveClientCount() == 0) {
+ reopenOutput(outputDesc, nullptr /*config*/, AUDIO_OUTPUT_FLAG_NONE, __func__);
+ }
+ }
}
return status;
}
@@ -3021,6 +3107,10 @@
status_t status = NO_ERROR;
IVolumeCurves &curves = getVolumeCurves(attributes);
VolumeSource vs = toVolumeSource(group);
+ // AUDIO_STREAM_BLUETOOTH_SCO is only used for volume control so we remap
+ // to AUDIO_STREAM_VOICE_CALL to match with relevant playback activity
+ VolumeSource activityVs = (vs == toVolumeSource(AUDIO_STREAM_BLUETOOTH_SCO, false)) ?
+ toVolumeSource(AUDIO_STREAM_VOICE_CALL, false) : vs;
product_strategy_t strategy = mEngine->getProductStrategyForAttributes(attributes);
status = setVolumeCurveIndex(index, device, curves);
@@ -3059,7 +3149,8 @@
if (curDevices.erase(AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
curDevices.insert(AUDIO_DEVICE_OUT_SPEAKER);
}
- if (!(desc->isActive(vs) || isInCall())) {
+
+ if (!(desc->isActive(activityVs) || isInCallOrScreening())) {
continue;
}
if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME &&
@@ -3093,7 +3184,7 @@
bool isPreempted = false;
bool isHigherPriority = productStrategy < strategy;
for (const auto &client : activeClients) {
- if (isHigherPriority && (client->volumeSource() != vs)) {
+ if (isHigherPriority && (client->volumeSource() != activityVs)) {
ALOGV("%s: Strategy=%d (\nrequester:\n"
" group %d, volumeGroup=%d attributes=%s)\n"
" higher priority source active:\n"
@@ -3106,7 +3197,7 @@
break;
}
// However, continue for loop to ensure no higher prio clients running on output
- if (client->volumeSource() == vs) {
+ if (client->volumeSource() == activityVs) {
applyVolume = true;
}
}
@@ -3892,6 +3983,15 @@
dst->appendFormat(" - uid=%d flag_mask=%#x\n", policy.first, policy.second);
}
+ dst->appendFormat(" Preferred mixer audio configuration:\n");
+ for (const auto it : mPreferredMixerAttrInfos) {
+ dst->appendFormat(" - device port id: %d\n", it.first);
+ for (const auto preferredMixerInfoIt : it.second) {
+ dst->appendFormat(" - strategy: %d; ", preferredMixerInfoIt.first);
+ preferredMixerInfoIt.second->dump(dst);
+ }
+ }
+
dst->appendFormat("\nPolicy Engine dump:\n");
mEngine->dump(dst);
}
@@ -4122,6 +4222,172 @@
AUDIO_OUTPUT_FLAG_DIRECT /*flags*/, false /*isInput*/);
}
+status_t AudioPolicyManager::getSupportedMixerAttributes(
+ audio_port_handle_t portId, std::vector<audio_mixer_attributes_t> &mixerAttrs) {
+ ALOGV("%s, portId=%d", __func__, portId);
+ sp<DeviceDescriptor> deviceDescriptor = mAvailableOutputDevices.getDeviceFromId(portId);
+ if (deviceDescriptor == nullptr) {
+ ALOGE("%s the requested device is currently unavailable", __func__);
+ return BAD_VALUE;
+ }
+ for (const auto& hwModule : mHwModules) {
+ for (const auto& curProfile : hwModule->getOutputProfiles()) {
+ if (curProfile->supportsDevice(deviceDescriptor)) {
+ curProfile->toSupportedMixerAttributes(&mixerAttrs);
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::setPreferredMixerAttributes(
+ const audio_attributes_t *attr,
+ audio_port_handle_t portId,
+ uid_t uid,
+ const audio_mixer_attributes_t *mixerAttributes) {
+ ALOGV("%s, attr=%s, mixerAttributes={format=%#x, channelMask=%#x, samplingRate=%u, "
+ "mixerBehavior=%d}, uid=%d, portId=%u",
+ __func__, toString(*attr).c_str(), mixerAttributes->config.format,
+ mixerAttributes->config.channel_mask, mixerAttributes->config.sample_rate,
+ mixerAttributes->mixer_behavior, uid, portId);
+ if (attr->usage != AUDIO_USAGE_MEDIA) {
+ ALOGE("%s failed, only media is allowed, the given usage is %d", __func__, attr->usage);
+ return BAD_VALUE;
+ }
+ sp<DeviceDescriptor> deviceDescriptor = mAvailableOutputDevices.getDeviceFromId(portId);
+ if (deviceDescriptor == nullptr) {
+ ALOGE("%s the requested device is currently unavailable", __func__);
+ return BAD_VALUE;
+ }
+ if (!audio_is_usb_out_device(deviceDescriptor->type())) {
+ ALOGE("%s(%d), type=%d, is not a usb output device",
+ __func__, portId, deviceDescriptor->type());
+ return BAD_VALUE;
+ }
+
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+ audio_flags_to_audio_output_flags(attr->flags, &flags);
+ flags = (audio_output_flags_t) (flags |
+ audio_output_flags_from_mixer_behavior(mixerAttributes->mixer_behavior));
+ sp<IOProfile> profile = nullptr;
+ DeviceVector devices(deviceDescriptor);
+ for (const auto& hwModule : mHwModules) {
+ for (const auto& curProfile : hwModule->getOutputProfiles()) {
+ if (curProfile->hasDynamicAudioProfile()
+ && curProfile->isCompatibleProfile(devices,
+ mixerAttributes->config.sample_rate,
+ nullptr /*updatedSamplingRate*/,
+ mixerAttributes->config.format,
+ nullptr /*updatedFormat*/,
+ mixerAttributes->config.channel_mask,
+ nullptr /*updatedChannelMask*/,
+ flags,
+ false /*exactMatchRequiredForInputFlags*/)) {
+ profile = curProfile;
+ break;
+ }
+ }
+ }
+ if (profile == nullptr) {
+ ALOGE("%s, there is no compatible profile found", __func__);
+ return BAD_VALUE;
+ }
+
+ sp<PreferredMixerAttributesInfo> mixerAttrInfo =
+ sp<PreferredMixerAttributesInfo>::make(
+ uid, portId, profile, flags, *mixerAttributes);
+ const product_strategy_t strategy = mEngine->getProductStrategyForAttributes(*attr);
+ mPreferredMixerAttrInfos[portId][strategy] = mixerAttrInfo;
+
+ // If 1) there is any client from the preferred mixer configuration owner that is currently
+ // active and matches the strategy and 2) current output is on the preferred device and the
+ // mixer configuration doesn't match the preferred one, reopen output with preferred mixer
+ // configuration.
+ std::vector<audio_io_handle_t> outputsToReopen;
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ const auto output = mOutputs.valueAt(i);
+ if (output->mProfile == profile && output->devices().onlyContainsDevice(deviceDescriptor)
+ && !output->isConfigurationMatched(mixerAttributes->config, flags)) {
+ for (const auto& client : output->getActiveClients()) {
+ if (client->uid() == uid && client->strategy() == strategy) {
+ client->setIsInvalid();
+ outputsToReopen.push_back(output->mIoHandle);
+ }
+ }
+ }
+ }
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.sample_rate = mixerAttributes->config.sample_rate;
+ config.channel_mask = mixerAttributes->config.channel_mask;
+ config.format = mixerAttributes->config.format;
+ for (const auto output : outputsToReopen) {
+ reopenOutput(mOutputs.valueFor(output), &config, flags, __func__);
+ }
+
+ return NO_ERROR;
+}
+
+sp<PreferredMixerAttributesInfo> AudioPolicyManager::getPreferredMixerAttributesInfo(
+ audio_port_handle_t devicePortId, product_strategy_t strategy) {
+ auto it = mPreferredMixerAttrInfos.find(devicePortId);
+ if (it == mPreferredMixerAttrInfos.end()) {
+ return nullptr;
+ }
+ auto mixerAttrInfoIt = it->second.find(strategy);
+ if (mixerAttrInfoIt == it->second.end()) {
+ return nullptr;
+ }
+ return mixerAttrInfoIt->second;
+}
+
+status_t AudioPolicyManager::getPreferredMixerAttributes(
+ const audio_attributes_t *attr,
+ audio_port_handle_t portId,
+ audio_mixer_attributes_t* mixerAttributes) {
+ sp<PreferredMixerAttributesInfo> info = getPreferredMixerAttributesInfo(
+ portId, mEngine->getProductStrategyForAttributes(*attr));
+ if (info == nullptr) {
+ return NAME_NOT_FOUND;
+ }
+ *mixerAttributes = info->getMixerAttributes();
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::clearPreferredMixerAttributes(const audio_attributes_t *attr,
+ audio_port_handle_t portId,
+ uid_t uid) {
+ const product_strategy_t strategy = mEngine->getProductStrategyForAttributes(*attr);
+ const auto preferredMixerAttrInfo = getPreferredMixerAttributesInfo(portId, strategy);
+ if (preferredMixerAttrInfo == nullptr) {
+ return NAME_NOT_FOUND;
+ }
+ if (preferredMixerAttrInfo->getUid() != uid) {
+ ALOGE("%s, requested uid=%d, owned uid=%d",
+ __func__, uid, preferredMixerAttrInfo->getUid());
+ return PERMISSION_DENIED;
+ }
+ mPreferredMixerAttrInfos[portId].erase(strategy);
+ if (mPreferredMixerAttrInfos[portId].empty()) {
+ mPreferredMixerAttrInfos.erase(portId);
+ }
+
+ // Reconfig existing output
+ std::vector<audio_io_handle_t> potentialOutputsToReopen;
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ if (mOutputs.valueAt(i)->mProfile == preferredMixerAttrInfo->getProfile()) {
+ potentialOutputsToReopen.push_back(mOutputs.keyAt(i));
+ }
+ }
+ for (const auto output : potentialOutputsToReopen) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
+ if (desc->isConfigurationMatched(preferredMixerAttrInfo->getConfigBase(),
+ preferredMixerAttrInfo->getFlags())) {
+ reopenOutput(desc, nullptr /*config*/, AUDIO_OUTPUT_FLAG_NONE, __func__);
+ }
+ }
+ return NO_ERROR;
+}
+
status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
@@ -4186,6 +4452,7 @@
*num_ports += numOutputs;
}
}
+
*generation = curAudioPortGeneration();
ALOGV("listAudioPorts() got %zu ports needed %d", portsWritten, *num_ports);
return NO_ERROR;
@@ -4530,10 +4797,11 @@
bool isRequestedDeviceForExclusiveUse = false;
output_type_t outputType;
bool isSpatialized;
+ bool isBitPerfect;
getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
&stream, sourceDesc->uid(), &config, &flags,
&selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- nullptr, &outputType, &isSpatialized);
+ nullptr, &outputType, &isSpatialized, &isBitPerfect);
if (output == AUDIO_IO_HANDLE_NONE) {
ALOGV("%s no output for device %s",
__FUNCTION__, sinkDevice->toString().c_str());
@@ -7444,14 +7712,18 @@
return is_state_in_call(state);
}
-bool AudioPolicyManager::isCallAudioAccessible()
-{
+bool AudioPolicyManager::isCallAudioAccessible() const {
audio_mode_t mode = mEngine->getPhoneState();
return (mode == AUDIO_MODE_IN_CALL)
|| (mode == AUDIO_MODE_CALL_SCREEN)
|| (mode == AUDIO_MODE_CALL_REDIRECT);
}
+bool AudioPolicyManager::isInCallOrScreening() const {
+ audio_mode_t mode = mEngine->getPhoneState();
+ return isStateInCall(mode) || mode == AUDIO_MODE_CALL_SCREEN;
+}
+
void AudioPolicyManager::cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc)
{
for (ssize_t i = (ssize_t)mAudioSources.size() - 1; i >= 0; i--) {
@@ -7744,19 +8016,23 @@
sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice(
const sp<IOProfile>& profile, const DeviceVector& devices,
- const audio_config_base_t *mixerConfig)
+ const audio_config_base_t *mixerConfig, const audio_config_t *halConfig,
+ audio_output_flags_t flags)
{
for (const auto& device : devices) {
// TODO: This should be checking if the profile supports the device combo.
if (!profile->supportsDevice(device)) {
+ ALOGE("%s profile(%s) doesn't support device %#x", __func__, profile->getName().c_str(),
+ device->type());
return nullptr;
}
}
sp<SwAudioOutputDescriptor> desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = desc->open(nullptr /* halConfig */, mixerConfig, devices,
- AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
+ status_t status = desc->open(halConfig, mixerConfig, devices,
+ AUDIO_STREAM_DEFAULT, flags, &output);
if (status != NO_ERROR) {
+ ALOGE("%s failed to open output %d", __func__, status);
return nullptr;
}
@@ -7774,7 +8050,9 @@
ALOGW("%s() missing param", __func__);
desc->close();
return nullptr;
- } else if (profile->hasDynamicAudioProfile()) {
+ } else if (profile->hasDynamicAudioProfile() && halConfig == nullptr) {
+ // Reopen the output with the best audio profile picked by APM when the profile supports
+ // dynamic audio profile and the hal config is not specified.
desc->close();
output = AUDIO_IO_HANDLE_NONE;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -7784,8 +8062,7 @@
config.offload_info.channel_mask = config.channel_mask;
config.offload_info.format = config.format;
- status = desc->open(&config, mixerConfig, devices,
- AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
+ status = desc->open(&config, mixerConfig, devices, AUDIO_STREAM_DEFAULT, flags, &output);
if (status != NO_ERROR) {
return nullptr;
}
@@ -7945,4 +8222,19 @@
return NO_ERROR;
}
+status_t AudioPolicyManager::reopenOutput(sp<SwAudioOutputDescriptor> outputDesc,
+ const audio_config_t *config,
+ audio_output_flags_t flags,
+ const char* caller) {
+ closeOutput(outputDesc->mIoHandle);
+ sp<SwAudioOutputDescriptor> preferredOutput = openOutputWithProfileAndDevice(
+ outputDesc->mProfile, outputDesc->devices(), nullptr /*mixerConfig*/, config, flags);
+ if (preferredOutput == nullptr) {
+ ALOGE("%s failed to reopen output device=%d, caller=%s",
+ __func__, outputDesc->devices()[0]->getId(), caller);
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
} // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index a3600a0..034093c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -47,6 +47,7 @@
#include <AudioOutputDescriptor.h>
#include <AudioPolicyMix.h>
#include <EffectDescriptor.h>
+#include <PreferredMixerAttributesInfo.h>
#include <SoundTriggerSession.h>
#include "EngineLibrary.h"
#include "TypeConverter.h"
@@ -123,7 +124,8 @@
audio_port_handle_t *portId,
std::vector<audio_io_handle_t> *secondaryOutputs,
output_type_t *outputType,
- bool *isSpatialized) override;
+ bool *isSpatialized,
+ bool *isBitPerfect) override;
virtual status_t startOutput(audio_port_handle_t portId);
virtual status_t stopOutput(audio_port_handle_t portId);
virtual bool releaseOutput(audio_port_handle_t portId);
@@ -395,6 +397,21 @@
virtual status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
AudioProfileVector& audioProfiles);
+ status_t getSupportedMixerAttributes(
+ audio_port_handle_t portId,
+ std::vector<audio_mixer_attributes_t>& mixerAttrs) override;
+ status_t setPreferredMixerAttributes(
+ const audio_attributes_t* attr,
+ audio_port_handle_t portId,
+ uid_t uid,
+ const audio_mixer_attributes_t* mixerAttributes) override;
+ status_t getPreferredMixerAttributes(const audio_attributes_t* attr,
+ audio_port_handle_t portId,
+ audio_mixer_attributes_t* mixerAttributes) override;
+ status_t clearPreferredMixerAttributes(const audio_attributes_t* attr,
+ audio_port_handle_t portId,
+ uid_t uid) override;
+
bool isCallScreenModeSupported() override;
void onNewAudioModulesAvailable() override;
@@ -600,7 +617,9 @@
// true if given state represents a device in a telephony or VoIP call
virtual bool isStateInCall(int state) const;
// true if playback to call TX or capture from call RX is possible
- bool isCallAudioAccessible();
+ bool isCallAudioAccessible() const;
+ // true if device is in a telephony or VoIP call or call screening is active
+ bool isInCallOrScreening() const;
// when a device is connected, checks if an open output can be routed
// to this device. If none is open, tries to open one of the available outputs.
@@ -983,6 +1002,10 @@
sp<SourceClientDescriptor> mCallRxSourceClient;
sp<SourceClientDescriptor> mCallTxSourceClient;
+ std::map<audio_port_handle_t,
+ std::map<product_strategy_t,
+ sp<PreferredMixerAttributesInfo>>> mPreferredMixerAttrInfos;
+
// Support for Multi-Stream Decoder (MSD) module
sp<DeviceDescriptor> getMsdAudioInDevice() const;
DeviceVector getMsdAudioOutDevices() const;
@@ -1060,7 +1083,8 @@
bool *isRequestedDeviceForExclusiveUse,
std::vector<sp<AudioPolicyMix>> *secondaryMixes,
output_type_t *outputType,
- bool *isSpatialized);
+ bool *isSpatialized,
+ bool *isBitPerfect);
// internal method to return the output handle for the given device and format
audio_io_handle_t getOutputForDevices(
const DeviceVector &devices,
@@ -1069,6 +1093,7 @@
const audio_config_t *config,
audio_output_flags_t *flags,
bool *isSpatialized,
+ sp<PreferredMixerAttributesInfo> prefMixerAttrInfo = nullptr,
bool forceMutingHaptic = false);
// Internal method checking if a direct output can be opened matching the requested
@@ -1236,11 +1261,15 @@
* @param[in] profile IOProfile to use as template
* @param[in] devices initial route to apply to this output stream
* @param[in] mixerConfig if not null, use this to configure the mixer
+ * @param[in] halConfig if not null, use this to configure the HAL
+ * @param[in] flags the flags to be used to open the output
* @return an output descriptor for the newly opened stream or null in case of error.
*/
sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice(
const sp<IOProfile>& profile, const DeviceVector& devices,
- const audio_config_base_t *mixerConfig = nullptr);
+ const audio_config_base_t *mixerConfig = nullptr,
+ const audio_config_t *halConfig = nullptr,
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE);
bool isOffloadPossible(const audio_offload_info_t& offloadInfo,
bool durationIgnored = false);
@@ -1273,6 +1302,13 @@
AudioProfileVector& audioProfiles,
uint32_t flags,
bool isInput);
+
+ sp<PreferredMixerAttributesInfo> getPreferredMixerAttributesInfo(
+ audio_port_handle_t devicePortId, product_strategy_t strategy);
+ status_t reopenOutput(sp<SwAudioOutputDescriptor> outputDesc,
+ const audio_config_t *config,
+ audio_output_flags_t flags,
+ const char* caller);
};
};
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index b576b6d..4eb5336 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -373,6 +373,7 @@
AutoCallerClear acc;
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized = false;
+ bool isBitPerfect = false;
status_t result = mAudioPolicyManager->getOutputForAttr(&attr, &output, session,
&stream,
attributionSource,
@@ -380,7 +381,8 @@
&flags, &selectedDeviceId, &portId,
&secondaryOutputs,
&outputType,
- &isSpatialized);
+ &isSpatialized,
+ &isBitPerfect);
// FIXME: Introduce a way to check for the the telephony device before opening the output
if (result == NO_ERROR) {
@@ -432,6 +434,7 @@
convertContainer<std::vector<int32_t>>(secondaryOutputs,
legacy2aidl_audio_io_handle_t_int32_t));
_aidl_return->isSpatialized = isSpatialized;
+ _aidl_return->isBitPerfect = isBitPerfect;
} else {
_aidl_return->configBase.format = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_audio_format_t_AudioFormatDescription(config.format));
@@ -2365,4 +2368,89 @@
return Status::ok();
}
+Status AudioPolicyService::getSupportedMixerAttributes(
+ int32_t portIdAidl, std::vector<media::AudioMixerAttributesInternal>* _aidl_return) {
+ if (mAudioPolicyManager == nullptr) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+
+ audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
+
+ std::vector<audio_mixer_attributes_t> mixerAttrs;
+ Mutex::Autolock _l(mLock);
+ RETURN_IF_BINDER_ERROR(
+ binderStatusFromStatusT(mAudioPolicyManager->getSupportedMixerAttributes(
+ portId, mixerAttrs)));
+ *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
+ convertContainer<std::vector<media::AudioMixerAttributesInternal>>(
+ mixerAttrs,
+ legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal));
+ return Status::ok();
+}
+
+Status AudioPolicyService::setPreferredMixerAttributes(
+ const media::AudioAttributesInternal& attrAidl,
+ int32_t portIdAidl,
+ int32_t uidAidl,
+ const media::AudioMixerAttributesInternal& mixerAttrAidl) {
+ if (mAudioPolicyManager == nullptr) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+
+ audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ audio_mixer_attributes_t mixerAttr = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t(mixerAttrAidl));
+ uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
+ audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
+
+ Mutex::Autolock _l(mLock);
+ return binderStatusFromStatusT(
+ mAudioPolicyManager->setPreferredMixerAttributes(&attr, portId, uid, &mixerAttr));
+}
+
+Status AudioPolicyService::getPreferredMixerAttributes(
+ const media::AudioAttributesInternal& attrAidl,
+ int32_t portIdAidl,
+ std::optional<media::AudioMixerAttributesInternal>* _aidl_return) {
+ if (mAudioPolicyManager == nullptr) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+
+ audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
+
+ Mutex::Autolock _l(mLock);
+ audio_mixer_attributes_t mixerAttr = AUDIO_MIXER_ATTRIBUTES_INITIALIZER;
+ RETURN_IF_BINDER_ERROR(
+ binderStatusFromStatusT(mAudioPolicyManager->getPreferredMixerAttributes(
+ &attr, portId, &mixerAttr)));
+ *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
+ legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal(mixerAttr));
+ return Status::ok();
+}
+
+Status AudioPolicyService::clearPreferredMixerAttributes(
+ const media::AudioAttributesInternal& attrAidl,
+ int32_t portIdAidl,
+ int32_t uidAidl) {
+ if (mAudioPolicyManager == nullptr) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+
+ audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
+ audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
+
+ Mutex::Autolock _l(mLock);
+ return binderStatusFromStatusT(
+ mAudioPolicyManager->clearPreferredMixerAttributes(&attr, portId, uid));
+}
+
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index cffacbb..48997db 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -155,7 +155,11 @@
BINDER_METHOD_ENTRY(getSpatializer) \
BINDER_METHOD_ENTRY(canBeSpatialized) \
BINDER_METHOD_ENTRY(getDirectPlaybackSupport) \
-BINDER_METHOD_ENTRY(getDirectProfilesForAttributes) \
+BINDER_METHOD_ENTRY(getDirectProfilesForAttributes) \
+BINDER_METHOD_ENTRY(getSupportedMixerAttributes) \
+BINDER_METHOD_ENTRY(setPreferredMixerAttributes) \
+BINDER_METHOD_ENTRY(getPreferredMixerAttributes) \
+BINDER_METHOD_ENTRY(clearPreferredMixerAttributes) \
// singleton for Binder Method Statistics for IAudioPolicyService
static auto& getIAudioPolicyServiceStatistics() {
@@ -202,6 +206,7 @@
mCaptureStateNotifier(false),
mCreateAudioPolicyManager(createAudioPolicyManager),
mDestroyAudioPolicyManager(destroyAudioPolicyManager) {
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
void AudioPolicyService::loadAudioPolicyManager()
@@ -1323,7 +1328,9 @@
case TRANSACTION_removeDevicesRoleForCapturePreset:
case TRANSACTION_clearDevicesRoleForCapturePreset:
case TRANSACTION_getDevicesForRoleAndCapturePreset:
- case TRANSACTION_getSpatializer: {
+ case TRANSACTION_getSpatializer:
+ case TRANSACTION_setPreferredMixerAttributes:
+ case TRANSACTION_clearPreferredMixerAttributes: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 3a7fffa..58af46d 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -277,6 +277,22 @@
binder::Status getDirectProfilesForAttributes(const media::AudioAttributesInternal& attr,
std::vector<media::audio::common::AudioProfile>* _aidl_return) override;
+ binder::Status getSupportedMixerAttributes(
+ int32_t portId,
+ std::vector<media::AudioMixerAttributesInternal>* _aidl_return) override;
+ binder::Status setPreferredMixerAttributes(
+ const media::AudioAttributesInternal& attr,
+ int32_t portId,
+ int32_t uid,
+ const media::AudioMixerAttributesInternal& mixerAttr) override;
+ binder::Status getPreferredMixerAttributes(
+ const media::AudioAttributesInternal& attr,
+ int32_t portId,
+ std::optional<media::AudioMixerAttributesInternal>* _aidl_return) override;
+ binder::Status clearPreferredMixerAttributes(const media::AudioAttributesInternal& attr,
+ int32_t portId,
+ int32_t uid) override;
+
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
// IBinder::DeathRecipient
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 21f2d09..b940d14 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -255,6 +255,7 @@
: mEngineDescriptor(engineDescriptor),
mPolicyCallback(callback) {
ALOGV("%s", __func__);
+ setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
void Spatializer::onFirstRef() {
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index 96f58d2..2a65546 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -131,8 +131,6 @@
size_t getAudioPortListUpdateCount() const { return mAudioPortListUpdateCount; }
- virtual void addSupportedFormat(audio_format_t /* format */) {}
-
void onRoutingUpdated() override {
mRoutingUpdatedUpdateCount++;
}
@@ -178,6 +176,38 @@
return &(*it);
}
+ String8 getParameters(audio_io_handle_t /* ioHandle */, const String8& /* keys*/ ) override {
+ AudioParameter mAudioParameters;
+ std::string formats;
+ for (const auto& f : mSupportedFormats) {
+ if (!formats.empty()) formats += AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
+ formats += audio_format_to_string(f);
+ }
+ mAudioParameters.add(
+ String8(AudioParameter::keyStreamSupportedFormats),
+ String8(formats.c_str()));
+ mAudioParameters.addInt(String8(AudioParameter::keyStreamSupportedSamplingRates), 48000);
+ std::string channelMasks;
+ for (const auto& cm : mSupportedChannelMasks) {
+ if (audio_channel_mask_is_valid(cm)) {
+ continue;
+ }
+ if (!channelMasks.empty()) channelMasks += AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
+ channelMasks += audio_channel_mask_to_string(cm);
+ }
+ mAudioParameters.add(
+ String8(AudioParameter::keyStreamSupportedChannels), String8(channelMasks.c_str()));
+ return mAudioParameters.toString();
+ }
+
+ void addSupportedFormat(audio_format_t format) {
+ mSupportedFormats.insert(format);
+ }
+
+ void addSupportedChannelMask(audio_channel_mask_t channelMask) {
+ mSupportedChannelMasks.insert(channelMask);
+ }
+
private:
audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
@@ -188,6 +218,8 @@
size_t mRoutingUpdatedUpdateCount = 0;
std::vector<struct audio_port_v7> mConnectedDevicePorts;
std::vector<struct audio_port_v7> mDisconnectedDevicePorts;
+ std::set<audio_format_t> mSupportedFormats;
+ std::set<audio_channel_mask_t> mSupportedChannelMasks;
};
} // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h b/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h
deleted file mode 100644
index 7343b9b..0000000
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h
+++ /dev/null
@@ -1,53 +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.
- */
-
-#include <map>
-#include <set>
-
-#include <system/audio.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "AudioPolicyTestClient.h"
-
-namespace android {
-
-class AudioPolicyManagerTestClientForHdmi : public AudioPolicyManagerTestClient {
-public:
- String8 getParameters(audio_io_handle_t /* ioHandle */, const String8& /* keys*/ ) override {
- AudioParameter mAudioParameters;
- std::string formats;
- for (const auto& f : mSupportedFormats) {
- if (!formats.empty()) formats += AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
- formats += audio_format_to_string(f);
- }
- mAudioParameters.add(
- String8(AudioParameter::keyStreamSupportedFormats),
- String8(formats.c_str()));
- mAudioParameters.addInt(String8(AudioParameter::keyStreamSupportedSamplingRates), 48000);
- mAudioParameters.add(String8(AudioParameter::keyStreamSupportedChannels), String8(""));
- return mAudioParameters.toString();
- }
-
- void addSupportedFormat(audio_format_t format) override {
- mSupportedFormats.insert(format);
- }
-
-private:
- std::set<audio_format_t> mSupportedFormats;
-};
-
-} // namespace android
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index ba5b6b2..a2326b3 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -35,7 +35,6 @@
#include "AudioPolicyInterface.h"
#include "AudioPolicyManagerTestClient.h"
-#include "AudioPolicyManagerTestClientForHdmi.h"
#include "AudioPolicyTestClient.h"
#include "AudioPolicyTestManager.h"
@@ -259,13 +258,14 @@
*portId = AUDIO_PORT_HANDLE_NONE;
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized;
+ bool isBitPerfect;
// TODO b/182392769: use attribution source util
AttributionSourceState attributionSource = AttributionSourceState();
attributionSource.uid = 0;
attributionSource.token = sp<BBinder>::make();
ASSERT_EQ(OK, mManager->getOutputForAttr(
&attr, output, session, &stream, attributionSource, &config, &flags,
- selectedDeviceId, portId, {}, &outputType, &isSpatialized));
+ selectedDeviceId, portId, {}, &outputType, &isSpatialized, &isBitPerfect));
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
}
@@ -982,6 +982,77 @@
}
}
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, PreferredMixerAttributes) {
+ mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT);
+ mClient->addSupportedChannelMask(AUDIO_CHANNEL_OUT_STEREO);
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "", "", AUDIO_FORMAT_DEFAULT));
+ auto devices = mManager->getAvailableOutputDevices();
+ audio_port_handle_t maxPortId = 0;
+ audio_port_handle_t speakerPortId;
+ audio_port_handle_t usbPortId;
+ for (auto device : devices) {
+ maxPortId = std::max(maxPortId, device->getId());
+ if (device->type() == AUDIO_DEVICE_OUT_SPEAKER) {
+ speakerPortId = device->getId();
+ } else if (device->type() == AUDIO_DEVICE_OUT_USB_DEVICE) {
+ usbPortId = device->getId();
+ }
+ }
+
+ const uid_t uid = 1234;
+ const uid_t otherUid = 4321;
+ const audio_attributes_t mediaAttr = {
+ .content_type = AUDIO_CONTENT_TYPE_MUSIC,
+ .usage = AUDIO_USAGE_MEDIA,
+ };
+ const audio_attributes_t alarmAttr = {
+ .content_type = AUDIO_CONTENT_TYPE_SONIFICATION,
+ .usage = AUDIO_USAGE_ALARM,
+ };
+
+ std::vector<audio_mixer_attributes_t> mixerAttributes;
+ EXPECT_EQ(NO_ERROR, mManager->getSupportedMixerAttributes(usbPortId, mixerAttributes));
+ for (const auto attrToSet : mixerAttributes) {
+ audio_mixer_attributes_t attrFromQuery = AUDIO_MIXER_ATTRIBUTES_INITIALIZER;
+
+ // The given device is not available
+ EXPECT_EQ(BAD_VALUE,
+ mManager->setPreferredMixerAttributes(
+ &mediaAttr, maxPortId + 1, uid, &attrToSet));
+ // The only allowed device is USB
+ EXPECT_EQ(BAD_VALUE,
+ mManager->setPreferredMixerAttributes(
+ &mediaAttr, speakerPortId, uid, &attrToSet));
+ // The only allowed usage is media
+ EXPECT_EQ(BAD_VALUE,
+ mManager->setPreferredMixerAttributes(&alarmAttr, usbPortId, uid, &attrToSet));
+ // Nothing set yet, must get null when query
+ EXPECT_EQ(NAME_NOT_FOUND,
+ mManager->getPreferredMixerAttributes(&mediaAttr, usbPortId, &attrFromQuery));
+ EXPECT_EQ(NO_ERROR,
+ mManager->setPreferredMixerAttributes(
+ &mediaAttr, usbPortId, uid, &attrToSet));
+ EXPECT_EQ(NO_ERROR,
+ mManager->getPreferredMixerAttributes(&mediaAttr, usbPortId, &attrFromQuery));
+ EXPECT_EQ(attrToSet.config.format, attrFromQuery.config.format);
+ EXPECT_EQ(attrToSet.config.sample_rate, attrFromQuery.config.sample_rate);
+ EXPECT_EQ(attrToSet.config.channel_mask, attrFromQuery.config.channel_mask);
+ EXPECT_EQ(attrToSet.mixer_behavior, attrFromQuery.mixer_behavior);
+ EXPECT_EQ(NAME_NOT_FOUND,
+ mManager->clearPreferredMixerAttributes(&mediaAttr, speakerPortId, uid));
+ EXPECT_EQ(PERMISSION_DENIED,
+ mManager->clearPreferredMixerAttributes(&mediaAttr, usbPortId, otherUid));
+ EXPECT_EQ(NO_ERROR,
+ mManager->clearPreferredMixerAttributes(&mediaAttr, usbPortId, uid));
+ }
+
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "", "", AUDIO_FORMAT_LDAC));
+}
+
class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
protected:
void TearDown() override;
@@ -1143,9 +1214,6 @@
std::map<audio_format_t, bool> getSurroundFormatsHelper();
std::vector<audio_format_t> getReportedSurroundFormatsHelper();
std::unordered_set<audio_format_t> getFormatsFromPorts();
- AudioPolicyManagerTestClient* getClient() override {
- return new AudioPolicyManagerTestClientForHdmi;
- }
void TearDown() override;
static const std::string sTvConfig;
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index d342aea..c937d3a 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -54,6 +54,7 @@
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
+ <mixPort name="hifi_output" role="source"/>
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
@@ -74,6 +75,8 @@
<devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink"
encodedFormats="AUDIO_FORMAT_LDAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_AAC AUDIO_FORMAT_SBC">
</devicePort>
+ <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink">
+ </devicePort>
</devicePorts>
<routes>
<route type="mix" sink="Speaker"
@@ -89,7 +92,9 @@
<route type="mix" sink="mixport_bt_hfp_input"
sources="BT SCO Headset Mic"/>
<route type="mix" sink="BT A2DP Out"
- sources="primary output"/>
+ sources="primary output,hifi_output"/>
+ <route type="mix" sink="USB Device Out"
+ sources="primary output,hifi_output"/>
</routes>
</module>
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 7b5ccc8..5e99389 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2926,7 +2926,7 @@
mCurrentAfTriggerId(0),
mCurrentPreCaptureTriggerId(0),
mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
- mAutoframingOverride(ANDROID_CONTROL_AUTOFRAMING_ON),
+ mAutoframingOverride(ANDROID_CONTROL_AUTOFRAMING_OFF),
mComposerOutput(false),
mCameraMute(ANDROID_SENSOR_TEST_PATTERN_MODE_OFF),
mCameraMuteChanged(false),
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 88f25f6..a441638 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -128,6 +128,36 @@
return res;
}
+status_t fixupAutoframingTags(CameraMetadata& resultMetadata) {
+ status_t res = OK;
+ camera_metadata_entry autoframingEntry =
+ resultMetadata.find(ANDROID_CONTROL_AUTOFRAMING);
+ if (autoframingEntry.count == 0) {
+ const uint8_t defaultAutoframingEntry = ANDROID_CONTROL_AUTOFRAMING_OFF;
+ res = resultMetadata.update(ANDROID_CONTROL_AUTOFRAMING, &defaultAutoframingEntry, 1);
+ if (res != OK) {
+ ALOGE("%s: Failed to update ANDROID_CONTROL_AUTOFRAMING: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+ }
+
+ camera_metadata_entry autoframingStateEntry =
+ resultMetadata.find(ANDROID_CONTROL_AUTOFRAMING_STATE);
+ if (autoframingStateEntry.count == 0) {
+ const uint8_t defaultAutoframingStateEntry = ANDROID_CONTROL_AUTOFRAMING_STATE_INACTIVE;
+ res = resultMetadata.update(ANDROID_CONTROL_AUTOFRAMING_STATE,
+ &defaultAutoframingStateEntry, 1);
+ if (res != OK) {
+ ALOGE("%s: Failed to update ANDROID_CONTROL_AUTOFRAMING_STATE: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+ }
+
+ return res;
+}
+
void correctMeteringRegions(camera_metadata_t *meta) {
if (meta == nullptr) return;
@@ -355,24 +385,17 @@
}
// Fix up autoframing metadata
- camera_metadata_entry autoframingEntry =
- captureResult.mMetadata.find(ANDROID_CONTROL_AUTOFRAMING);
- if (autoframingEntry.count == 0) {
- const uint8_t defaultAutoframingEntry = ANDROID_CONTROL_AUTOFRAMING_OFF;
- if (captureResult.mMetadata.update(ANDROID_CONTROL_AUTOFRAMING,
- &defaultAutoframingEntry, 1) != OK) {
- SET_ERR("Failed to set autoframing mode in metadata for frame %d", frameNumber);
- return;
- }
+ res = fixupAutoframingTags(captureResult.mMetadata);
+ if (res != OK) {
+ SET_ERR("Failed to set autoframing defaults in result metadata: %s (%d)",
+ strerror(-res), res);
+ return;
}
-
- camera_metadata_entry autoframingStateEntry =
- captureResult.mMetadata.find(ANDROID_CONTROL_AUTOFRAMING_STATE);
- if (autoframingStateEntry.count == 0) {
- const uint8_t defaultAutoframingStateEntry = ANDROID_CONTROL_AUTOFRAMING_STATE_INACTIVE;
- if (captureResult.mMetadata.update(ANDROID_CONTROL_AUTOFRAMING_STATE,
- &defaultAutoframingStateEntry, 1) != OK) {
- SET_ERR("Failed to set autoframing state in metadata for frame %d", frameNumber);
+ for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
+ res = fixupAutoframingTags(physicalMetadata.mPhysicalCameraMetadata);
+ if (res != OK) {
+ SET_ERR("Failed to set autoframing defaults in physical result metadata: %s (%d)",
+ strerror(-res), res);
return;
}
}
diff --git a/services/camera/libcameraservice/device3/RotateAndCropMapper.cpp b/services/camera/libcameraservice/device3/RotateAndCropMapper.cpp
index a02e5f6..9cdd365 100644
--- a/services/camera/libcameraservice/device3/RotateAndCropMapper.cpp
+++ b/services/camera/libcameraservice/device3/RotateAndCropMapper.cpp
@@ -142,13 +142,13 @@
ch : // pillarbox or 1:1, full height
cw / mRotateAspect; // letterbox, not full height
switch (rotateMode) {
- case ANDROID_SCALER_ROTATE_AND_CROP_90:
+ case ANDROID_SCALER_ROTATE_AND_CROP_270:
transformMat[1] = -rw / ch; // +y -> -x
transformMat[2] = rh / cw; // +x -> +y
xShift = (cw + rw) / 2; // left edge of crop to right edge of rotated
yShift = (ch - rh) / 2; // top edge of crop to top edge of rotated
break;
- case ANDROID_SCALER_ROTATE_AND_CROP_270:
+ case ANDROID_SCALER_ROTATE_AND_CROP_90:
transformMat[1] = rw / ch; // +y -> +x
transformMat[2] = -rh / cw; // +x -> -y
xShift = (cw - rw) / 2; // left edge of crop to left edge of rotated
@@ -271,13 +271,13 @@
rx = cx + (cw - rw) / 2;
ry = cy + (ch - rh) / 2;
switch (rotateMode) {
- case ANDROID_SCALER_ROTATE_AND_CROP_90:
+ case ANDROID_SCALER_ROTATE_AND_CROP_270:
transformMat[1] = ch / rw; // +y -> +x
transformMat[2] = -cw / rh; // +x -> -y
xShift = -(cw - rw) / 2; // left edge of rotated to left edge of cropped
yShift = ry - cy + ch; // top edge of rotated to bottom edge of cropped
break;
- case ANDROID_SCALER_ROTATE_AND_CROP_270:
+ case ANDROID_SCALER_ROTATE_AND_CROP_90:
transformMat[1] = -ch / rw; // +y -> -x
transformMat[2] = cw / rh; // +x -> +y
xShift = (cw + rw) / 2; // left edge of rotated to left edge of cropped
diff --git a/services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h b/services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h
index 42e458c..8b9b92b 100644
--- a/services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h
+++ b/services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h
@@ -100,5 +100,7 @@
ANDROID_CONTROL_AUTOFRAMING_STATE,
ANDROID_CONTROL_SETTINGS_OVERRIDE,
ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER,
+ ANDROID_EXTENSION_CURRENT_TYPE,
+ ANDROID_EXTENSION_STRENGTH,
} },
};
diff --git a/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp b/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp
index 3c187cd..9f86526 100644
--- a/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp
+++ b/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp
@@ -195,6 +195,7 @@
// Round-trip results can't be exact since we've gone from a large int range -> small int range
// and back, leading to quantization. For 4/3 aspect ratio, no more than +-1 error expected
+
e = result.find(ANDROID_CONTROL_AE_REGIONS);
EXPECT_EQUAL_WITHIN_N(full_region, e.data.i32, 1, "Round-tripped AE region isn't right");
@@ -209,11 +210,11 @@
EXPECT_EQUAL_WITHIN_N(full_face, e.data.i32, 1, "App-side face rectangle isn't right");
auto full_landmarks = std::vector<int32_t> {
- full_crop[0], full_crop[1] + full_crop[3],
full_crop[0] + full_crop[2], full_crop[1],
- full_crop[0] + full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4,
+ full_crop[0], full_crop[1] + full_crop[3],
+ full_crop[0] + 3*full_crop[2]/4, full_crop[1] + full_crop[3]/4,
full_crop[0] + full_crop[2]/2, full_crop[1] + full_crop[3]/2,
- full_crop[0] + 3*full_crop[2]/4, full_crop[1] + full_crop[3]/4
+ full_crop[0] + full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4
};
e = result.find(ANDROID_STATISTICS_FACE_LANDMARKS);
EXPECT_EQUAL_WITHIN_N(full_landmarks, e.data.i32, 1, "App-side face landmarks aren't right");
@@ -286,7 +287,6 @@
// Round-trip results can't be exact since we've gone from a large int range -> small int range
// and back, leading to quantization. For 4/3 aspect ratio, no more than +-1 error expected
-
e = result.find(ANDROID_CONTROL_AE_REGIONS);
EXPECT_EQUAL_WITHIN_N(full_region, e.data.i32, 1, "Round-tripped AE region isn't right");
@@ -301,11 +301,11 @@
EXPECT_EQUAL_WITHIN_N(full_face, e.data.i32, 1, "App-side face rectangle isn't right");
auto full_landmarks = std::vector<int32_t> {
- full_crop[0] + full_crop[2], full_crop[1],
full_crop[0], full_crop[1] + full_crop[3],
- full_crop[0] + 3*full_crop[2]/4, full_crop[1] + full_crop[3]/4,
+ full_crop[0] + full_crop[2], full_crop[1],
+ full_crop[0] + full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4,
full_crop[0] + full_crop[2]/2, full_crop[1] + full_crop[3]/2,
- full_crop[0] + full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4
+ full_crop[0] + 3*full_crop[2]/4, full_crop[1] + full_crop[3]/4
};
e = result.find(ANDROID_STATISTICS_FACE_LANDMARKS);
EXPECT_EQUAL_WITHIN_N(full_landmarks, e.data.i32, 1, "App-side face landmarks aren't right");
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index 119bb6c..7af6c41 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -269,6 +269,24 @@
"enabled",
};
+static constexpr const char * const MidiDeviceCloseFields[] {
+ "mediametrics_midi_device_close_reported",
+ "uid",
+ "midi_device_id",
+ "input_port_count",
+ "output_port_count",
+ "device_type",
+ "is_shared",
+ "supports_ump",
+ "using_alsa",
+ "duration_ns",
+ "opened_count",
+ "closed_count",
+ "device_disconnected",
+ "total_input_bytes",
+ "total_output_bytes",
+};
+
/**
* printFields is a helper method that prints the fields and corresponding values
* in a human readable style.
@@ -497,6 +515,15 @@
[this](const std::shared_ptr<const android::mediametrics::Item> &item){
mSpatializer.onEvent(item);
}));
+
+ // Handle MIDI
+ mActions.addAction(
+ AMEDIAMETRICS_KEY_AUDIO_MIDI "." AMEDIAMETRICS_PROP_EVENT,
+ std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_DEVICECLOSED),
+ std::make_shared<AnalyticsActions::Function>(
+ [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
+ mMidiLogging.onEvent(item);
+ }));
}
AudioAnalytics::~AudioAnalytics()
@@ -1710,6 +1737,127 @@
return { s, n };
}
+void AudioAnalytics::MidiLogging::onEvent(
+ const std::shared_ptr<const android::mediametrics::Item> &item) const {
+ const std::string& key = item->getKey();
+
+ const auto uid = item->getUid();
+
+ int32_t deviceId = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_DEVICEID, &deviceId);
+
+ int32_t inputPortCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_INPUTPORTCOUNT, &inputPortCount);
+
+ int32_t outputPortCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_OUTPUTPORTCOUNT, &outputPortCount);
+
+ int32_t hardwareType = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_HARDWARETYPE, &hardwareType);
+
+ std::string isSharedString;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_ISSHARED, &isSharedString);
+ const bool isShared = (isSharedString == "true");
+
+ std::string supportsMidiUmpString;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_SUPPORTSMIDIUMP, &supportsMidiUmpString);
+ const bool supportsMidiUmp = (supportsMidiUmpString == "true");
+
+ std::string usingAlsaString;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_USINGALSA, &usingAlsaString);
+ const bool usingAlsa = (usingAlsaString == "true");
+
+ int64_t durationNs = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_DURATIONNS, &durationNs);
+
+ int32_t openedCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_OPENEDCOUNT, &openedCount);
+
+ int32_t closedCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_CLOSEDCOUNT, &closedCount);
+
+ std::string deviceDisconnectedString;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_DEVICEDISCONNECTED, &deviceDisconnectedString);
+ const bool deviceDisconnected = (deviceDisconnectedString == "true");
+
+ int32_t totalInputBytes = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_TOTALINPUTBYTES, &totalInputBytes);
+
+ int32_t totalOutputBytes = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_TOTALOUTPUTBYTES, &totalOutputBytes);
+
+ LOG(LOG_LEVEL) << "key:" << key
+ << " uid:" << uid
+ << " id:" << deviceId
+ << " input_port_count:" << inputPortCount
+ << " output_port_count:" << outputPortCount
+ << " device_type:" << hardwareType
+ << " is_shared:" << isSharedString
+ << " supports_ump:" << supportsMidiUmpString
+ << " using_alsa:" << usingAlsaString
+ << " duration_opened_ms:" << durationNs
+ << " opened_count:" << openedCount
+ << " closed_count:" << closedCount
+ << " device_disconnected:" << deviceDisconnectedString
+ << " total_input_bytes:" << totalInputBytes
+ << " total_output_bytes:" << totalOutputBytes;
+
+ if (mAudioAnalytics.mDeliverStatistics) {
+ const auto result = sendToStatsd(
+ CONDITION(stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED)
+ , uid
+ , deviceId
+ , inputPortCount
+ , outputPortCount
+ , hardwareType
+ , isShared
+ , supportsMidiUmp
+ , usingAlsa
+ , durationNs
+ , openedCount
+ , closedCount
+ , deviceDisconnected
+ , totalInputBytes
+ , totalOutputBytes);
+ std::stringstream ss;
+ ss << "result:" << result;
+ const auto fieldsStr = printFields(MidiDeviceCloseFields,
+ CONDITION(stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED)
+ , uid
+ , deviceId
+ , inputPortCount
+ , outputPortCount
+ , hardwareType
+ , isShared
+ , supportsMidiUmp
+ , usingAlsa
+ , durationNs
+ , openedCount
+ , closedCount
+ , deviceDisconnected
+ , totalInputBytes
+ , totalOutputBytes);
+ ss << " " << fieldsStr;
+ std::string str = ss.str();
+ ALOGV("%s: statsd %s", __func__, str.c_str());
+ mAudioAnalytics.mStatsdLog->log(
+ stats::media_metrics::MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED, str);
+ }
+}
+
// This method currently suppresses the name.
std::string AudioAnalytics::getDeviceNamesFromOutputDevices(std::string_view devices) const {
std::string deviceNames;
diff --git a/services/mediametrics/iface_statsd.cpp b/services/mediametrics/iface_statsd.cpp
index f64b3ec..8a48ce5 100644
--- a/services/mediametrics/iface_statsd.cpp
+++ b/services/mediametrics/iface_statsd.cpp
@@ -87,6 +87,9 @@
{ "nuplayer", statsd_nuplayer },
{ "nuplayer2", statsd_nuplayer },
{ "recorder", statsd_recorder },
+ { "media_drm_created", statsd_media_drm_created },
+ { "media_drm_session_opened", statsd_media_drm_session_opened },
+ { "media_drm_errored", statsd_media_drm_errored },
};
return dump2StatsdInternal(statsd_pushers, item, statsdLog);
}
diff --git a/services/mediametrics/include/mediametricsservice/AudioAnalytics.h b/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
index 82e928e..f0a4ac8 100644
--- a/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
+++ b/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
@@ -363,6 +363,20 @@
SimpleLog mSimpleLog GUARDED_BY(mLock) {64};
} mSpatializer{*this};
+ // MidiLogging collects info whenever a MIDI device is closed.
+ class MidiLogging {
+ public:
+ explicit MidiLogging(AudioAnalytics &audioAnalytics)
+ : mAudioAnalytics(audioAnalytics) {}
+
+ void onEvent(
+ const std::shared_ptr<const android::mediametrics::Item> &item) const;
+
+ private:
+
+ AudioAnalytics &mAudioAnalytics;
+ } mMidiLogging{*this};
+
AudioPowerUsage mAudioPowerUsage;
};
diff --git a/services/mediametrics/include/mediametricsservice/iface_statsd.h b/services/mediametrics/include/mediametricsservice/iface_statsd.h
index c2a8b3c..a97a386 100644
--- a/services/mediametrics/include/mediametricsservice/iface_statsd.h
+++ b/services/mediametrics/include/mediametricsservice/iface_statsd.h
@@ -32,6 +32,9 @@
extern statsd_pusher statsd_codec;
extern statsd_pusher statsd_extractor;
extern statsd_pusher statsd_mediaparser;
+extern statsd_pusher statsd_media_drm_created;
+extern statsd_pusher statsd_media_drm_session_opened;
+extern statsd_pusher statsd_media_drm_errored;
extern statsd_pusher statsd_nuplayer;
extern statsd_pusher statsd_recorder;
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
index 8769efb..1008531 100644
--- a/services/mediametrics/statsd_drm.cpp
+++ b/services/mediametrics/statsd_drm.cpp
@@ -233,4 +233,112 @@
return true;
}
+bool statsd_media_drm_created(const std::shared_ptr<const mediametrics::Item>& item,
+ const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+ int64_t uuid_lsb = -1;
+ if (!item->getInt64("uuid_lsb", &uuid_lsb)) return false;
+ int64_t uuid_msb = -1;
+ if (!item->getInt64("uuid_msb", &uuid_msb)) return false;
+ int64_t object_nonce_lsb = -1;
+ if (!item->getInt64("object_nonce_lsb", &object_nonce_lsb)) return false;
+ int64_t object_nonce_msb = -1;
+ if (!item->getInt64("object_nonce_msb", &object_nonce_msb)) return false;
+ int64_t apex_version = -1;
+ item->getInt64("apex_version", &apex_version);
+ const int result = stats_write(
+ stats::media_metrics::MEDIA_DRM_CREATED,
+ uuid_lsb, uuid_msb, object_nonce_lsb,
+ object_nonce_msb, apex_version);
+
+ std::stringstream log;
+ log << "result:" << result << " {"
+ << " media_drm_created:"
+ << stats::media_metrics::MEDIA_DRM_CREATED
+ << " uuid_lsb:" << uuid_lsb
+ << " uuid_msb:" << uuid_msb
+ << " object_nonce_lsb:" << object_nonce_lsb
+ << " object_nonce_msb:" << object_nonce_msb
+ << " apex_version:" << apex_version
+ << " }";
+ statsdLog->log(stats::media_metrics::MEDIA_DRM_CREATED, log.str());
+ return true;
+}
+
+bool statsd_media_drm_session_opened(const std::shared_ptr<const mediametrics::Item>& item,
+ const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+ int64_t object_nonce_lsb = -1;
+ if (!item->getInt64("object_nonce_lsb", &object_nonce_lsb)) return false;
+ int64_t object_nonce_msb = -1;
+ if (!item->getInt64("object_nonce_msb", &object_nonce_msb)) return false;
+ int64_t session_nonce_lsb = -1;
+ if (!item->getInt64("session_nonce_lsb", &session_nonce_lsb)) return false;
+ int64_t session_nonce_msb = -1;
+ if (!item->getInt64("session_nonce_msb", &session_nonce_msb)) return false;
+ int32_t requested_security_level = -1;
+ if (!item->getInt32("requested_security_level", &requested_security_level)) return false;
+ int32_t opened_security_level = -1;
+ if (!item->getInt32("opened_security_level", &opened_security_level)) return false;
+ const int result = stats_write(
+ stats::media_metrics::MEDIA_DRM_SESSION_OPENED, object_nonce_lsb,
+ object_nonce_msb, session_nonce_lsb, session_nonce_msb,
+ requested_security_level, opened_security_level);
+
+ std::stringstream log;
+ log << "result:" << result << " {"
+ << " media_drm_session_opened:"
+ << stats::media_metrics::MEDIA_DRM_SESSION_OPENED
+ << " object_nonce_lsb:" << object_nonce_lsb
+ << " object_nonce_msb:" << object_nonce_msb
+ << " session_nonce_lsb:" << session_nonce_lsb
+ << " session_nonce_msb:" << session_nonce_msb
+ << " requested_security_level:" << requested_security_level
+ << " opened_security_level:" << opened_security_level
+ << " }";
+ statsdLog->log(stats::media_metrics::MEDIA_DRM_SESSION_OPENED, log.str());
+ return true;
+}
+
+bool statsd_media_drm_errored(const std::shared_ptr<const mediametrics::Item>& item,
+ const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+ int64_t object_nonce_lsb = -1;
+ if (!item->getInt64("object_nonce_lsb", &object_nonce_lsb)) return false;
+ int64_t object_nonce_msb = -1;
+ if (!item->getInt64("object_nonce_msb", &object_nonce_msb)) return false;
+ int64_t session_nonce_lsb = 0;
+ item->getInt64("session_nonce_lsb", &session_nonce_lsb);
+ int64_t session_nonce_msb = 0;
+ item->getInt64("session_nonce_msb", &session_nonce_msb);
+ int32_t api = -1;
+ if (!item->getInt32("api", &api)) return false;
+ int32_t error_code = -1;
+ if (!item->getInt32("error_code", &error_code)) return false;
+ int32_t cdm_err = 0;
+ item->getInt32("cdm_err", &cdm_err);
+ int32_t oem_err = 0;
+ item->getInt32("oem_err", &oem_err);
+ const int result = stats_write(
+ stats::media_metrics::MEDIA_DRM_ERRORED, object_nonce_lsb,
+ object_nonce_msb, session_nonce_lsb, session_nonce_msb,
+ api, error_code, cdm_err, oem_err);
+
+ std::stringstream log;
+ log << "result:" << result << " {"
+ << " media_drm_errored:"
+ << stats::media_metrics::MEDIA_DRM_ERRORED
+ << " object_nonce_lsb:" << object_nonce_lsb
+ << " object_nonce_msb:" << object_nonce_msb
+ << " session_nonce_lsb:" << session_nonce_lsb
+ << " session_nonce_msb:" << session_nonce_msb
+ << " api:" << api
+ << " error_code:" << error_code
+ << " cdm_err:" << cdm_err
+ << " oem_err:" << oem_err
+ << " }";
+ statsdLog->log(stats::media_metrics::MEDIA_DRM_ERRORED, log.str());
+ return true;
+}
+
} // namespace android
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index b55b601..fd546f6 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -69,6 +69,10 @@
result << " Reference Count: " << mOpenCount << "\n";
result << " Session Id: " << getSessionId() << "\n";
result << " Privacy Sensitive: " << isPrivacySensitive() << "\n";
+ result << " Hardware Channel Count:" << getHardwareSamplesPerFrame() << "\n";
+ result << " Hardware Format: " << getHardwareFormat() << " ("
+ << audio_format_to_string(getHardwareFormat()) << ")\n";
+ result << " Hardware Sample Rate: " << getHardwareSampleRate() << "\n";
result << " Connected: " << mConnected.load() << "\n";
result << " Registered Streams:" << "\n";
result << AAudioServiceStreamShared::dumpHeader() << "\n";
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 290e9ff..3d237b3 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -231,6 +231,9 @@
setFormat(config.format);
setSampleRate(config.sample_rate);
+ setHardwareSampleRate(getSampleRate());
+ setHardwareFormat(getFormat());
+ setHardwareSamplesPerFrame(AAudioConvert_channelMaskToCount(getChannelMask()));
// If the position is not updated while the timestamp is updated for more than a certain amount,
// the timestamp reported from the HAL may not be accurate. Here, a timestamp grace period is
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index dd421fe..02202d8 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -82,6 +82,9 @@
setDeviceId(mStreamInternal->getDeviceId());
setSessionId(mStreamInternal->getSessionId());
setFormat(AUDIO_FORMAT_PCM_FLOAT); // force for mixer
+ setHardwareSampleRate(mStreamInternal->getHardwareSampleRate());
+ setHardwareFormat(mStreamInternal->getHardwareFormat());
+ setHardwareSamplesPerFrame(mStreamInternal->getHardwareSamplesPerFrame());
mFramesPerBurst = mStreamInternal->getFramesPerBurst();
return result;
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index d395c25..35d712c 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -84,7 +84,8 @@
std::string AAudioServiceStreamBase::dumpHeader() {
return std::string(
- " T Handle UId Port Run State Format Burst Chan Mask Capacity");
+ " T Handle UId Port Run State Format Burst Chan Mask Capacity"
+ " HwFormat HwChan HwRate");
}
std::string AAudioServiceStreamBase::dump() const {
@@ -101,6 +102,9 @@
result << std::setw(5) << getSamplesPerFrame();
result << std::setw(8) << std::hex << getChannelMask() << std::dec;
result << std::setw(9) << getBufferCapacity();
+ result << std::setw(9) << getHardwareFormat();
+ result << std::setw(7) << getHardwareSamplesPerFrame();
+ result << std::setw(7) << getHardwareSampleRate();
return result.str();
}
@@ -435,7 +439,15 @@
}
}
if (isIdle_l() && AudioClock::getNanoseconds() >= standbyTime) {
- standby_l();
+ aaudio_result_t result = standby_l();
+ if (result != AAUDIO_OK) {
+ // If standby failed because of the function is not implemented, there is no
+ // need to retry. Otherwise, retry standby later.
+ ALOGW("Failed to enter standby, error=%d", result);
+ standbyTime = result == AAUDIO_ERROR_UNIMPLEMENTED
+ ? std::numeric_limits<int64_t>::max()
+ : AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
+ }
}
if (command != nullptr) {
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index b2ba725..b5f8b90 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -320,7 +320,7 @@
}
virtual aaudio_result_t standby_l() REQUIRES(mLock) {
- return AAUDIO_ERROR_UNAVAILABLE;
+ return AAUDIO_ERROR_UNIMPLEMENTED;
}
class ExitStandbyParam : public AAudioCommandParam {
public:
diff --git a/services/oboeservice/fuzzer/Android.bp b/services/oboeservice/fuzzer/Android.bp
index 605ac01..91ae511 100644
--- a/services/oboeservice/fuzzer/Android.bp
+++ b/services/oboeservice/fuzzer/Android.bp
@@ -29,6 +29,9 @@
cc_fuzz {
name: "oboeservice_fuzzer",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
srcs: [
"oboeservice_fuzzer.cpp",
],
diff --git a/services/oboeservice/fuzzer/README.md b/services/oboeservice/fuzzer/README.md
index ae7af3eb..617822f 100644
--- a/services/oboeservice/fuzzer/README.md
+++ b/services/oboeservice/fuzzer/README.md
@@ -23,21 +23,24 @@
12. InputPreset
13. BufferCapacity
-| Parameter| Valid Input Values| Configured Value|
-|------------- |-------------| ----- |
-| `AAudioFormat` | `AAUDIO_FORMAT_UNSPECIFIED`, `AAUDIO_FORMAT_PCM_I16`, `AAUDIO_FORMAT_PCM_FLOAT` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
-| `UserId` | `INT32_MIN` to `INT32_MAX` | Value obtained from getuid() |
-| `ProcessId` | `INT32_MIN` to `INT32_MAX` | Value obtained from getpid() |
-| `InService` | `bool` | Value obtained from FuzzedDataProvider |
-| `DeviceId` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
-| `SampleRate` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
-| `ChannelMask` | `AAUDIO_UNSPECIFIED`, `AAUDIO_CHANNEL_INDEX_MASK_1`, `AAUDIO_CHANNEL_INDEX_MASK_2`, `AAUDIO_CHANNEL_INDEX_MASK_3`, `AAUDIO_CHANNEL_INDEX_MASK_4`, `AAUDIO_CHANNEL_INDEX_MASK_5`, `AAUDIO_CHANNEL_INDEX_MASK_6`, `AAUDIO_CHANNEL_INDEX_MASK_7`, `AAUDIO_CHANNEL_INDEX_MASK_8`, `AAUDIO_CHANNEL_INDEX_MASK_9`, `AAUDIO_CHANNEL_INDEX_MASK_10`, `AAUDIO_CHANNEL_INDEX_MASK_11`, `AAUDIO_CHANNEL_INDEX_MASK_12`, `AAUDIO_CHANNEL_INDEX_MASK_13`, `AAUDIO_CHANNEL_INDEX_MASK_14`, `AAUDIO_CHANNEL_INDEX_MASK_15`, `AAUDIO_CHANNEL_INDEX_MASK_16`, `AAUDIO_CHANNEL_INDEX_MASK_17`, `AAUDIO_CHANNEL_INDEX_MASK_18`, `AAUDIO_CHANNEL_INDEX_MASK_19`, `AAUDIO_CHANNEL_INDEX_MASK_20`, `AAUDIO_CHANNEL_INDEX_MASK_21`, `AAUDIO_CHANNEL_INDEX_MASK_22`, `AAUDIO_CHANNEL_INDEX_MASK_23`, `AAUDIO_CHANNEL_INDEX_MASK_24`, `AAUDIO_CHANNEL_MONO`, `AAUDIO_CHANNEL_STEREO`, `AAUDIO_CHANNEL_FRONT_BACK`, `AAUDIO_CHANNEL_2POINT0POINT2`, `AAUDIO_CHANNEL_2POINT1POINT2`, `AAUDIO_CHANNEL_3POINT0POINT2`, `AAUDIO_CHANNEL_3POINT1POINT2`, `AAUDIO_CHANNEL_5POINT1`, `AAUDIO_CHANNEL_MONO`, `AAUDIO_CHANNEL_STEREO`, `AAUDIO_CHANNEL_2POINT1`, `AAUDIO_CHANNEL_TRI`, `AAUDIO_CHANNEL_TRI_BACK`, `AAUDIO_CHANNEL_3POINT1`, `AAUDIO_CHANNEL_2POINT0POINT2`, `AAUDIO_CHANNEL_2POINT1POINT2`, `AAUDIO_CHANNEL_3POINT0POINT2`, `AAUDIO_CHANNEL_3POINT1POINT2`, `AAUDIO_CHANNEL_QUAD`, `AAUDIO_CHANNEL_QUAD_SIDE`, `AAUDIO_CHANNEL_SURROUND`, `AAUDIO_CHANNEL_PENTA`, `AAUDIO_CHANNEL_5POINT1`, `AAUDIO_CHANNEL_5POINT1_SIDE`, `AAUDIO_CHANNEL_5POINT1POINT2`, `AAUDIO_CHANNEL_5POINT1POINT4`, `AAUDIO_CHANNEL_6POINT1`, `AAUDIO_CHANNEL_7POINT1`, `AAUDIO_CHANNEL_7POINT1POINT2`, `AAUDIO_CHANNEL_7POINT1POINT4`, `AAUDIO_CHANNEL_9POINT1POINT4`, `AAUDIO_CHANNEL_9POINT1POINT6` | Value obtained from FuzzedDataProvider |
-| `Direction` | `AAUDIO_DIRECTION_OUTPUT`, `AAUDIO_DIRECTION_INPUT` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
-| `SharingMode` | `AAUDIO_SHARING_MODE_EXCLUSIVE`, `AAUDIO_SHARING_MODE_SHARED` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
-| `Usage` | `AAUDIO_USAGE_MEDIA`, `AAUDIO_USAGE_VOICE_COMMUNICATION`, `AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING`, `AAUDIO_USAGE_ALARM`, `AAUDIO_USAGE_NOTIFICATION`, `AAUDIO_USAGE_NOTIFICATION_RINGTONE`, `AAUDIO_USAGE_NOTIFICATION_EVENT`, `AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY`, `AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE`, `AAUDIO_USAGE_ASSISTANCE_SONIFICATION`, `AAUDIO_USAGE_GAME`, `AAUDIO_USAGE_ASSISTANT`, `AAUDIO_SYSTEM_USAGE_EMERGENCY`, `AAUDIO_SYSTEM_USAGE_SAFETY`, `AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS`, `AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
-| `ContentType` | `AAUDIO_CONTENT_TYPE_SPEECH`, `AAUDIO_CONTENT_TYPE_MUSIC`, `AAUDIO_CONTENT_TYPE_MOVIE`, `AAUDIO_CONTENT_TYPE_SONIFICATION` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
-| `InputPreset` | `AAUDIO_INPUT_PRESET_GENERIC`, `AAUDIO_INPUT_PRESET_CAMCORDER`, `AAUDIO_INPUT_PRESET_VOICE_RECOGNITION`, `AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION`, `AAUDIO_INPUT_PRESET_UNPROCESSED`, `AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
-| `BufferCapacity` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
+| Parameter | Valid Input Values| Configured Value|
+|---------------------------|-------------| ----- |
+| `Format` | `AAUDIO_FORMAT_UNSPECIFIED`, `AAUDIO_FORMAT_PCM_I16`, `AAUDIO_FORMAT_PCM_FLOAT`, `AAUDIO_FORMAT_IEC61937`, `AAUDIO_FORMAT_PCM_I24_PACKED`, `AAUDIO_FORMAT_PCM_I32` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
+| `UserId` | `INT32_MIN` to `INT32_MAX` | Value obtained from getuid() |
+| `ProcessId` | `INT32_MIN` to `INT32_MAX` | Value obtained from getpid() |
+| `InService` | `bool` | Value obtained from FuzzedDataProvider |
+| `DeviceId` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
+| `SampleRate` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
+| `ChannelMask` | `AAUDIO_UNSPECIFIED`, `AAUDIO_CHANNEL_INDEX_MASK_1`, `AAUDIO_CHANNEL_INDEX_MASK_2`, `AAUDIO_CHANNEL_INDEX_MASK_3`, `AAUDIO_CHANNEL_INDEX_MASK_4`, `AAUDIO_CHANNEL_INDEX_MASK_5`, `AAUDIO_CHANNEL_INDEX_MASK_6`, `AAUDIO_CHANNEL_INDEX_MASK_7`, `AAUDIO_CHANNEL_INDEX_MASK_8`, `AAUDIO_CHANNEL_INDEX_MASK_9`, `AAUDIO_CHANNEL_INDEX_MASK_10`, `AAUDIO_CHANNEL_INDEX_MASK_11`, `AAUDIO_CHANNEL_INDEX_MASK_12`, `AAUDIO_CHANNEL_INDEX_MASK_13`, `AAUDIO_CHANNEL_INDEX_MASK_14`, `AAUDIO_CHANNEL_INDEX_MASK_15`, `AAUDIO_CHANNEL_INDEX_MASK_16`, `AAUDIO_CHANNEL_INDEX_MASK_17`, `AAUDIO_CHANNEL_INDEX_MASK_18`, `AAUDIO_CHANNEL_INDEX_MASK_19`, `AAUDIO_CHANNEL_INDEX_MASK_20`, `AAUDIO_CHANNEL_INDEX_MASK_21`, `AAUDIO_CHANNEL_INDEX_MASK_22`, `AAUDIO_CHANNEL_INDEX_MASK_23`, `AAUDIO_CHANNEL_INDEX_MASK_24`, `AAUDIO_CHANNEL_MONO`, `AAUDIO_CHANNEL_STEREO`, `AAUDIO_CHANNEL_FRONT_BACK`, `AAUDIO_CHANNEL_2POINT0POINT2`, `AAUDIO_CHANNEL_2POINT1POINT2`, `AAUDIO_CHANNEL_3POINT0POINT2`, `AAUDIO_CHANNEL_3POINT1POINT2`, `AAUDIO_CHANNEL_5POINT1`, `AAUDIO_CHANNEL_MONO`, `AAUDIO_CHANNEL_STEREO`, `AAUDIO_CHANNEL_2POINT1`, `AAUDIO_CHANNEL_TRI`, `AAUDIO_CHANNEL_TRI_BACK`, `AAUDIO_CHANNEL_3POINT1`, `AAUDIO_CHANNEL_2POINT0POINT2`, `AAUDIO_CHANNEL_2POINT1POINT2`, `AAUDIO_CHANNEL_3POINT0POINT2`, `AAUDIO_CHANNEL_3POINT1POINT2`, `AAUDIO_CHANNEL_QUAD`, `AAUDIO_CHANNEL_QUAD_SIDE`, `AAUDIO_CHANNEL_SURROUND`, `AAUDIO_CHANNEL_PENTA`, `AAUDIO_CHANNEL_5POINT1`, `AAUDIO_CHANNEL_5POINT1_SIDE`, `AAUDIO_CHANNEL_5POINT1POINT2`, `AAUDIO_CHANNEL_5POINT1POINT4`, `AAUDIO_CHANNEL_6POINT1`, `AAUDIO_CHANNEL_7POINT1`, `AAUDIO_CHANNEL_7POINT1POINT2`, `AAUDIO_CHANNEL_7POINT1POINT4`, `AAUDIO_CHANNEL_9POINT1POINT4`, `AAUDIO_CHANNEL_9POINT1POINT6` | Value obtained from FuzzedDataProvider |
+| `Direction` | `AAUDIO_DIRECTION_OUTPUT`, `AAUDIO_DIRECTION_INPUT` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
+| `SharingMode` | `AAUDIO_SHARING_MODE_EXCLUSIVE`, `AAUDIO_SHARING_MODE_SHARED` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
+| `Usage` | `AAUDIO_USAGE_MEDIA`, `AAUDIO_USAGE_VOICE_COMMUNICATION`, `AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING`, `AAUDIO_USAGE_ALARM`, `AAUDIO_USAGE_NOTIFICATION`, `AAUDIO_USAGE_NOTIFICATION_RINGTONE`, `AAUDIO_USAGE_NOTIFICATION_EVENT`, `AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY`, `AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE`, `AAUDIO_USAGE_ASSISTANCE_SONIFICATION`, `AAUDIO_USAGE_GAME`, `AAUDIO_USAGE_ASSISTANT`, `AAUDIO_SYSTEM_USAGE_EMERGENCY`, `AAUDIO_SYSTEM_USAGE_SAFETY`, `AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS`, `AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
+| `ContentType` | `AAUDIO_CONTENT_TYPE_SPEECH`, `AAUDIO_CONTENT_TYPE_MUSIC`, `AAUDIO_CONTENT_TYPE_MOVIE`, `AAUDIO_CONTENT_TYPE_SONIFICATION` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
+| `InputPreset` | `AAUDIO_INPUT_PRESET_GENERIC`, `AAUDIO_INPUT_PRESET_CAMCORDER`, `AAUDIO_INPUT_PRESET_VOICE_RECOGNITION`, `AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION`, `AAUDIO_INPUT_PRESET_UNPROCESSED`, `AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
+| `BufferCapacity` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
+| `HardwareSampleRate` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
+| `HardwareSamplesPerFrame` | `INT32_MIN` to `INT32_MAX` | Value obtained from FuzzedDataProvider |
+| `HardwareFormat` | `AAUDIO_FORMAT_UNSPECIFIED`, `AAUDIO_FORMAT_PCM_I16`, `AAUDIO_FORMAT_PCM_FLOAT`, `AAUDIO_FORMAT_IEC61937`, `AAUDIO_FORMAT_PCM_I24_PACKED`, `AAUDIO_FORMAT_PCM_I32` | Value chosen from valid values by obtaining index from FuzzedDataProvider |
This also ensures that the plugin is always deterministic for any given input.
diff --git a/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp b/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
index 5e48955..6dc6eff 100644
--- a/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
+++ b/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
@@ -34,6 +34,9 @@
AAUDIO_FORMAT_UNSPECIFIED,
AAUDIO_FORMAT_PCM_I16,
AAUDIO_FORMAT_PCM_FLOAT,
+ AAUDIO_FORMAT_PCM_I24_PACKED,
+ AAUDIO_FORMAT_PCM_I32,
+ AAUDIO_FORMAT_IEC61937
};
aaudio_usage_t kAAudioUsages[] = {
@@ -400,6 +403,13 @@
request.getConfiguration().setBufferCapacity(fdp.ConsumeIntegral<int32_t>());
+ request.getConfiguration().setHardwareSampleRate(fdp.ConsumeIntegral<int32_t>());
+ request.getConfiguration().setHardwareSamplesPerFrame(fdp.ConsumeIntegral<int32_t>());
+ request.getConfiguration().setHardwareFormat((audio_format_t)(
+ fdp.ConsumeBool()
+ ? fdp.ConsumeIntegral<int32_t>()
+ : kAAudioFormats[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioFormats - 1)]));
+
aaudio_handle_t stream = mClient->openStream(request, configurationOutput);
if (stream < 0) {
// invalid request, stream not opened.