Merge "Fix the error with EffectProxy open"
diff --git a/apex/TEST_MAPPING b/apex/TEST_MAPPING
index 4b7c019..bb4f089 100644
--- a/apex/TEST_MAPPING
+++ b/apex/TEST_MAPPING
@@ -7,16 +7,16 @@
"presubmit": [
// The following tests validate codec and drm path.
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
]
}
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
index b2d4d6e..a9b4b2a 100644
--- a/drm/TEST_MAPPING
+++ b/drm/TEST_MAPPING
@@ -2,16 +2,16 @@
"presubmit": [
// The following tests validate codec and drm path.
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
]
}
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
index bc004c8..ce4d730 100644
--- a/drm/libmediadrm/DrmMetricsLogger.cpp
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -41,49 +41,59 @@
DrmMetricsLogger::~DrmMetricsLogger() {}
-int MediaErrorToJavaError(status_t err) {
+int MediaErrorToEnum(status_t err) {
+#define ERROR_BAD_VALUE (BAD_VALUE)
+#define ERROR_DEAD_OBJECT (DEAD_OBJECT)
#define STATUS_CASE(status) \
- case status: \
- return J##status
+ case ERROR_##status: \
+ return ENUM_##status
switch (err) {
- STATUS_CASE(ERROR_DRM_UNKNOWN);
- STATUS_CASE(ERROR_DRM_NO_LICENSE);
- STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
- STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
- STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
- STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
- STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
- STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
- STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
- STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
- STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
- STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
- STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
- STATUS_CASE(ERROR_DRM_GENERIC_OEM);
- STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
- STATUS_CASE(ERROR_DRM_INIT_DATA);
- STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
- STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
- STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
- STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
- STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
- STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
- STATUS_CASE(ERROR_DRM_LICENSE_STATE);
- STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
- STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
- STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
- STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
- STATUS_CASE(ERROR_DRM_PROVISIONING_REQUEST_REJECTED);
- STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
- STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
- STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
- STATUS_CASE(ERROR_DRM_STORAGE_READ);
- STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
- STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
+ STATUS_CASE(DRM_UNKNOWN);
+ STATUS_CASE(DRM_NO_LICENSE);
+ STATUS_CASE(DRM_LICENSE_EXPIRED);
+ STATUS_CASE(DRM_RESOURCE_BUSY);
+ STATUS_CASE(DRM_INSUFFICIENT_OUTPUT_PROTECTION);
+ STATUS_CASE(DRM_SESSION_NOT_OPENED);
+ STATUS_CASE(DRM_CANNOT_HANDLE);
+ STATUS_CASE(DRM_INSUFFICIENT_SECURITY);
+ STATUS_CASE(DRM_FRAME_TOO_LARGE);
+ STATUS_CASE(DRM_SESSION_LOST_STATE);
+ STATUS_CASE(DRM_CERTIFICATE_MALFORMED);
+ STATUS_CASE(DRM_CERTIFICATE_MISSING);
+ STATUS_CASE(DRM_CRYPTO_LIBRARY);
+ STATUS_CASE(DRM_GENERIC_OEM);
+ STATUS_CASE(DRM_GENERIC_PLUGIN);
+ STATUS_CASE(DRM_INIT_DATA);
+ STATUS_CASE(DRM_KEY_NOT_LOADED);
+ STATUS_CASE(DRM_LICENSE_PARSE);
+ STATUS_CASE(DRM_LICENSE_POLICY);
+ STATUS_CASE(DRM_LICENSE_RELEASE);
+ STATUS_CASE(DRM_LICENSE_REQUEST_REJECTED);
+ STATUS_CASE(DRM_LICENSE_RESTORE);
+ STATUS_CASE(DRM_LICENSE_STATE);
+ STATUS_CASE(DRM_MEDIA_FRAMEWORK);
+ STATUS_CASE(DRM_PROVISIONING_CERTIFICATE);
+ STATUS_CASE(DRM_PROVISIONING_CONFIG);
+ STATUS_CASE(DRM_PROVISIONING_PARSE);
+ STATUS_CASE(DRM_PROVISIONING_REQUEST_REJECTED);
+ STATUS_CASE(DRM_PROVISIONING_RETRY);
+ STATUS_CASE(DRM_RESOURCE_CONTENTION);
+ STATUS_CASE(DRM_SECURE_STOP_RELEASE);
+ STATUS_CASE(DRM_STORAGE_READ);
+ STATUS_CASE(DRM_STORAGE_WRITE);
+ STATUS_CASE(DRM_ZERO_SUBSAMPLES);
+ STATUS_CASE(DRM_INVALID_STATE);
+ STATUS_CASE(BAD_VALUE);
+ STATUS_CASE(DRM_NOT_PROVISIONED);
+ STATUS_CASE(DRM_DEVICE_REVOKED);
+ STATUS_CASE(DRM_DECRYPT);
+ STATUS_CASE(DEAD_OBJECT);
+#undef ERROR_BAD_VALUE
+#undef ERROR_DEAD_OBJECT
#undef STATUS_CASE
}
- return static_cast<int>(err);
+ return ENUM_DRM_UNKNOWN;
}
int DrmPluginSecurityLevelToJavaSecurityLevel(DrmPlugin::SecurityLevel securityLevel) {
@@ -187,12 +197,12 @@
DrmStatus DrmMetricsLogger::closeSession(Vector<uint8_t> const& sessionId) {
std::vector<uint8_t> sid = toStdVec(sessionId);
- {
+ DrmStatus status = mImpl->closeSession(sessionId);
+ if (status == OK) {
const std::lock_guard<std::mutex> lock(mSessionMapMutex);
mSessionMap.erase(sid);
- }
- DrmStatus status = mImpl->closeSession(sessionId);
- if (status != OK) {
+ } else {
+ // TODO(b/275729711): reclaim sessions that failed to close
reportMediaDrmErrored(status, __func__, sid);
}
return status;
@@ -582,7 +592,7 @@
}
}
mediametrics_setCString(handle, "api", api);
- mediametrics_setInt32(handle, "error_code", MediaErrorToJavaError(error_code));
+ mediametrics_setInt32(handle, "error_code", MediaErrorToEnum(error_code));
mediametrics_setInt32(handle, "cdm_err", error_code.getCdmErr());
mediametrics_setInt32(handle, "oem_err", error_code.getOemErr());
mediametrics_setInt32(handle, "error_context", error_code.getContext());
diff --git a/drm/libmediadrm/TEST_MAPPING b/drm/libmediadrm/TEST_MAPPING
index bc15879..8d7be22 100644
--- a/drm/libmediadrm/TEST_MAPPING
+++ b/drm/libmediadrm/TEST_MAPPING
@@ -1,19 +1,19 @@
{
"presubmit": [
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.MediaDrmTest"
+ "include-filter": "com.google.android.media.wvts.MediaDrmTest"
},
{
- "include-filter": "com.google.android.media.gts.WidevineDashPolicyTests"
+ "include-filter": "com.google.android.media.wvts.WidevineDashPolicyTests"
}
]
}
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
index 7666f04..e72f7f7 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
@@ -25,41 +25,49 @@
namespace android {
+// Keep enums in sync with frameworks/proto_logging/stats/enums/media/drm/enums.proto
+
enum {
- JERROR_DRM_UNKNOWN = 0,
- JERROR_DRM_NO_LICENSE = 1,
- JERROR_DRM_LICENSE_EXPIRED = 2,
- JERROR_DRM_RESOURCE_BUSY = 3,
- JERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
- JERROR_DRM_SESSION_NOT_OPENED = 5,
- JERROR_DRM_CANNOT_HANDLE = 6,
- JERROR_DRM_INSUFFICIENT_SECURITY = 7,
- JERROR_DRM_FRAME_TOO_LARGE = 8,
- JERROR_DRM_SESSION_LOST_STATE = 9,
- JERROR_DRM_CERTIFICATE_MALFORMED = 10,
- JERROR_DRM_CERTIFICATE_MISSING = 11,
- JERROR_DRM_CRYPTO_LIBRARY = 12,
- JERROR_DRM_GENERIC_OEM = 13,
- JERROR_DRM_GENERIC_PLUGIN = 14,
- JERROR_DRM_INIT_DATA = 15,
- JERROR_DRM_KEY_NOT_LOADED = 16,
- JERROR_DRM_LICENSE_PARSE = 17,
- JERROR_DRM_LICENSE_POLICY = 18,
- JERROR_DRM_LICENSE_RELEASE = 19,
- JERROR_DRM_LICENSE_REQUEST_REJECTED = 20,
- JERROR_DRM_LICENSE_RESTORE = 21,
- JERROR_DRM_LICENSE_STATE = 22,
- JERROR_DRM_MEDIA_FRAMEWORK = 23,
- JERROR_DRM_PROVISIONING_CERTIFICATE = 24,
- JERROR_DRM_PROVISIONING_CONFIG = 25,
- JERROR_DRM_PROVISIONING_PARSE = 26,
- JERROR_DRM_PROVISIONING_REQUEST_REJECTED = 27,
- JERROR_DRM_PROVISIONING_RETRY = 28,
- JERROR_DRM_RESOURCE_CONTENTION = 29,
- JERROR_DRM_SECURE_STOP_RELEASE = 30,
- JERROR_DRM_STORAGE_READ = 31,
- JERROR_DRM_STORAGE_WRITE = 32,
- JERROR_DRM_ZERO_SUBSAMPLES = 33,
+ ENUM_DRM_UNKNOWN = 0,
+ ENUM_DRM_NO_LICENSE = 1,
+ ENUM_DRM_LICENSE_EXPIRED = 2,
+ ENUM_DRM_RESOURCE_BUSY = 3,
+ ENUM_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
+ ENUM_DRM_SESSION_NOT_OPENED = 5,
+ ENUM_DRM_CANNOT_HANDLE = 6,
+ ENUM_DRM_INSUFFICIENT_SECURITY = 7,
+ ENUM_DRM_FRAME_TOO_LARGE = 8,
+ ENUM_DRM_SESSION_LOST_STATE = 9,
+ ENUM_DRM_CERTIFICATE_MALFORMED = 10,
+ ENUM_DRM_CERTIFICATE_MISSING = 11,
+ ENUM_DRM_CRYPTO_LIBRARY = 12,
+ ENUM_DRM_GENERIC_OEM = 13,
+ ENUM_DRM_GENERIC_PLUGIN = 14,
+ ENUM_DRM_INIT_DATA = 15,
+ ENUM_DRM_KEY_NOT_LOADED = 16,
+ ENUM_DRM_LICENSE_PARSE = 17,
+ ENUM_DRM_LICENSE_POLICY = 18,
+ ENUM_DRM_LICENSE_RELEASE = 19,
+ ENUM_DRM_LICENSE_REQUEST_REJECTED = 20,
+ ENUM_DRM_LICENSE_RESTORE = 21,
+ ENUM_DRM_LICENSE_STATE = 22,
+ ENUM_DRM_MEDIA_FRAMEWORK = 23,
+ ENUM_DRM_PROVISIONING_CERTIFICATE = 24,
+ ENUM_DRM_PROVISIONING_CONFIG = 25,
+ ENUM_DRM_PROVISIONING_PARSE = 26,
+ ENUM_DRM_PROVISIONING_REQUEST_REJECTED = 27,
+ ENUM_DRM_PROVISIONING_RETRY = 28,
+ ENUM_DRM_RESOURCE_CONTENTION = 29,
+ ENUM_DRM_SECURE_STOP_RELEASE = 30,
+ ENUM_DRM_STORAGE_READ = 31,
+ ENUM_DRM_STORAGE_WRITE = 32,
+ ENUM_DRM_ZERO_SUBSAMPLES = 33,
+ ENUM_DRM_INVALID_STATE = 34,
+ ENUM_BAD_VALUE = 35,
+ ENUM_DRM_NOT_PROVISIONED = 36,
+ ENUM_DRM_DEVICE_REVOKED = 37,
+ ENUM_DRM_DECRYPT = 38,
+ ENUM_DEAD_OBJECT = 39,
};
enum {
diff --git a/include/drm/TEST_MAPPING b/include/drm/TEST_MAPPING
index 74fa50d..8595f12 100644
--- a/include/drm/TEST_MAPPING
+++ b/include/drm/TEST_MAPPING
@@ -1,16 +1,16 @@
{
"presubmit": [
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
]
}
diff --git a/include/media/Interpolator.h b/include/media/Interpolator.h
index 71e7604..0ee8779 100644
--- a/include/media/Interpolator.h
+++ b/include/media/Interpolator.h
@@ -122,7 +122,7 @@
// monotonic computation.
// we use lazy computation here - if we precompute in
// a single pass, duplicate secant computations may be avoided.
- S sec, sec0, sec1;
+ S sec{}, sec0{}, sec1{}; // initialization not needed, used for clang-tidy
if (!catmullRom || monotonic) {
sec = (high->second - low->second) / interval;
sec0 = low2 != this->end()
@@ -269,7 +269,7 @@
// Note: We don't need to check size is within some bounds as
// the Parcel read will fail if size is incorrectly specified too large.
- float lastx;
+ float lastx = 0.f; // initialization not needed, used for clang tidy
for (uint32_t i = 0; i < size; ++i) {
float x = config.xy[i * 2];
float y = config.xy[i * 2 + 1];
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 9aa896c..87256c8 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -21,16 +21,16 @@
],
"presubmit": [
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
],
"file_patterns": ["(?i)drm|crypto"]
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 8c2b940..0cfd128 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <stdio.h>
+
#include <algorithm>
#include <map>
#include <utility>
@@ -570,7 +572,6 @@
GET_DEVICE_DESC_CONNECTION(BT_LE));
return pairs;
}();
-#undef GET_DEVICE_DESC_CONNECTION
return pairs;
}
@@ -998,55 +999,161 @@
}
}
+AudioDeviceAddress::Tag suggestDeviceAddressTag(const AudioDeviceDescription& description) {
+ using Tag = AudioDeviceAddress::Tag;
+ if (std::string connection = description.connection;
+ connection == GET_DEVICE_DESC_CONNECTION(BT_A2DP) ||
+ // Note: BT LE Broadcast uses a "group id".
+ (description.type != AudioDeviceType::OUT_BROADCAST &&
+ connection == GET_DEVICE_DESC_CONNECTION(BT_LE)) ||
+ connection == GET_DEVICE_DESC_CONNECTION(BT_SCO) ||
+ connection == GET_DEVICE_DESC_CONNECTION(WIRELESS)) {
+ return Tag::mac;
+ } else if (connection == GET_DEVICE_DESC_CONNECTION(IP_V4)) {
+ return Tag::ipv4;
+ } else if (connection == GET_DEVICE_DESC_CONNECTION(USB)) {
+ return Tag::alsa;
+ }
+ return Tag::id;
+}
+
::android::status_t aidl2legacy_AudioDevice_audio_device(
const AudioDevice& aidl,
audio_devices_t* legacyType, char* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- return aidl2legacy_string(
- aidl.address.get<AudioDeviceAddress::id>(),
- legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+ std::string stringAddress;
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl, legacyType, &stringAddress));
+ return aidl2legacy_string(stringAddress, legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
}
::android::status_t aidl2legacy_AudioDevice_audio_device(
const AudioDevice& aidl,
audio_devices_t* legacyType, String8* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
- aidl.address.get<AudioDeviceAddress::id>()));
+ std::string stringAddress;
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl, legacyType, &stringAddress));
+ *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(stringAddress));
return OK;
}
::android::status_t aidl2legacy_AudioDevice_audio_device(
const AudioDevice& aidl,
audio_devices_t* legacyType, std::string* legacyAddress) {
+ using Tag = AudioDeviceAddress::Tag;
*legacyType = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
+ char addressBuffer[AUDIO_DEVICE_MAX_ADDRESS_LEN]{};
+ // 'aidl.address' can be empty even when the connection type is not.
+ // This happens for device ports that act as "blueprints". In this case
+ // we pass an empty string using the 'id' variant.
+ switch (aidl.address.getTag()) {
+ case Tag::mac: {
+ const std::vector<uint8_t>& mac = aidl.address.get<AudioDeviceAddress::mac>();
+ if (mac.size() != 6) return BAD_VALUE;
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ } break;
+ case Tag::ipv4: {
+ const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>();
+ if (ipv4.size() != 4) return BAD_VALUE;
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%u.%u.%u.%u",
+ ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
+ } break;
+ case Tag::ipv6: {
+ const std::vector<int32_t>& ipv6 = aidl.address.get<AudioDeviceAddress::ipv6>();
+ if (ipv6.size() != 8) return BAD_VALUE;
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN,
+ "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
+ ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7]);
+ } break;
+ case Tag::alsa: {
+ const std::vector<int32_t>& alsa = aidl.address.get<AudioDeviceAddress::alsa>();
+ if (alsa.size() != 2) return BAD_VALUE;
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "card=%d;device=%d",
+ alsa[0], alsa[1]);
+ } break;
+ case Tag::id: {
+ RETURN_STATUS_IF_ERROR(aidl2legacy_string(aidl.address.get<AudioDeviceAddress::id>(),
+ addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+ } break;
+ }
+ *legacyAddress = addressBuffer;
return OK;
}
ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
audio_devices_t legacyType, const char* legacyAddress) {
- AudioDevice aidl;
- aidl.type = VALUE_OR_RETURN(
- legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
- const std::string aidl_id = VALUE_OR_RETURN(
+ const std::string stringAddress = VALUE_OR_RETURN(
legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
- aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
- return aidl;
+ return legacy2aidl_audio_device_AudioDevice(legacyType, stringAddress);
}
ConversionResult<AudioDevice>
legacy2aidl_audio_device_AudioDevice(
audio_devices_t legacyType, const String8& legacyAddress) {
+ const std::string stringAddress = VALUE_OR_RETURN(legacy2aidl_String8_string(legacyAddress));
+ return legacy2aidl_audio_device_AudioDevice(legacyType, stringAddress);
+}
+
+ConversionResult<AudioDevice>
+legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const std::string& legacyAddress) {
+ using Tag = AudioDeviceAddress::Tag;
AudioDevice aidl;
aidl.type = VALUE_OR_RETURN(
legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
- const std::string aidl_id = VALUE_OR_RETURN(
- legacy2aidl_String8_string(legacyAddress));
- aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+ // 'legacyAddress' can be empty even when the connection type is not.
+ // This happens for device ports that act as "blueprints". In this case
+ // we pass an empty string using the 'id' variant.
+ if (!legacyAddress.empty()) {
+ switch (suggestDeviceAddressTag(aidl.type)) {
+ case Tag::mac: {
+ std::vector<uint8_t> mac(6);
+ int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
+ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+ if (status != mac.size()) {
+ ALOGE("%s: malformed MAC address: \"%s\"", __func__, legacyAddress.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::mac>(std::move(mac));
+ } break;
+ case Tag::ipv4: {
+ std::vector<uint8_t> ipv4(4);
+ int status = sscanf(legacyAddress.c_str(), "%hhu.%hhu.%hhu.%hhu",
+ &ipv4[0], &ipv4[1], &ipv4[2], &ipv4[3]);
+ if (status != ipv4.size()) {
+ ALOGE("%s: malformed IPv4 address: \"%s\"", __func__, legacyAddress.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::ipv4>(std::move(ipv4));
+ } break;
+ case Tag::ipv6: {
+ std::vector<int32_t> ipv6(8);
+ int status = sscanf(legacyAddress.c_str(), "%X:%X:%X:%X:%X:%X:%X:%X",
+ &ipv6[0], &ipv6[1], &ipv6[2], &ipv6[3], &ipv6[4], &ipv6[5], &ipv6[6],
+ &ipv6[7]);
+ if (status != ipv6.size()) {
+ ALOGE("%s: malformed IPv6 address: \"%s\"", __func__, legacyAddress.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::ipv6>(std::move(ipv6));
+ } break;
+ case Tag::alsa: {
+ std::vector<int32_t> alsa(2);
+ int status = sscanf(legacyAddress.c_str(), "card=%d;device=%d", &alsa[0], &alsa[1]);
+ if (status != alsa.size()) {
+ ALOGE("%s: malformed ALSA address: \"%s\"", __func__, legacyAddress.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::alsa>(std::move(alsa));
+ } break;
+ case Tag::id: {
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(legacyAddress);
+ } break;
+ }
+ } else {
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(legacyAddress);
+ }
return aidl;
}
@@ -3009,6 +3116,8 @@
} // namespace android
+#undef GET_DEVICE_DESC_CONNECTION
+
#if defined(BACKEND_NDK)
} // aidl
#endif
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index 9100892..ec1f75c 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -190,6 +190,9 @@
ConversionResult<media::audio::common::AudioDeviceDescription>
legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
+media::audio::common::AudioDeviceAddress::Tag suggestDeviceAddressTag(
+ const media::audio::common::AudioDeviceDescription& description);
+
::android::status_t aidl2legacy_AudioDevice_audio_device(
const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
char* legacyAddress);
@@ -204,6 +207,8 @@
audio_devices_t legacyType, const char* legacyAddress);
ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
audio_devices_t legacyType, const ::android::String8& legacyAddress);
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const std::string& legacyAddress);
ConversionResult<audio_extra_audio_descriptor>
aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index ed91e2c..b179cbb 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -58,15 +58,15 @@
ConversionResult<To> convertIntegral(From from) {
// Special handling is required for signed / vs. unsigned comparisons, since otherwise we may
// have the signed converted to unsigned and produce wrong results.
- if (std::is_signed_v<From> && !std::is_signed_v<To>) {
+ if constexpr (std::is_signed_v<From> && !std::is_signed_v<To>) {
if (from < 0 || from > std::numeric_limits<To>::max()) {
return ::android::base::unexpected(::android::BAD_VALUE);
}
- } else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
+ } else if constexpr (std::is_signed_v<To> && !std::is_signed_v<From>) {
if (from > std::numeric_limits<To>::max()) {
return ::android::base::unexpected(::android::BAD_VALUE);
}
- } else {
+ } else /* constexpr */ {
if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
return ::android::base::unexpected(::android::BAD_VALUE);
}
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index dfdd84d..2dea84c 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "C2Store"
-#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#include <utils/Log.h>
#include <C2AllocatorBlob.h>
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 6ffbdc4..7c7b65b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -250,6 +250,12 @@
return af->setMode(mode);
}
+status_t AudioSystem::setSimulateDeviceConnections(bool enabled) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setSimulateDeviceConnections(enabled);
+}
+
status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
@@ -1544,6 +1550,15 @@
return OK;
}
+status_t AudioSystem::listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* result) {
+ if (result == nullptr) return BAD_VALUE;
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aps->listDeclaredDevicePorts(role, result)));
+ return OK;
+}
+
status_t AudioSystem::getAudioPort(struct audio_port_v7* port) {
if (port == nullptr) {
return BAD_VALUE;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index ff4b071..cb1a67d 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2484,11 +2484,22 @@
timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC;
timeout.tv_nsec = 0;
+ // Use timestamp progress to safeguard we don't falsely time out.
+ AudioTimestamp timestamp{};
+ const bool isTimestampValid = getTimestamp(timestamp) == OK;
+ const auto frameCount = isTimestampValid ? timestamp.mPosition : 0;
+
status_t status = proxy->waitStreamEndDone(&timeout);
switch (status) {
+ case TIMED_OUT:
+ if (isTimestampValid
+ && getTimestamp(timestamp) == OK && frameCount != timestamp.mPosition) {
+ ALOGD("%s: waitStreamEndDone retrying", __func__);
+ break; // we retry again (and recheck possible state change).
+ }
+ [[fallthrough]];
case NO_ERROR:
case DEAD_OBJECT:
- case TIMED_OUT:
if (status != DEAD_OBJECT) {
// for DEAD_OBJECT, we do not send a EVENT_STREAM_END after stop();
// instead, the application should handle the EVENT_NEW_IAUDIOTRACK.
@@ -2506,6 +2517,7 @@
}
}
if (waitStreamEnd && status != DEAD_OBJECT) {
+ ALOGV("%s: waitStreamEndDone complete", __func__);
return NS_INACTIVE;
}
break;
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index a005ab4..7bf7b98 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -809,6 +809,10 @@
return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, connected));
}
+status_t AudioFlingerClientAdapter::setSimulateDeviceConnections(bool enabled) {
+ return statusTFromBinderStatus(mDelegate->setSimulateDeviceConnections(enabled));
+}
+
status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) {
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
@@ -1355,6 +1359,10 @@
return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, connected));
}
+Status AudioFlingerServerAdapter::setSimulateDeviceConnections(bool enabled) {
+ return Status::fromStatusT(mDelegate->setSimulateDeviceConnections(enabled));
+}
+
Status AudioFlingerServerAdapter::setRequestedLatencyMode(
int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 7c44c74..e676d89 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -229,6 +229,9 @@
void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
+ // Used for tests only. Requires AIDL HAL to work.
+ void setSimulateDeviceConnections(boolean enabled);
+
/**
* Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
* This can be used when some use case on a given mixer/stream can only be enabled
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index ed7e243..fb87042 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -202,7 +202,9 @@
in AudioAttributesInternal attributes);
/**
- * List available audio ports and their attributes. Returns the generation.
+ * List currently attached audio ports and their attributes. Returns the generation.
+ * The generation is incremented each time when anything changes in the ports
+ * configuration.
*
* On input, count represents the maximum length of the returned array.
* On output, count is the total number of elements, which may be larger than the array size.
@@ -214,6 +216,13 @@
inout Int count,
out AudioPortFw[] ports);
+ /**
+ * List all device ports declared in the configuration (including currently detached ones)
+ * 'role' can be 'NONE' to get both input and output devices,
+ * 'SINK' for output devices, and 'SOURCE' for input devices.
+ */
+ AudioPortFw[] listDeclaredDevicePorts(AudioPortRole role);
+
/** Get attributes for the audio port with the given id (AudioPort.hal.id field). */
AudioPortFw getAudioPort(int /* audio_port_handle_t */ portId);
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index b1feb60..6080314 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -80,5 +80,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libaudioflinger",
+ vector: "local_no_privileges_required",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 543ce00..3e3b79c 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -23,6 +23,7 @@
#include <vector>
#include <android/content/AttributionSourceState.h>
+#include <android/media/AudioPortFw.h>
#include <android/media/AudioVibratorInfo.h>
#include <android/media/BnAudioFlingerClient.h>
#include <android/media/BnAudioPolicyServiceClient.h>
@@ -121,6 +122,9 @@
// set audio mode in audio hardware
static status_t setMode(audio_mode_t mode);
+ // test API: switch HALs into the mode which simulates external device connections
+ static status_t setSimulateDeviceConnections(bool enabled);
+
// returns true in *state if tracks are active on the specified stream or have been active
// in the past inPastMs milliseconds
static status_t isStreamActive(audio_stream_type_t stream, bool *state, uint32_t inPastMs);
@@ -378,6 +382,9 @@
struct audio_port_v7 *ports,
unsigned int *generation);
+ static status_t listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* result);
+
/* Get attributes for a given audio port. On input, the port
* only needs the 'id' field to be filled in. */
static status_t getAudioPort(struct audio_port_v7 *port);
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 25b5414..b1491da 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -360,6 +360,8 @@
virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+ virtual status_t setSimulateDeviceConnections(bool enabled) = 0;
+
virtual status_t setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) = 0;
@@ -473,6 +475,7 @@
int32_t getAAudioMixerBurstCount() override;
int32_t getAAudioHardwareBurstMinUsec() override;
status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override;
+ status_t setSimulateDeviceConnections(bool enabled) override;
status_t setRequestedLatencyMode(audio_io_handle_t output,
audio_latency_mode_t mode) override;
status_t getSupportedLatencyModes(
@@ -569,6 +572,7 @@
GET_AAUDIO_MIXER_BURST_COUNT = media::BnAudioFlingerService::TRANSACTION_getAAudioMixerBurstCount,
GET_AAUDIO_HARDWARE_BURST_MIN_USEC = media::BnAudioFlingerService::TRANSACTION_getAAudioHardwareBurstMinUsec,
SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
+ SET_SIMULATE_DEVICE_CONNECTIONS = media::BnAudioFlingerService::TRANSACTION_setSimulateDeviceConnections,
SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
@@ -698,6 +702,7 @@
Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
+ Status setSimulateDeviceConnections(bool enabled) override;
Status setRequestedLatencyMode(
int output, media::audio::common::AudioLatencyMode mode) override;
Status getSupportedLatencyModes(int output,
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 2189521..1e8dcca 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -14,6 +14,12 @@
"-Wall",
"-Werror",
],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
sanitize: {
misc_undefined: [
"unsigned-integer-overflow",
@@ -22,37 +28,35 @@
},
}
-cc_test {
- name: "audio_aidl_conversion_tests",
+cc_defaults {
+ name: "audio_aidl_conversion_test_defaults",
defaults: [
"libaudioclient_tests_defaults",
"latest_android_media_audio_common_types_cpp_static",
],
- srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
- shared_libs: [
- "libbinder",
- "libcutils",
- "liblog",
- "libutils",
- ],
static_libs: [
- "libaudioclient_aidl_conversion",
- "libaudio_aidl_conversion_common_cpp",
"audioclient-types-aidl-cpp",
"av-types-aidl-cpp",
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudioclient_aidl_conversion",
"libstagefright_foundation",
],
}
cc_test {
+ name: "audio_aidl_conversion_tests",
+ defaults: [
+ "audio_aidl_conversion_test_defaults",
+ ],
+ srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
+}
+
+cc_test {
name: "audio_aidl_status_tests",
defaults: ["libaudioclient_tests_defaults"],
srcs: ["audio_aidl_status_tests.cpp"],
shared_libs: [
"libaudioclient_aidl_conversion",
- "libbinder",
- "libcutils",
- "libutils",
],
}
@@ -70,9 +74,6 @@
shared_libs: [
"framework-permission-aidl-cpp",
"libaudioclient",
- "libbinder",
- "libcutils",
- "libutils",
],
data: ["track_test_input_*.txt"],
}
@@ -89,35 +90,23 @@
"libmediametrics_headers",
],
shared_libs: [
- "libaudioclient",
- "libbinder",
- "libcutils",
- "libutils",
"framework-permission-aidl-cpp",
+ "libaudioclient",
],
data: ["record_test_input_*.txt"],
}
cc_defaults {
name: "libaudioclient_gtests_defaults",
- cflags: [
- "-Wall",
- "-Werror",
- ],
defaults: [
- "latest_android_media_audio_common_types_cpp_static",
+ "audio_aidl_conversion_test_defaults",
],
shared_libs: [
"capture_state_listener-aidl-cpp",
"framework-permission-aidl-cpp",
- "libaudioclient_aidl_conversion",
- "libaudio_aidl_conversion_common_cpp",
"libbase",
- "libbinder",
"libcgrouprc",
- "libcutils",
"libdl",
- "liblog",
"libmedia",
"libmediametrics",
"libmediautils",
@@ -125,8 +114,6 @@
"libnblog",
"libprocessgroup",
"libshmemcompat",
- "libstagefright_foundation",
- "libutils",
"libxml2",
"mediametricsservice-aidl-cpp",
"packagemanager_aidl-cpp",
@@ -148,7 +135,6 @@
],
data: ["bbb*.raw"],
test_config_template: "audio_test_template.xml",
- test_suites: ["device-tests"],
}
cc_test {
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index e2216a0..91ef7b3 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -15,6 +15,7 @@
*/
#include <iostream>
+#include <string>
#include <gtest/gtest.h>
@@ -32,6 +33,7 @@
using media::AudioPortType;
using media::audio::common::AudioChannelLayout;
using media::audio::common::AudioDevice;
+using media::audio::common::AudioDeviceAddress;
using media::audio::common::AudioDeviceDescription;
using media::audio::common::AudioDeviceType;
using media::audio::common::AudioEncapsulationMetadataType;
@@ -131,6 +133,14 @@
return make_AudioDeviceDescription(AudioDeviceType::IN_DEFAULT);
}
+AudioDeviceDescription make_ADD_MicIn() {
+ return make_AudioDeviceDescription(AudioDeviceType::IN_MICROPHONE);
+}
+
+AudioDeviceDescription make_ADD_RSubmixIn() {
+ return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX);
+}
+
AudioDeviceDescription make_ADD_DefaultOut() {
return make_AudioDeviceDescription(AudioDeviceType::OUT_DEFAULT);
}
@@ -145,6 +155,39 @@
AudioDeviceDescription::CONNECTION_BT_SCO());
}
+AudioDeviceDescription make_ADD_BtA2dpHeadphone() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADPHONE,
+ AudioDeviceDescription::CONNECTION_BT_A2DP());
+}
+
+AudioDeviceDescription make_ADD_BtLeHeadset() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_BT_LE());
+}
+
+AudioDeviceDescription make_ADD_BtLeBroadcast() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_BROADCAST,
+ AudioDeviceDescription::CONNECTION_BT_LE());
+}
+
+AudioDeviceDescription make_ADD_IpV4Device() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_DEVICE,
+ AudioDeviceDescription::CONNECTION_IP_V4());
+}
+
+AudioDeviceDescription make_ADD_UsbHeadset() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_USB());
+}
+
+AudioDevice make_AudioDevice(const AudioDeviceDescription& type,
+ const AudioDeviceAddress& address) {
+ AudioDevice result;
+ result.type = type;
+ result.address = address;
+ return result;
+}
+
AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
AudioFormatDescription result;
result.type = type;
@@ -390,6 +433,48 @@
make_ADD_DefaultOut(), make_ADD_WiredHeadset(),
make_ADD_BtScoHeadset()));
+class AudioDeviceRoundTripTest : public testing::TestWithParam<AudioDevice> {};
+TEST_P(AudioDeviceRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = GetParam();
+ audio_devices_t legacyType;
+ String8 legacyAddress;
+ status_t status = aidl2legacy_AudioDevice_audio_device(initial, &legacyType, &legacyAddress);
+ ASSERT_EQ(OK, status);
+ auto convBack = legacy2aidl_audio_device_AudioDevice(legacyType, legacyAddress);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(
+ AudioDeviceRoundTrip, AudioDeviceRoundTripTest,
+ testing::Values(
+ make_AudioDevice(make_ADD_MicIn(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("bottom")),
+ make_AudioDevice(make_ADD_RSubmixIn(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("1:2-in-3")),
+ // The case of a "blueprint" device port for an external device.
+ make_AudioDevice(make_ADD_BtScoHeadset(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("")),
+ make_AudioDevice(make_ADD_BtScoHeadset(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+ // Another "blueprint"
+ make_AudioDevice(make_ADD_BtA2dpHeadphone(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("")),
+ make_AudioDevice(make_ADD_BtA2dpHeadphone(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+ make_AudioDevice(make_ADD_BtLeHeadset(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+ make_AudioDevice(make_ADD_BtLeBroadcast(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("42")),
+ make_AudioDevice(make_ADD_IpV4Device(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::ipv4>(
+ std::vector<uint8_t>{192, 168, 0, 1})),
+ make_AudioDevice(make_ADD_UsbHeadset(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::alsa>(
+ std::vector<int32_t>{1, 2}))));
+
class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> {
};
TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index 682f43e..d43b669 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -18,12 +18,19 @@
#include <string.h>
+#include <set>
+
#include <gtest/gtest.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/IAudioFlinger.h>
#include <utils/Log.h>
#include "audio_test_utils.h"
+using android::media::audio::common::AudioDeviceAddress;
+using android::media::audio::common::AudioDeviceDescription;
+using android::media::audio::common::AudioDeviceType;
+using android::media::audio::common::AudioPortExt;
using namespace android;
void anyPatchContainsInputDevice(audio_port_handle_t deviceId, bool& res) {
@@ -579,3 +586,106 @@
EXPECT_EQ(NO_ERROR, AudioSystem::setUserIdDeviceAffinities(userId, outputDevices));
EXPECT_EQ(NO_ERROR, AudioSystem::removeUserIdDeviceAffinities(userId));
}
+
+namespace {
+
+class WithSimulatedDeviceConnections {
+ public:
+ WithSimulatedDeviceConnections()
+ : mIsSupported(AudioSystem::setSimulateDeviceConnections(true) == OK) {}
+ ~WithSimulatedDeviceConnections() {
+ if (mIsSupported) {
+ if (status_t status = AudioSystem::setSimulateDeviceConnections(false); status != OK) {
+ ALOGE("Error restoring device connections simulation state: %d", status);
+ }
+ }
+ }
+ bool isSupported() const { return mIsSupported; }
+
+ private:
+ const bool mIsSupported;
+};
+
+android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
+ const android::media::audio::common::AudioPort& port) {
+ static int nextId = 0;
+ using Tag = AudioDeviceAddress::Tag;
+ AudioDeviceAddress address;
+ switch (suggestDeviceAddressTag(port.ext.get<AudioPortExt::Tag::device>().device.type)) {
+ case Tag::id:
+ address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
+ break;
+ case Tag::mac:
+ address = AudioDeviceAddress::make<Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
+ break;
+ case Tag::ipv4:
+ address = AudioDeviceAddress::make<Tag::ipv4>(
+ std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
+ break;
+ case Tag::ipv6:
+ address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
+ 0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
+ break;
+ case Tag::alsa:
+ address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
+ break;
+ }
+ android::media::audio::common::AudioPort result = port;
+ result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
+ return result;
+}
+
+} // namespace
+
+TEST_F(AudioSystemTest, SetDeviceConnectedState) {
+ WithSimulatedDeviceConnections connSim;
+ if (!connSim.isSupported()) {
+ GTEST_SKIP() << "Simulation of external device connections not supported";
+ }
+ std::vector<media::AudioPortFw> ports;
+ ASSERT_EQ(OK, AudioSystem::listDeclaredDevicePorts(media::AudioPortRole::NONE, &ports));
+ if (ports.empty()) {
+ GTEST_SKIP() << "No ports returned by the audio system";
+ }
+ const std::set<AudioDeviceType> typesToUse{
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::IN_HEADSET,
+ AudioDeviceType::IN_MICROPHONE, AudioDeviceType::OUT_DEVICE,
+ AudioDeviceType::OUT_HEADPHONE, AudioDeviceType::OUT_HEADSET,
+ AudioDeviceType::OUT_HEARING_AID, AudioDeviceType::OUT_SPEAKER};
+ std::vector<media::AudioPortFw> externalDevicePorts;
+ for (const auto& port : ports) {
+ if (const auto& device = port.hal.ext.get<AudioPortExt::device>().device;
+ !device.type.connection.empty() && typesToUse.count(device.type.type)) {
+ externalDevicePorts.push_back(port);
+ }
+ }
+ if (externalDevicePorts.empty()) {
+ GTEST_SKIP() << "No ports for considered non-attached devices";
+ }
+ for (auto& port : externalDevicePorts) {
+ android::media::audio::common::AudioPort aidlPort = GenerateUniqueDeviceAddress(port.hal);
+ SCOPED_TRACE(aidlPort.toString());
+ audio_devices_t type;
+ char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+ status_t status = aidl2legacy_AudioDevice_audio_device(
+ aidlPort.ext.get<AudioPortExt::Tag::device>().device, &type, address);
+ ASSERT_EQ(OK, status);
+ audio_policy_dev_state_t deviceState = AudioSystem::getDeviceConnectionState(type, address);
+ EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
+ if (deviceState != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) continue;
+ // !!! Instead of the default format, use each format from 'ext.encodedFormats'
+ // !!! if they are not empty
+ status = AudioSystem::setDeviceConnectionState(AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ aidlPort, AUDIO_FORMAT_DEFAULT);
+ EXPECT_EQ(OK, status);
+ if (status != OK) continue;
+ deviceState = AudioSystem::getDeviceConnectionState(type, address);
+ EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, deviceState);
+ status = AudioSystem::setDeviceConnectionState(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ aidlPort, AUDIO_FORMAT_DEFAULT);
+ EXPECT_EQ(OK, status);
+ deviceState = AudioSystem::getDeviceConnectionState(type, address);
+ EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
+ }
+}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 8b88f24..3894cbf 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -23,6 +23,8 @@
#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
+#include <android/binder_enums.h>
+#include <binder/Enums.h>
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionUtil.h>
@@ -34,32 +36,42 @@
#include "StreamHalAidl.h"
using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioConfig;
using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioLatencyMode;
+using aidl::android::media::audio::common::AudioMMapPolicy;
+using aidl::android::media::audio::common::AudioMMapPolicyInfo;
+using aidl::android::media::audio::common::AudioMMapPolicyType;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioPortMixExt;
using aidl::android::media::audio::common::AudioPortMixExtUseCase;
-using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
using aidl::android::media::audio::common::AudioSource;
-using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::Float;
-using aidl::android::hardware::audio::common::getFrameSizeInBytes;
-using aidl::android::hardware::audio::common::isBitPositionFlagSet;
-using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
+using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
+using aidl::android::hardware::audio::common::isDefaultAudioFormat;
+using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
using aidl::android::hardware::audio::common::RecordTrackMetadata;
using aidl::android::hardware::audio::core::AudioPatch;
+using aidl::android::hardware::audio::core::AudioRoute;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::ITelephony;
+using aidl::android::hardware::audio::core::ModuleDebug;
using aidl::android::hardware::audio::core::StreamDescriptor;
namespace android {
@@ -84,6 +96,75 @@
portConfig->format = config.base.format;
}
+template<typename OutEnum, typename OutEnumRange, typename InEnum>
+ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
+ using InIntType = std::underlying_type_t<InEnum>;
+ static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
+
+ InIntType inEnumIndex = static_cast<InIntType>(e);
+ OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
+ if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
+ return ::android::base::unexpected(BAD_VALUE);
+ }
+ return outEnum;
+}
+
+template<typename NdkEnum, typename CppEnum>
+ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum e) {
+ return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), e);
+}
+
+template<typename CppEnum, typename NdkEnum>
+ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum e) {
+ return convertEnum<CppEnum>(::android::enum_range<CppEnum>(), e);
+}
+
+ConversionResult<android::media::audio::common::AudioDeviceAddress>
+ndk2cpp_AudioDeviceAddress(const AudioDeviceAddress& ndk) {
+ using CppTag = android::media::audio::common::AudioDeviceAddress::Tag;
+ using NdkTag = AudioDeviceAddress::Tag;
+
+ CppTag cppTag = VALUE_OR_RETURN(ndk2cpp_Enum<CppTag>(ndk.getTag()));
+
+ switch (cppTag) {
+ case CppTag::id:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::id>(
+ ndk.get<NdkTag::id>());
+ case CppTag::mac:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::mac>(
+ ndk.get<NdkTag::mac>());
+ case CppTag::ipv4:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv4>(
+ ndk.get<NdkTag::ipv4>());
+ case CppTag::ipv6:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv6>(
+ ndk.get<NdkTag::ipv6>());
+ case CppTag::alsa:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::alsa>(
+ ndk.get<NdkTag::alsa>());
+ }
+
+ return ::android::base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::audio::common::AudioDevice> ndk2cpp_AudioDevice(const AudioDevice& ndk) {
+ media::audio::common::AudioDevice cpp;
+ cpp.type.type = VALUE_OR_RETURN(
+ ndk2cpp_Enum<media::audio::common::AudioDeviceType>(ndk.type.type));
+ cpp.type.connection = ndk.type.connection;
+ cpp.address = VALUE_OR_RETURN(ndk2cpp_AudioDeviceAddress(ndk.address));
+ return cpp;
+}
+
+ConversionResult<media::audio::common::AudioMMapPolicyInfo>
+ndk2cpp_AudioMMapPolicyInfo(const AudioMMapPolicyInfo& ndk) {
+ media::audio::common::AudioMMapPolicyInfo cpp;
+ cpp.device = VALUE_OR_RETURN(ndk2cpp_AudioDevice(ndk.device));
+ cpp.mmapPolicy = VALUE_OR_RETURN(
+ ndk2cpp_Enum<media::audio::common::AudioMMapPolicy>(ndk.mmapPolicy));
+ return cpp;
+}
+
} // namespace
status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
@@ -116,6 +197,7 @@
}
ALOGI("%s: module %s default port ids: input %d, output %d",
__func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
+ RETURN_STATUS_IF_ERROR(updateRoutes());
std::vector<AudioPortConfig> portConfigs;
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
@@ -257,9 +339,9 @@
AudioPortConfig mixPortConfig;
Cleanups cleanups;
audio_config writableConfig = *config;
- int32_t nominalLatency;
+ AudioPatch aidlPatch;
RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
- &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
*size = aidlConfig.frameCount *
getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
// Do not disarm cleanups to release temporary port configs.
@@ -270,7 +352,11 @@
int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
AudioSource aidlSource, struct audio_config* config,
Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
- int32_t* nominalLatency) {
+ AudioPatch* aidlPatch) {
+ ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
+ this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
+ aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
+ aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
// Find / create AudioPortConfigs for the device port and the mix port,
// then find / create a patch between them, and open a stream on the mix port.
@@ -281,25 +367,23 @@
cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
}
RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
- mixPortConfig, &created));
+ std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
if (created) {
cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
}
setConfigFromPortConfig(aidlConfig, *mixPortConfig);
- AudioPatch patch;
if (isInput) {
RETURN_STATUS_IF_ERROR(findOrCreatePatch(
- {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
+ {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
} else {
RETURN_STATUS_IF_ERROR(findOrCreatePatch(
- {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
+ {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
}
if (created) {
- cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
+ cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
}
- *nominalLatency = patch.latenciesMs[0];
if (aidlConfig->frameCount <= 0) {
- aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
+ aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
}
*config = VALUE_OR_RETURN_STATUS(
::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
@@ -445,10 +529,10 @@
AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
AudioPortConfig mixPortConfig;
Cleanups cleanups;
- int32_t nominalLatency;
+ AudioPatch aidlPatch;
RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
- config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
args.portConfigId = mixPortConfig.id;
const bool isOffload = isBitPositionFlagSet(
@@ -472,8 +556,9 @@
__func__, ret.desc.toString().c_str());
return NO_INIT;
}
- *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
+ *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
std::move(ret.stream), this /*callbackBroker*/);
+ mStreams.insert(std::pair(*outStream, aidlPatch.id));
void* cbCookie = (*outStream).get();
{
std::lock_guard l(mLock);
@@ -510,9 +595,9 @@
::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
AudioPortConfig mixPortConfig;
Cleanups cleanups;
- int32_t nominalLatency;
+ AudioPatch aidlPatch;
RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
- config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
args.portConfigId = mixPortConfig.id;
RecordTrackMetadata aidlTrackMetadata{
@@ -532,8 +617,9 @@
__func__, ret.desc.toString().c_str());
return NO_INIT;
}
- *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
+ *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
std::move(ret.stream), this /*micInfoProvider*/);
+ mStreams.insert(std::pair(*inStream, aidlPatch.id));
cleanups.disarmAll();
return OK;
}
@@ -601,20 +687,41 @@
__func__, ::android::internal::ToString(aidlSources).c_str(),
::android::internal::ToString(aidlSinks).c_str());
auto fillPortConfigs = [&](
- const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
+ const std::vector<AudioPortConfig>& configs,
+ const std::set<int32_t>& destinationPortIds,
+ std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
for (const auto& s : configs) {
AudioPortConfig portConfig;
bool created = false;
- RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
+ s, destinationPortIds, &portConfig, &created));
if (created) {
cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
}
ids->push_back(portConfig.id);
+ if (portIds != nullptr) {
+ portIds->insert(portConfig.portId);
+ }
}
return OK;
};
- RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
- RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
+ // When looking up port configs, the destinationPortId is only used for mix ports.
+ // Thus, we process device port configs first, and look up the destination port ID from them.
+ bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
+ [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
+ const std::vector<AudioPortConfig>& devicePortConfigs =
+ sourceIsDevice ? aidlSources : aidlSinks;
+ std::vector<int32_t>* devicePortConfigIds =
+ sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
+ const std::vector<AudioPortConfig>& mixPortConfigs =
+ sourceIsDevice ? aidlSinks : aidlSources;
+ std::vector<int32_t>* mixPortConfigIds =
+ sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
+ std::set<int32_t> devicePortIds;
+ RETURN_STATUS_IF_ERROR(fillPortConfigs(
+ devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
+ RETURN_STATUS_IF_ERROR(fillPortConfigs(
+ mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
if (existingPatchIt != mPatches.end()) {
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mModule->setAudioPatch(aidlPatch, &aidlPatch)));
@@ -649,22 +756,68 @@
return OK;
}
-status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
- TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return INVALID_OPERATION;
-}
-
-status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
- TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return INVALID_OPERATION;
-}
-
-status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
+status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mModule) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (port == nullptr) {
+ return BAD_VALUE;
+ }
+ audio_port_v7 portV7;
+ audio_populate_audio_port_v7(port, &portV7);
+ RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
+ return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
+}
+
+status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ if (port == nullptr) {
+ return BAD_VALUE;
+ }
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
+ ::aidl::android::AudioPortDirection::INPUT;
+ auto aidlPort = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
+ if (aidlPort.ext.getTag() != AudioPortExt::device) {
+ ALOGE("%s: provided port is not a device port (module %s): %s",
+ __func__, mInstance.c_str(), aidlPort.toString().c_str());
+ return BAD_VALUE;
+ }
+ const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+ // It seems that we don't have to call HAL since all valid ports have been added either
+ // during initialization, or while handling connection of an external device.
+ auto portsIt = findPort(matchDevice);
+ if (portsIt == mPorts.end()) {
+ ALOGE("%s: device port for device %s is not found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ return BAD_VALUE;
+ }
+ const int32_t fwkId = aidlPort.id;
+ aidlPort = portsIt->second;
+ aidlPort.id = fwkId;
+ *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
+ aidlPort, isInput));
+ return OK;
+}
+
+status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ if (config == nullptr) {
+ return BAD_VALUE;
+ }
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+ config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
+ AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+ *config, isInput, 0 /*portId*/));
+ AudioPortConfig portConfig;
+ bool created = false;
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
+ requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
return OK;
}
@@ -732,23 +885,41 @@
}
status_t DeviceHalAidl::getMmapPolicyInfos(
- media::audio::common::AudioMMapPolicyType policyType __unused,
- std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
+ media::audio::common::AudioMMapPolicyType policyType,
+ std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
+ AudioMMapPolicyType mmapPolicyType =
+ VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
+
+ std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
+
+ if (status_t status = statusTFromBinderStatus(
+ mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
+ return status;
+ }
+
+ *policyInfos = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
+ mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
return OK;
}
int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ int32_t mixerBurstCount = 0;
+ if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
+ return mixerBurstCount;
+ }
+ return 0;
}
int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ int32_t hardwareBurstMinUsec = 0;
+ if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
+ return hardwareBurstMinUsec;
+ }
+ return 0;
}
error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
@@ -764,7 +935,7 @@
TIME_CHECK();
if (!mModule) return NO_INIT;
return mModule->dump(fd, Args(args).args(), args.size());
-};
+}
int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
TIME_CHECK();
@@ -772,6 +943,73 @@
return INVALID_OPERATION;
}
+status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ if (port == nullptr) {
+ return BAD_VALUE;
+ }
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
+ ::aidl::android::AudioPortDirection::INPUT;
+ AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
+ if (aidlPort.ext.getTag() != AudioPortExt::device) {
+ ALOGE("%s: provided port is not a device port (module %s): %s",
+ __func__, mInstance.c_str(), aidlPort.toString().c_str());
+ return BAD_VALUE;
+ }
+ if (connected) {
+ AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+ // Reset the device address to find the "template" port.
+ matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
+ auto portsIt = findPort(matchDevice);
+ if (portsIt == mPorts.end()) {
+ ALOGW("%s: device port for device %s is not found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ return BAD_VALUE;
+ }
+ // Use the ID of the "template" port, use all the information from the provided port.
+ aidlPort.id = portsIt->first;
+ AudioPort connectedPort;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
+ aidlPort, &connectedPort)));
+ const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
+ LOG_ALWAYS_FATAL_IF(!inserted,
+ "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
+ __func__, mInstance.c_str(), connectedPort.toString().c_str(),
+ it->second.toString().c_str());
+ } else { // !connected
+ AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+ auto portsIt = findPort(matchDevice);
+ if (portsIt == mPorts.end()) {
+ ALOGW("%s: device port for device %s is not found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ return BAD_VALUE;
+ }
+ // Any streams opened on the external device must be closed by this time,
+ // thus we can clean up patches and port configs that were created for them.
+ resetUnusedPatchesAndPortConfigs();
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
+ portsIt->second.id)));
+ mPorts.erase(portsIt);
+ }
+ return updateRoutes();
+}
+
+status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ ModuleDebug debug{ .simulateDeviceConnections = enabled };
+ status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
+ // This is important to log as it affects HAL behavior.
+ if (status == OK) {
+ ALOGI("%s: set enabled: %d", __func__, enabled);
+ } else {
+ ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
+ }
+ return status;
+}
+
bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
return p.ext.get<AudioPortExt::Tag::device>().device == device;
@@ -865,7 +1103,8 @@
status_t DeviceHalAidl::findOrCreatePortConfig(
const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
- AudioSource source, AudioPortConfig* portConfig, bool* created) {
+ AudioSource source, const std::set<int32_t>& destinationPortIds,
+ AudioPortConfig* portConfig, bool* created) {
// These flags get removed one by one in this order when retrying port finding.
static const std::vector<AudioInputFlags> kOptionalInputFlags{
AudioInputFlags::FAST, AudioInputFlags::RAW };
@@ -873,7 +1112,7 @@
if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
auto optionalInputFlagsIt = kOptionalInputFlags.begin();
AudioIoFlags matchFlags = flags.value();
- auto portsIt = findPort(config, matchFlags);
+ auto portsIt = findPort(config, matchFlags, destinationPortIds);
while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
&& optionalInputFlagsIt != kOptionalInputFlags.end()) {
if (!isBitPositionFlagSet(
@@ -883,7 +1122,7 @@
}
matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
~makeBitPositionFlagMask(*optionalInputFlagsIt++));
- portsIt = findPort(config, matchFlags);
+ portsIt = findPort(config, matchFlags, destinationPortIds);
ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
"retried with flags %s", __func__, config.toString().c_str(),
flags.value().toString().c_str(), mInstance.c_str(),
@@ -919,7 +1158,8 @@
}
status_t DeviceHalAidl::findOrCreatePortConfig(
- const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
+ const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
+ AudioPortConfig* portConfig, bool* created) {
using Tag = AudioPortExt::Tag;
if (requestedPortConfig.ext.getTag() == Tag::mix) {
if (const auto& p = requestedPortConfig;
@@ -936,7 +1176,8 @@
requestedPortConfig.ext.get<Tag::mix>().usecase.
get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
return findOrCreatePortConfig(config, requestedPortConfig.flags,
- requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
+ requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
+ portConfig, created);
} else if (requestedPortConfig.ext.getTag() == Tag::device) {
return findOrCreatePortConfig(
requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
@@ -968,20 +1209,30 @@
[&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
}
+
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
- const AudioConfig& config, const AudioIoFlags& flags) {
+ const AudioConfig& config, const AudioIoFlags& flags,
+ const std::set<int32_t>& destinationPortIds) {
+ auto belongsToProfile = [&config](const AudioProfile& prof) {
+ return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
+ (config.base.channelMask.getTag() == AudioChannelLayout::none ||
+ std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
+ config.base.channelMask) != prof.channelMasks.end()) &&
+ (config.base.sampleRate == 0 ||
+ std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
+ config.base.sampleRate) != prof.sampleRates.end());
+ };
auto matcher = [&](const auto& pair) {
const auto& p = pair.second;
return p.ext.getTag() == AudioPortExt::Tag::mix &&
p.flags == flags &&
- std::find_if(p.profiles.begin(), p.profiles.end(),
- [&](const auto& prof) {
- return prof.format == config.base.format &&
- std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
- config.base.channelMask) != prof.channelMasks.end() &&
- std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
- config.base.sampleRate) != prof.sampleRates.end();
- }) != p.profiles.end(); };
+ (destinationPortIds.empty() ||
+ std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
+ [&](const int32_t destId) { return mRoutingMatrix.count(
+ std::make_pair(p.id, destId)) != 0; })) &&
+ (p.profiles.empty() ||
+ std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
+ p.profiles.end()); };
return std::find_if(mPorts.begin(), mPorts.end(), matcher);
}
@@ -1006,34 +1257,7 @@
(!flags.has_value() || p.flags.value() == flags.value()) &&
p.ext.template get<Tag::mix>().handle == ioHandle; });
}
-/*
-DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
- const AudioPortConfig& portConfig) {
- using Tag = AudioPortExt::Tag;
- if (portConfig.ext.getTag() == Tag::mix) {
- return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
- [&](const auto& pair) {
- const auto& p = pair.second;
- LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
- !p.sampleRate.has_value() || !p.channelMask.has_value() ||
- !p.format.has_value() || !p.flags.has_value(),
- "%s: stored mix port config is not fully specified: %s",
- __func__, p.toString().c_str());
- return p.ext.getTag() == Tag::mix &&
- (!portConfig.sampleRate.has_value() ||
- p.sampleRate == portConfig.sampleRate) &&
- (!portConfig.channelMask.has_value() ||
- p.channelMask == portConfig.channelMask) &&
- (!portConfig.format.has_value() || p.format == portConfig.format) &&
- (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
- p.ext.template get<Tag::mix>().handle ==
- portConfig.ext.template get<Tag::mix>().handle; });
- } else if (portConfig.ext.getTag() == Tag::device) {
- return findPortConfig(portConfig.ext.get<Tag::device>().device);
- }
- return mPortConfigs.end();
-}
-*/
+
void DeviceHalAidl::resetPatch(int32_t patchId) {
if (auto it = mPatches.find(patchId); it != mPatches.end()) {
mPatches.erase(it);
@@ -1061,6 +1285,56 @@
ALOGE("%s: port config id %d not found", __func__, portConfigId);
}
+void DeviceHalAidl::resetUnusedPatches() {
+ // Since patches can be created independently of streams via 'createAudioPatch',
+ // here we only clean up patches for released streams.
+ for (auto it = mStreams.begin(); it != mStreams.end(); ) {
+ if (auto streamSp = it->first.promote(); streamSp) {
+ ++it;
+ } else {
+ resetPatch(it->second);
+ it = mStreams.erase(it);
+ }
+ }
+}
+
+void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
+ resetUnusedPatches();
+ resetUnusedPortConfigs();
+}
+
+void DeviceHalAidl::resetUnusedPortConfigs() {
+ // The assumption is that port configs are used to create patches
+ // (or to open streams, but that involves creation of patches, too). Thus,
+ // orphaned port configs can and should be reset.
+ std::set<int32_t> portConfigIds;
+ std::transform(mPortConfigs.begin(), mPortConfigs.end(),
+ std::inserter(portConfigIds, portConfigIds.end()),
+ [](const auto& pcPair) { return pcPair.first; });
+ for (const auto& p : mPatches) {
+ for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
+ for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
+ }
+ for (int32_t id : portConfigIds) resetPortConfig(id);
+}
+
+status_t DeviceHalAidl::updateRoutes() {
+ TIME_CHECK();
+ std::vector<AudioRoute> routes;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mModule->getAudioRoutes(&routes)));
+ ALOGW_IF(routes.empty(), "%s: module %s returned an empty list of audio routes",
+ __func__, mInstance.c_str());
+ mRoutingMatrix.clear();
+ for (const auto& r : routes) {
+ for (auto portId : r.sourcePortIds) {
+ mRoutingMatrix.emplace(r.sinkPortId, portId);
+ mRoutingMatrix.emplace(portId, r.sinkPortId);
+ }
+ }
+ return OK;
+}
+
void DeviceHalAidl::clearCallbacks(void* cookie) {
std::lock_guard l(mLock);
mCallbacks.erase(cookie);
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 0a86ddc..fd0cd54 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -24,6 +24,7 @@
#include <android-base/thread_annotations.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
#include "ConversionHelperAidl.h"
@@ -138,7 +139,7 @@
status_t setAudioPortConfig(const struct audio_port_config* config) override;
// List microphones
- status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones);
+ status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones) override;
status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
@@ -154,10 +155,14 @@
error::Result<audio_hw_sync_t> getHwAvSync() override;
- status_t dump(int __unused, const Vector<String16>& __unused) override;
-
int32_t supportsBluetoothVariableLatency(bool* supports __unused) override;
+ status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
+
+ status_t setSimulateDeviceConnections(bool enabled) override;
+
+ status_t dump(int __unused, const Vector<String16>& __unused) override;
+
private:
friend class sp<DeviceHalAidl>;
@@ -176,6 +181,10 @@
using PortConfigs = std::map<int32_t /*port config ID*/,
::aidl::android::media::audio::common::AudioPortConfig>;
using Ports = std::map<int32_t /*port ID*/, ::aidl::android::media::audio::common::AudioPort>;
+ // Answers the question "whether portID 'first' is reachable from portID 'second'?"
+ // It's not a map because both portIDs are known. The matrix is symmetric.
+ using RoutingMatrix = std::set<std::pair<int32_t, int32_t>>;
+ using Streams = std::map<wp<StreamHalInterface>, int32_t /*patch ID*/>;
class Cleanups;
// Must not be constructed directly by clients.
@@ -209,25 +218,25 @@
const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle,
::aidl::android::media::audio::common::AudioSource aidlSource,
+ const std::set<int32_t>& destinationPortIds,
::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
status_t findOrCreatePortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+ const std::set<int32_t>& destinationPortIds,
::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
Patches::iterator findPatch(const std::set<int32_t>& sourcePortConfigIds,
const std::set<int32_t>& sinkPortConfigIds);
Ports::iterator findPort(const ::aidl::android::media::audio::common::AudioDevice& device);
Ports::iterator findPort(
const ::aidl::android::media::audio::common::AudioConfig& config,
- const ::aidl::android::media::audio::common::AudioIoFlags& flags);
+ const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+ const std::set<int32_t>& destinationPortIds);
PortConfigs::iterator findPortConfig(
const ::aidl::android::media::audio::common::AudioDevice& device);
PortConfigs::iterator findPortConfig(
const ::aidl::android::media::audio::common::AudioConfig& config,
const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle);
- // Currently unused but may be useful for implementing setAudioPortConfig
- // PortConfigs::iterator findPortConfig(
- // const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
status_t prepareToOpenStream(
int32_t aidlHandle,
const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
@@ -237,9 +246,13 @@
Cleanups* cleanups,
::aidl::android::media::audio::common::AudioConfig* aidlConfig,
::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig,
- int32_t* nominalLatency);
+ ::aidl::android::hardware::audio::core::AudioPatch* aidlPatch);
void resetPatch(int32_t patchId);
void resetPortConfig(int32_t portConfigId);
+ void resetUnusedPatches();
+ void resetUnusedPatchesAndPortConfigs();
+ void resetUnusedPortConfigs();
+ status_t updateRoutes();
// CallbackBroker implementation
void clearCallbacks(void* cookie) override;
@@ -266,6 +279,8 @@
int32_t mDefaultOutputPortId = -1;
PortConfigs mPortConfigs;
Patches mPatches;
+ RoutingMatrix mRoutingMatrix;
+ Streams mStreams;
Microphones mMicrophones;
std::mutex mLock;
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 052eb65..132aad7 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -126,6 +126,11 @@
status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
+ status_t setSimulateDeviceConnections(bool enabled __unused) override {
+ // Only supported by AIDL HALs.
+ return INVALID_OPERATION;
+ }
+
error::Result<audio_hw_sync_t> getHwAvSync() override;
status_t dump(int fd, const Vector<String16>& args) override;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index cbc1578..3048580 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -40,6 +40,7 @@
using ::aidl::android::hardware::audio::core::IStreamIn;
using ::aidl::android::hardware::audio::core::IStreamOut;
using ::aidl::android::hardware::audio::core::StreamDescriptor;
+using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
namespace android {
@@ -255,16 +256,23 @@
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ const auto state = getState();
+ StreamDescriptor::Reply reply;
+ if (state == StreamDescriptor::State::STANDBY) {
+ if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true);
+ status != OK) {
+ return status;
+ }
+ return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), &reply, true);
+ }
+
+ return INVALID_OPERATION;
}
status_t StreamHalAidl::stop() {
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
- TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return standby();
}
status_t StreamHalAidl::getLatency(uint32_t *latency) {
@@ -290,6 +298,20 @@
return OK;
}
+status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!mStream) return NO_INIT;
+ StreamDescriptor::Reply reply;
+ // TODO: switch to updateCountersIfNeeded once we sort out mWorkerTid initialization
+ if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), &reply, true);
+ status != OK) {
+ return status;
+ }
+ *frames = reply.hardware.frames;
+ *timestamp = reply.hardware.timeNs;
+ return OK;
+}
+
status_t StreamHalAidl::getXruns(int32_t *frames) {
ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
if (!mStream) return NO_INIT;
@@ -419,19 +441,35 @@
}
status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
- struct audio_mmap_buffer_info *info __unused) {
+ struct audio_mmap_buffer_info *info) {
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (!mContext.isMmapped()) {
+ return BAD_VALUE;
+ }
+ const MmapBufferDescriptor& bufferDescriptor = mContext.getMmapBufferDescriptor();
+ info->shared_memory_fd = bufferDescriptor.sharedMemory.fd.get();
+ info->buffer_size_frames = mContext.getBufferSizeFrames();
+ info->burst_size_frames = bufferDescriptor.burstSizeFrames;
+ info->flags = static_cast<audio_mmap_buffer_flag>(bufferDescriptor.flags);
+
return OK;
}
-status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
- ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (!mContext.isMmapped()) {
+ return BAD_VALUE;
+ }
+ int64_t aidlPosition = 0, aidlTimestamp = 0;
+ if (status_t status = getHardwarePosition(&aidlPosition, &aidlTimestamp); status != OK) {
+ return status;
+ }
+
+ position->time_nanoseconds = aidlTimestamp;
+ position->position_frames = static_cast<int32_t>(aidlPosition);
return OK;
}
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 157e8bb..147c131 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -25,6 +25,7 @@
#include <aidl/android/hardware/audio/core/BpStreamCommon.h>
#include <aidl/android/hardware/audio/core/BpStreamIn.h>
#include <aidl/android/hardware/audio/core/BpStreamOut.h>
+#include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h>
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
@@ -34,6 +35,7 @@
#include "StreamPowerLog.h"
using ::aidl::android::hardware::audio::common::AudioOffloadMetadata;
+using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
namespace android {
@@ -47,21 +49,25 @@
::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
explicit StreamContextAidl(
- const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
+ ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
bool isAsynchronous)
: mFrameSizeBytes(descriptor.frameSizeBytes),
mCommandMQ(new CommandMQ(descriptor.command)),
mReplyMQ(new ReplyMQ(descriptor.reply)),
mBufferSizeFrames(descriptor.bufferSizeFrames),
mDataMQ(maybeCreateDataMQ(descriptor)),
- mIsAsynchronous(isAsynchronous) {}
+ mIsAsynchronous(isAsynchronous),
+ mIsMmapped(isMmapped(descriptor)),
+ mMmapBufferDescriptor(maybeGetMmapBuffer(descriptor)) {}
StreamContextAidl(StreamContextAidl&& other) :
mFrameSizeBytes(other.mFrameSizeBytes),
mCommandMQ(std::move(other.mCommandMQ)),
mReplyMQ(std::move(other.mReplyMQ)),
mBufferSizeFrames(other.mBufferSizeFrames),
mDataMQ(std::move(other.mDataMQ)),
- mIsAsynchronous(other.mIsAsynchronous) {}
+ mIsAsynchronous(other.mIsAsynchronous),
+ mIsMmapped(other.mIsMmapped),
+ mMmapBufferDescriptor(std::move(other.mMmapBufferDescriptor)) {}
StreamContextAidl& operator=(StreamContextAidl&& other) {
mFrameSizeBytes = other.mFrameSizeBytes;
mCommandMQ = std::move(other.mCommandMQ);
@@ -69,16 +75,19 @@
mBufferSizeFrames = other.mBufferSizeFrames;
mDataMQ = std::move(other.mDataMQ);
mIsAsynchronous = other.mIsAsynchronous;
+ mIsMmapped = other.mIsMmapped;
+ mMmapBufferDescriptor = std::move(other.mMmapBufferDescriptor);
return *this;
}
bool isValid() const {
return mFrameSizeBytes != 0 &&
mCommandMQ != nullptr && mCommandMQ->isValid() &&
mReplyMQ != nullptr && mReplyMQ->isValid() &&
- (mDataMQ != nullptr || (
+ (mDataMQ == nullptr || (
mDataMQ->isValid() &&
mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() >=
- mFrameSizeBytes * mBufferSizeFrames));
+ mFrameSizeBytes * mBufferSizeFrames)) &&
+ (!mIsMmapped || mMmapBufferDescriptor.sharedMemory.fd.get() >= 0);
}
size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
@@ -87,6 +96,8 @@
size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
bool isAsynchronous() const { return mIsAsynchronous; }
+ bool isMmapped() const { return mIsMmapped; }
+ const MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; }
private:
static std::unique_ptr<DataMQ> maybeCreateDataMQ(
@@ -97,6 +108,19 @@
}
return nullptr;
}
+ static bool isMmapped(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+ using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+ return descriptor.audio.getTag() == Tag::mmap;
+ }
+ static MmapBufferDescriptor maybeGetMmapBuffer(
+ ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+ using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+ if (descriptor.audio.getTag() == Tag::mmap) {
+ return std::move(descriptor.audio.get<Tag::mmap>());
+ }
+ return {};
+ }
size_t mFrameSizeBytes;
std::unique_ptr<CommandMQ> mCommandMQ;
@@ -104,6 +128,8 @@
size_t mBufferSizeFrames;
std::unique_ptr<DataMQ> mDataMQ;
bool mIsAsynchronous;
+ bool mIsMmapped;
+ MmapBufferDescriptor mMmapBufferDescriptor;
};
class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
@@ -181,6 +207,8 @@
status_t getObservablePosition(int64_t *frames, int64_t *timestamp);
+ status_t getHardwarePosition(int64_t *frames, int64_t *timestamp);
+
status_t getXruns(int32_t *frames);
status_t transfer(void *buffer, size_t bytes, size_t *transferred);
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index c685345..2523ba6 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -128,13 +128,14 @@
std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
virtual int32_t getAAudioMixerBurstCount() = 0;
virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
+
virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0;
// Update the connection status of an external device.
- virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) {
- ALOGE("%s override me port %p connected %d", __func__, port, connected);
- return OK;
- }
+ virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) = 0;
+
+ // Enable simulation of external devices connection at the HAL level.
+ virtual status_t setSimulateDeviceConnections(bool enabled) = 0;
virtual error::Result<audio_hw_sync_t> getHwAvSync() = 0;
diff --git a/media/libeffects/dynamicsproc/Android.bp b/media/libeffects/dynamicsproc/Android.bp
index 736a086..7838117 100644
--- a/media/libeffects/dynamicsproc/Android.bp
+++ b/media/libeffects/dynamicsproc/Android.bp
@@ -92,6 +92,10 @@
"dynamicsprocessingdefaults",
],
+ static_libs: [
+ "libaudioaidlranges",
+ ],
+
visibility: [
"//hardware/interfaces/audio/aidl/default",
],
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index e508d48..f1619a8 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -62,32 +62,135 @@
const std::string DynamicsProcessingImpl::kEffectName = "DynamicsProcessing";
-const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMin =
+static const Range::DynamicsProcessingRange kEngineConfigRange = {
+ .min = DynamicsProcessing::make<
+ DynamicsProcessing::engineArchitecture>(DynamicsProcessing::EngineArchitecture(
+ {.resolutionPreference =
+ DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
+ .preferredProcessingDurationMs = 0,
+ .preEqStage = {.inUse = false, .bandCount = 0},
+ .postEqStage = {.inUse = false, .bandCount = 0},
+ .mbcStage = {.inUse = false, .bandCount = 0},
+ .limiterInUse = false})),
+ .max = DynamicsProcessing::make<
+ DynamicsProcessing::engineArchitecture>(DynamicsProcessing::EngineArchitecture(
+ {.resolutionPreference =
+ DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
+ .preferredProcessingDurationMs = std::numeric_limits<float>::max(),
+ .preEqStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+ .postEqStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+ .mbcStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+ .limiterInUse = true}))};
+
+static const DynamicsProcessing::ChannelConfig kChannelConfigMin =
+ DynamicsProcessing::ChannelConfig({.channel = 0, .enable = false});
+
+static const DynamicsProcessing::ChannelConfig kChannelConfigMax =
+ DynamicsProcessing::ChannelConfig(
+ {.channel = std::numeric_limits<int>::max(), .enable = true});
+
+static const Range::DynamicsProcessingRange kPreEqChannelConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::preEq>({kChannelConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::preEq>({kChannelConfigMax})};
+
+static const Range::DynamicsProcessingRange kPostEqChannelConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::postEq>({kChannelConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::postEq>({kChannelConfigMax})};
+
+static const Range::DynamicsProcessingRange kMbcChannelConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::mbc>({kChannelConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::mbc>({kChannelConfigMax})};
+
+static const DynamicsProcessing::EqBandConfig kEqBandConfigMin =
DynamicsProcessing::EqBandConfig({.channel = 0,
.band = 0,
.enable = false,
.cutoffFrequencyHz = 220,
- .gainDb = std::numeric_limits<float>::min()});
-const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMax =
+ .gainDb = std::numeric_limits<float>::lowest()});
+
+static const DynamicsProcessing::EqBandConfig kEqBandConfigMax =
DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
.band = std::numeric_limits<int>::max(),
.enable = true,
.cutoffFrequencyHz = 20000,
.gainDb = std::numeric_limits<float>::max()});
-const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPreEqBandRange = {
- .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
- {DynamicsProcessingImpl::kEqBandConfigMin}),
- .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
- {DynamicsProcessingImpl::kEqBandConfigMax})};
-const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPostEqBandRange = {
- .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
- {DynamicsProcessingImpl::kEqBandConfigMin}),
- .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
- {DynamicsProcessingImpl::kEqBandConfigMax})};
-const Range DynamicsProcessingImpl::kRange =
- Range::make<Range::dynamicsProcessing>({DynamicsProcessingImpl::kPreEqBandRange});
-const Capability DynamicsProcessingImpl::kCapability = {.range = {DynamicsProcessingImpl::kRange}};
+static const Range::DynamicsProcessingRange kPreEqBandConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>({kEqBandConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>({kEqBandConfigMax})};
+
+static const Range::DynamicsProcessingRange kPostEqBandConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>({kEqBandConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>({kEqBandConfigMax})};
+
+static const Range::DynamicsProcessingRange kMbcBandConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
+ {DynamicsProcessing::MbcBandConfig(
+ {.channel = 0,
+ .band = 0,
+ .enable = false,
+ .cutoffFrequencyHz = 220,
+ .attackTimeMs = 0,
+ .releaseTimeMs = 0,
+ .ratio = 0,
+ .thresholdDb = std::numeric_limits<float>::lowest(),
+ .kneeWidthDb = 0,
+ .noiseGateThresholdDb = std::numeric_limits<float>::lowest(),
+ .expanderRatio = 0,
+ .preGainDb = std::numeric_limits<float>::lowest(),
+ .postGainDb = std::numeric_limits<float>::lowest()})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
+ {DynamicsProcessing::MbcBandConfig(
+ {.channel = std::numeric_limits<int>::max(),
+ .band = std::numeric_limits<int>::max(),
+ .enable = true,
+ .cutoffFrequencyHz = 20000,
+ .attackTimeMs = std::numeric_limits<float>::max(),
+ .releaseTimeMs = std::numeric_limits<float>::max(),
+ .ratio = std::numeric_limits<float>::max(),
+ .thresholdDb = 0,
+ .kneeWidthDb = std::numeric_limits<float>::max(),
+ .noiseGateThresholdDb = 0,
+ .expanderRatio = std::numeric_limits<float>::max(),
+ .preGainDb = std::numeric_limits<float>::max(),
+ .postGainDb = std::numeric_limits<float>::max()})})};
+
+static const Range::DynamicsProcessingRange kInputGainRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+ {DynamicsProcessing::InputGain(
+ {.channel = 0, .gainDb = std::numeric_limits<float>::lowest()})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+ {DynamicsProcessing::InputGain({.channel = std::numeric_limits<int>::max(),
+ .gainDb = std::numeric_limits<float>::max()})})};
+
+static const Range::DynamicsProcessingRange kLimiterRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::limiter>(
+ {DynamicsProcessing::LimiterConfig(
+ {.channel = 0,
+ .enable = false,
+ .linkGroup = std::numeric_limits<int>::min(),
+ .attackTimeMs = 0,
+ .releaseTimeMs = 0,
+ .ratio = 0,
+ .thresholdDb = std::numeric_limits<float>::min(),
+ .postGainDb = std::numeric_limits<float>::min()})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::limiter>(
+ {DynamicsProcessing::LimiterConfig(
+ {.channel = std::numeric_limits<int>::max(),
+ .enable = true,
+ .linkGroup = std::numeric_limits<int>::max(),
+ .attackTimeMs = std::numeric_limits<float>::max(),
+ .releaseTimeMs = std::numeric_limits<float>::max(),
+ .ratio = std::numeric_limits<float>::max(),
+ .thresholdDb = 0,
+ .postGainDb = std::numeric_limits<float>::max()})})};
+
+const std::vector<Range::DynamicsProcessingRange> kRanges = {
+ kEngineConfigRange, kPreEqChannelConfigRange, kPostEqChannelConfigRange,
+ kMbcChannelConfigRange, kPreEqBandConfigRange, kPostEqBandConfigRange,
+ kMbcBandConfigRange, kInputGainRange, kLimiterRange};
+
+const Capability DynamicsProcessingImpl::kCapability = {.range = kRanges};
const Descriptor DynamicsProcessingImpl::kDescriptor = {
.common = {.id = {.type = getEffectTypeUuidDynamicsProcessing(),
@@ -158,14 +261,19 @@
}
}
+bool DynamicsProcessingImpl::isParamInRange(const Parameter::Specific& specific) {
+ auto& dp = specific.get<Parameter::Specific::dynamicsProcessing>();
+ return DynamicsProcessingRanges::isParamInRange(dp, kRanges);
+}
+
ndk::ScopedAStatus DynamicsProcessingImpl::setParameterSpecific(
const Parameter::Specific& specific) {
RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ RETURN_IF(!isParamInRange(specific), EX_ILLEGAL_ARGUMENT, "outOfRange");
auto& param = specific.get<Parameter::Specific::dynamicsProcessing>();
- // TODO: check range here, dynamicsProcessing need customized method for nested parameters.
auto tag = param.getTag();
switch (tag) {
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
index d094c69..1e1e72e 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -18,8 +18,9 @@
#include <aidl/android/hardware/audio/effect/BnEffect.h>
-#include "effect-impl/EffectImpl.h"
#include "DynamicsProcessingContext.h"
+#include "EffectRangeSpecific.h"
+#include "effect-impl/EffectImpl.h"
namespace aidl::android::hardware::audio::effect {
@@ -51,14 +52,10 @@
std::string getEffectName() override { return kEffectName; }
private:
- static const DynamicsProcessing::EqBandConfig kEqBandConfigMin;
- static const DynamicsProcessing::EqBandConfig kEqBandConfigMax;
- static const Range::DynamicsProcessingRange kPreEqBandRange;
- static const Range::DynamicsProcessingRange kPostEqBandRange;
- static const Range kRange;
std::shared_ptr<DynamicsProcessingContext> mContext;
ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
Parameter::Specific* specific);
+ bool isParamInRange(const Parameter::Specific& specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index 69ff522..9d77135 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -16,11 +16,11 @@
#define LOG_TAG "AHAL_DPLibEffectsContext"
-#include "DynamicsProcessing.h"
#include "DynamicsProcessingContext.h"
+#include "DynamicsProcessing.h"
-#include <functional>
#include <sys/param.h>
+#include <functional>
#include <unordered_set>
namespace aidl::android::hardware::audio::effect {
@@ -83,7 +83,7 @@
if (block < minBlockSize) {
block = minBlockSize;
} else if (!powerof2(block)) {
- //find next highest power of 2.
+ // find next highest power of 2.
block = 1 << (32 - __builtin_clz(block));
}
mDpFreq->configure(block, block >> 1, sampleRate);
@@ -91,9 +91,6 @@
RetCode DynamicsProcessingContext::setEngineArchitecture(
const DynamicsProcessing::EngineArchitecture& engineArchitecture) {
- RETURN_VALUE_IF(!validateEngineConfig(engineArchitecture), RetCode::ERROR_ILLEGAL_PARAMETER,
- "illegalEngineConfig");
-
std::lock_guard lg(mMutex);
if (!mEngineInited || mEngineArchitecture != engineArchitecture) {
if (engineArchitecture.resolutionPreference ==
@@ -134,10 +131,12 @@
RetCode DynamicsProcessingContext::setPreEqBand(
const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
std::lock_guard lg(mMutex);
- RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
- "postEqNotInUse");
- return setBands_l<DynamicsProcessing::EqBandConfig>(
- bands, mEngineArchitecture.preEqStage.bandCount, StageType::PREEQ);
+ RETURN_VALUE_IF(!mEngineArchitecture.preEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "preEqNotInUse");
+ RETURN_VALUE_IF(
+ !validateBandConfig(bands, mChannelCount, mEngineArchitecture.preEqStage.bandCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+ return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::PREEQ);
}
RetCode DynamicsProcessingContext::setPostEqBand(
@@ -145,8 +144,10 @@
std::lock_guard lg(mMutex);
RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
"postEqNotInUse");
- return setBands_l<DynamicsProcessing::EqBandConfig>(
- bands, mEngineArchitecture.postEqStage.bandCount, StageType::POSTEQ);
+ RETURN_VALUE_IF(
+ !validateBandConfig(bands, mChannelCount, mEngineArchitecture.postEqStage.bandCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+ return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::POSTEQ);
}
RetCode DynamicsProcessingContext::setMbcBand(
@@ -154,8 +155,10 @@
std::lock_guard lg(mMutex);
RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
"mbcNotInUse");
- return setBands_l<DynamicsProcessing::MbcBandConfig>(
- bands, mEngineArchitecture.preEqStage.bandCount, StageType::MBC);
+ RETURN_VALUE_IF(
+ !validateBandConfig(bands, mChannelCount, mEngineArchitecture.mbcStage.bandCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+ return setBands_l<DynamicsProcessing::MbcBandConfig>(bands, StageType::MBC);
}
RetCode DynamicsProcessingContext::setLimiter(
@@ -163,13 +166,17 @@
std::lock_guard lg(mMutex);
RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
"limiterNotInUse");
- return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, -1, StageType::LIMITER);
+ RETURN_VALUE_IF(!validateLimiterConfig(limiters, mChannelCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "limiterConfigNotValid");
+ return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, StageType::LIMITER);
}
RetCode DynamicsProcessingContext::setInputGain(
const std::vector<DynamicsProcessing::InputGain>& inputGains) {
std::lock_guard lg(mMutex);
- return setBands_l<DynamicsProcessing::InputGain>(inputGains, -1, StageType::INPUTGAIN);
+ RETURN_VALUE_IF(!validateInputGainConfig(inputGains, mChannelCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
+ return setBands_l<DynamicsProcessing::InputGain>(inputGains, StageType::INPUTGAIN);
}
DynamicsProcessing::EngineArchitecture DynamicsProcessingContext::getEngineArchitecture() {
@@ -406,45 +413,33 @@
return eqBands;
}
-/**
- * When StageEnablement is in use, bandCount needs to be positive.
- */
-bool DynamicsProcessingContext::validateStageEnablement(
- const DynamicsProcessing::StageEnablement& enablement) {
- return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
-}
-
-bool DynamicsProcessingContext::validateEngineConfig(
- const DynamicsProcessing::EngineArchitecture& engine) {
- return engine.preferredProcessingDurationMs >= 0 &&
- validateStageEnablement(engine.preEqStage) &&
- validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
-}
-
-bool DynamicsProcessingContext::validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band,
- int maxChannel, int maxBand) {
- return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand);
-}
-
-bool DynamicsProcessingContext::validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band,
- int maxChannel, int maxBand) {
- return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
- validateTime(band.attackTimeMs) && validateTime(band.releaseTimeMs) &&
- validateRatio(band.ratio) && validateBandDb(band.thresholdDb) &&
- validateBandDb(band.kneeWidthDb) && validateBandDb(band.noiseGateThresholdDb) &&
- validateRatio(band.expanderRatio);
+template <typename T>
+bool DynamicsProcessingContext::validateBandConfig(const std::vector<T>& bands, int maxChannel,
+ int maxBand) {
+ std::vector<float> freqs(bands.size(), -1);
+ for (auto band : bands) {
+ if (!validateChannel(band.channel, maxChannel)) return false;
+ if (!validateBand(band.band, maxBand)) return false;
+ freqs[band.band] = band.cutoffFrequencyHz;
+ }
+ if (std::count(freqs.begin(), freqs.end(), -1)) return false;
+ return std::is_sorted(freqs.begin(), freqs.end());
}
bool DynamicsProcessingContext::validateLimiterConfig(
- const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
- return validateChannel(limiter.channel, maxChannel) && validateTime(limiter.attackTimeMs) &&
- validateTime(limiter.releaseTimeMs) && validateRatio(limiter.ratio) &&
- validateBandDb(limiter.thresholdDb);
+ const std::vector<DynamicsProcessing::LimiterConfig>& cfgs, int maxChannel) {
+ for (auto cfg : cfgs) {
+ if (!validateChannel(cfg.channel, maxChannel)) return false;
+ }
+ return true;
}
-bool DynamicsProcessingContext::validateInputGainConfig(const DynamicsProcessing::InputGain& gain,
- int maxChannel) {
- return validateChannel(gain.channel, maxChannel);
+bool DynamicsProcessingContext::validateInputGainConfig(
+ const std::vector<DynamicsProcessing::InputGain>& cfgs, int maxChannel) {
+ for (auto cfg : cfgs) {
+ if (!validateChannel(cfg.channel, maxChannel)) return false;
+ }
+ return true;
}
template <typename D>
@@ -483,7 +478,6 @@
}
RetCode DynamicsProcessingContext::setDpChannelBand_l(const std::any& anyConfig, StageType type,
- int maxCh, int maxBand,
std::set<std::pair<int, int>>& chBandSet) {
RETURN_VALUE_IF(!anyConfig.has_value(), RetCode::ERROR_ILLEGAL_PARAMETER, "bandInvalid");
RetCode ret = RetCode::SUCCESS;
@@ -494,8 +488,6 @@
case StageType::POSTEQ: {
dp_fx::DPEq* dp;
const auto& config = std::any_cast<DynamicsProcessing::EqBandConfig>(anyConfig);
- RETURN_VALUE_IF(!validateEqBandConfig(config, maxCh, maxBand),
- RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
RETURN_VALUE_IF(
nullptr == (dp = getEqWithType_l(type, config.channel)) || !dp->isEnabled(),
RetCode::ERROR_ILLEGAL_PARAMETER, "dpEqNotExist");
@@ -508,8 +500,6 @@
case StageType::MBC: {
dp_fx::DPMbc* dp;
const auto& config = std::any_cast<DynamicsProcessing::MbcBandConfig>(anyConfig);
- RETURN_VALUE_IF(!validateMbcBandConfig(config, maxCh, maxBand),
- RetCode::ERROR_ILLEGAL_PARAMETER, "mbcBandNotValid");
RETURN_VALUE_IF(nullptr == (dp = getMbc_l(config.channel)) || !dp->isEnabled(),
RetCode::ERROR_ILLEGAL_PARAMETER, "dpMbcNotExist");
dp_fx::DPMbcBand band;
@@ -524,8 +514,6 @@
case StageType::LIMITER: {
dp_fx::DPChannel* dp;
const auto& config = std::any_cast<DynamicsProcessing::LimiterConfig>(anyConfig);
- RETURN_VALUE_IF(!validateLimiterConfig(config, maxCh),
- RetCode::ERROR_ILLEGAL_PARAMETER, "limiterBandNotValid");
RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
dp_fx::DPLimiter limiter;
@@ -539,8 +527,6 @@
case StageType::INPUTGAIN: {
dp_fx::DPChannel* dp;
const auto& config = std::any_cast<DynamicsProcessing::InputGain>(anyConfig);
- RETURN_VALUE_IF(!validateInputGainConfig(config, maxCh),
- RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
dp->setInputGain(config.gainDb);
@@ -555,14 +541,12 @@
}
template <typename T /* BandConfig */>
-RetCode DynamicsProcessingContext::setBands_l(
- const std::vector<T>& bands, int maxBand, StageType type) {
+RetCode DynamicsProcessingContext::setBands_l(const std::vector<T>& bands, StageType type) {
RetCode ret = RetCode::SUCCESS;
std::set<std::pair<int /* channel */, int /* band */>> bandSet;
for (const auto& it : bands) {
- if (RetCode::SUCCESS !=
- setDpChannelBand_l(std::make_any<T>(it), type, mChannelCount, maxBand, bandSet)) {
+ if (RetCode::SUCCESS != setDpChannelBand_l(std::make_any<T>(it), type, bandSet)) {
LOG(WARNING) << __func__ << " skipping band " << it.toString();
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
continue;
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
index 8be784e..b8539f6 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
@@ -103,28 +103,22 @@
RetCode setDpChannels_l(const std::vector<DynamicsProcessing::ChannelConfig>& channels,
bool stageInUse, StageType type) REQUIRES(mMutex);
template <typename T /* BandConfig */>
- RetCode setBands_l(const std::vector<T>& bands, int maxBand, StageType type) REQUIRES(mMutex);
- RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type, int maxCh, int maxBand,
+ RetCode setBands_l(const std::vector<T>& bands, StageType type) REQUIRES(mMutex);
+ RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type,
std::set<std::pair<int, int>>& chBandSet) REQUIRES(mMutex);
std::vector<DynamicsProcessing::EqBandConfig> getEqBandConfigs(StageType type);
std::vector<DynamicsProcessing::ChannelConfig> getChannelConfig(StageType type);
- bool validateStageEnablement(const DynamicsProcessing::StageEnablement& enablement);
- bool validateEngineConfig(const DynamicsProcessing::EngineArchitecture& engine);
- bool validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band, int maxChannel,
- int maxBand);
- bool validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band, int maxChannel,
- int maxBand);
- bool validateLimiterConfig(const DynamicsProcessing::LimiterConfig& limiter, int maxChannel);
- bool validateInputGainConfig(const DynamicsProcessing::InputGain& gain, int maxChannel);
+ template <typename T /* BandConfig */>
+ bool validateBandConfig(const std::vector<T>& bands, int maxChannel, int maxBand);
+ bool validateLimiterConfig(const std::vector<DynamicsProcessing::LimiterConfig>& cfgs,
+ int maxChannel);
+ bool validateInputGainConfig(const std::vector<DynamicsProcessing::InputGain>& cfgs,
+ int maxChannel);
- inline bool validateCutoffFrequency(float freq);
inline bool validateChannel(int ch, int maxCh) { return ch >= 0 && ch < maxCh; }
inline bool validateBand(int band, int maxBand) { return band >= 0 && band < maxBand; }
- inline bool validateTime(int time) { return time >= 0; }
- inline bool validateRatio(int ratio) { return ratio >= 0; }
- inline bool validateBandDb(int db) { return db <= 0; }
};
} // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 8a3b84e..86427ed 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -27,40 +27,6 @@
#include <utils/String8.h>
#include <utils/KeyedVector.h>
-// The binder is supposed to propagate the scheduler group across
-// the binder interface so that remote calls are executed with
-// the same priority as local calls. This is currently not working
-// so this change puts in a temporary hack to fix the issue with
-// metadata retrieval which can be a huge CPU hit if done on a
-// foreground thread.
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-
-#undef LOG_TAG
-#define LOG_TAG "IMediaMetadataRetriever"
-#include <utils/Log.h>
-#include <cutils/sched_policy.h>
-
-namespace android {
-
-static void sendSchedPolicy(Parcel& data)
-{
- SchedPolicy policy;
- get_sched_policy(gettid(), &policy);
- data.writeInt32(policy);
-}
-
-static void setSchedPolicy(const Parcel& data)
-{
- SchedPolicy policy = (SchedPolicy) data.readInt32();
- set_sched_policy(gettid(), policy);
-}
-static void restoreSchedPolicy()
-{
- set_sched_policy(gettid(), SP_FOREGROUND);
-}
-}; // end namespace android
-#endif
-
namespace android {
enum {
@@ -157,9 +123,6 @@
data.writeInt32(option);
data.writeInt32(colorFormat);
data.writeInt32(metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(GET_FRAME_AT_TIME, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -178,9 +141,6 @@
data.writeInt32(colorFormat);
data.writeInt32(metaOnly);
data.writeInt32(thumbnail);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(GET_IMAGE_AT_INDEX, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -202,9 +162,6 @@
data.writeInt32(top);
data.writeInt32(right);
data.writeInt32(bottom);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(GET_IMAGE_RECT_AT_INDEX, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -223,9 +180,6 @@
data.writeInt32(index);
data.writeInt32(colorFormat);
data.writeInt32(metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(GET_FRAME_AT_INDEX, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -238,9 +192,6 @@
{
Parcel data, reply;
data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -253,9 +204,6 @@
{
Parcel data, reply;
data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
data.writeInt32(keyCode);
remote()->transact(EXTRACT_METADATA, data, &reply);
status_t ret = reply.readInt32();
@@ -366,9 +314,6 @@
bool metaOnly = (data.readInt32() != 0);
ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d), metaOnly(%d)",
timeUs, option, colorFormat, metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> bitmap = getFrameAtTime(timeUs, option, colorFormat, metaOnly);
if (bitmap != 0) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
@@ -376,9 +321,6 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
case GET_IMAGE_AT_INDEX: {
@@ -389,9 +331,6 @@
bool thumbnail = (data.readInt32() != 0);
ALOGV("getImageAtIndex: index(%d), colorFormat(%d), metaOnly(%d), thumbnail(%d)",
index, colorFormat, metaOnly, thumbnail);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> bitmap = getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
if (bitmap != 0) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
@@ -399,9 +338,6 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
@@ -415,9 +351,6 @@
int bottom = data.readInt32();
ALOGV("getImageRectAtIndex: index(%d), colorFormat(%d), rect {%d, %d, %d, %d}",
index, colorFormat, left, top, right, bottom);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> bitmap = getImageRectAtIndex(
index, colorFormat, left, top, right, bottom);
if (bitmap != 0) { // Don't send NULL across the binder interface
@@ -426,9 +359,6 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
@@ -439,9 +369,6 @@
bool metaOnly = (data.readInt32() != 0);
ALOGV("getFrameAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
index, colorFormat, metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> frame = getFrameAtIndex(index, colorFormat, metaOnly);
if (frame != nullptr) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
@@ -449,16 +376,10 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
case EXTRACT_ALBUM_ART: {
CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> albumArt = extractAlbumArt();
if (albumArt != 0) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
@@ -466,16 +387,10 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
case EXTRACT_METADATA: {
CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
int keyCode = data.readInt32();
const char* value = extractMetadata(keyCode);
if (value != NULL) { // Don't send NULL across the binder interface
@@ -484,9 +399,6 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
default:
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 32e40c3..fc49d69 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -238,6 +238,7 @@
"CallbackMediaSource.cpp",
"CameraSource.cpp",
"CameraSourceTimeLapse.cpp",
+ "CodecErrorLog.cpp",
"FrameDecoder.cpp",
"HevcUtils.cpp",
"InterfaceUtils.cpp",
diff --git a/media/libstagefright/CodecErrorLog.cpp b/media/libstagefright/CodecErrorLog.cpp
new file mode 100644
index 0000000..9785623
--- /dev/null
+++ b/media/libstagefright/CodecErrorLog.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CodecErrorLog"
+
+#include <log/log.h>
+#include <media/stagefright/CodecErrorLog.h>
+
+namespace android {
+
+void CodecErrorLog::log(const char *tag, const char *message) {
+ std::unique_lock lock(mLock);
+ ALOG(LOG_ERROR, tag, "%s", message);
+ mStream << message << std::endl;
+}
+
+void CodecErrorLog::log(const char *tag, const std::string &message) {
+ log(tag, message.c_str());
+}
+
+std::string CodecErrorLog::extract() {
+ std::unique_lock lock(mLock);
+ std::string msg = mStream.str();
+ mStream.str("");
+ return msg;
+}
+
+void CodecErrorLog::clear() {
+ std::unique_lock lock(mLock);
+ mStream.str("");
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 9b8cc5e..4a67876 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -41,6 +41,7 @@
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
#include <android/dlext.h>
+#include <android-base/stringprintf.h>
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryDealer.h>
@@ -874,10 +875,12 @@
};
}
if (!mGetCodecInfo) {
- mGetCodecInfo = [](const AString &name, sp<MediaCodecInfo> *info) -> status_t {
+ mGetCodecInfo = [&log = mErrorLog](const AString &name,
+ sp<MediaCodecInfo> *info) -> status_t {
*info = nullptr;
const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
if (!mcl) {
+ log.log(LOG_TAG, "Fatal error: failed to initialize MediaCodecList");
return NO_INIT; // if called from Java should raise IOException
}
AString tmp = name;
@@ -892,6 +895,8 @@
*info = mcl->getCodecInfo(codecIdx);
return OK;
}
+ log.log(LOG_TAG, base::StringPrintf("Codec with name '%s' is not found on the device.",
+ name.c_str()));
return NAME_NOT_FOUND;
};
}
@@ -947,6 +952,7 @@
void MediaCodec::updateMediametrics() {
if (mMetricsHandle == 0) {
+ ALOGW("no metrics handle found");
return;
}
@@ -1625,6 +1631,8 @@
status_t MediaCodec::init(const AString &name) {
status_t err = mResourceManagerProxy->init();
if (err != OK) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: failed to initialize ResourceManager (err=%d)", err));
mCodec = NULL; // remove the codec
return err;
}
@@ -1644,11 +1652,14 @@
if (!name.startsWith("android.filter.")) {
err = mGetCodecInfo(name, &mCodecInfo);
if (err != OK) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Getting codec info with name '%s' failed (err=%d)", name.c_str(), err));
mCodec = NULL; // remove the codec.
return err;
}
if (mCodecInfo == nullptr) {
- ALOGE("Getting codec info with name '%s' failed", name.c_str());
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Getting codec info with name '%s' failed", name.c_str()));
return NAME_NOT_FOUND;
}
secureCodec = name.endsWith(".secure");
@@ -1671,7 +1682,8 @@
mCodec = mGetCodecBase(name, owner);
if (mCodec == NULL) {
- ALOGE("Getting codec base with name '%s' (owner='%s') failed", name.c_str(), owner);
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Getting codec base with name '%s' (from '%s' HAL) failed", name.c_str(), owner));
return NAME_NOT_FOUND;
}
@@ -1683,7 +1695,7 @@
mCodecLooper->setName("CodecLooper");
err = mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
if (OK != err) {
- ALOGE("Codec Looper failed to start");
+ mErrorLog.log(LOG_TAG, "Fatal error: codec looper failed to start");
return err;
}
}
@@ -1860,7 +1872,8 @@
// Prevent possible integer overflow in downstream code.
if (mWidth < 0 || mHeight < 0 ||
(uint64_t)mWidth * mHeight > (uint64_t)INT32_MAX / 4) {
- ALOGE("Invalid size(s), width=%d, height=%d", mWidth, mHeight);
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid size(s), width=%d, height=%d", mWidth, mHeight));
return BAD_VALUE;
}
@@ -3030,17 +3043,17 @@
sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
// use mutex instead of a context switch
if (mReleasedByResourceManager) {
- ALOGE("getBufferAndFormat - resource already released");
+ mErrorLog.log(LOG_TAG, "resource already released");
return DEAD_OBJECT;
}
if (buffer == NULL) {
- ALOGE("getBufferAndFormat - null MediaCodecBuffer");
+ mErrorLog.log(LOG_TAG, "null buffer");
return INVALID_OPERATION;
}
if (format == NULL) {
- ALOGE("getBufferAndFormat - null AMessage");
+ mErrorLog.log(LOG_TAG, "null format");
return INVALID_OPERATION;
}
@@ -3048,7 +3061,9 @@
format->clear();
if (!isExecuting()) {
- ALOGE("getBufferAndFormat - not executing");
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid to call %s; only valid in Executing states",
+ apiStateString().c_str()));
return INVALID_OPERATION;
}
@@ -3060,6 +3075,7 @@
if (index >= buffers.size()) {
ALOGE("getBufferAndFormat - trying to get buffer with "
"bad index (index=%zu buffer_size=%zu)", index, buffers.size());
+ mErrorLog.log(LOG_TAG, base::StringPrintf("Bad index (index=%zu)", index));
return INVALID_OPERATION;
}
@@ -3067,6 +3083,7 @@
if (!info.mOwnedByClient) {
ALOGE("getBufferAndFormat - invalid operation "
"(the index %zu is not owned by client)", index);
+ mErrorLog.log(LOG_TAG, base::StringPrintf("index %zu is not owned by client", index));
return INVALID_OPERATION;
}
@@ -3194,6 +3211,7 @@
void MediaCodec::cancelPendingDequeueOperations() {
if (mFlags & kFlagDequeueInputPending) {
+ mErrorLog.log(LOG_TAG, "Pending dequeue input buffer request cancelled");
PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
++mDequeueInputTimeoutGeneration;
@@ -3202,6 +3220,7 @@
}
if (mFlags & kFlagDequeueOutputPending) {
+ mErrorLog.log(LOG_TAG, "Pending dequeue output buffer request cancelled");
PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
++mDequeueOutputTimeoutGeneration;
@@ -3211,8 +3230,16 @@
}
bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
- if (!isExecuting() || (mFlags & kFlagIsAsync)
- || (newRequest && (mFlags & kFlagDequeueInputPending))) {
+ if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid to call %s; only valid in executing state",
+ apiStateString().c_str()));
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ } else if (mFlags & kFlagIsAsync) {
+ mErrorLog.log(LOG_TAG, "Invalid to call in async mode");
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ } else if (newRequest && (mFlags & kFlagDequeueInputPending)) {
+ mErrorLog.log(LOG_TAG, "Invalid to call while another dequeue input request is pending");
PostReplyWithError(replyID, INVALID_OPERATION);
return true;
} else if (mFlags & kFlagStickyError) {
@@ -3235,8 +3262,16 @@
}
bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
- if (!isExecuting() || (mFlags & kFlagIsAsync)
- || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
+ if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid to call %s; only valid in executing state",
+ apiStateString().c_str()));
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ } else if (mFlags & kFlagIsAsync) {
+ mErrorLog.log(LOG_TAG, "Invalid to call in async mode");
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ } else if (newRequest && (mFlags & kFlagDequeueOutputPending)) {
+ mErrorLog.log(LOG_TAG, "Invalid to call while another dequeue output request is pending");
PostReplyWithError(replyID, INVALID_OPERATION);
} else if (mFlags & kFlagStickyError) {
PostReplyWithError(replyID, getStickyError());
@@ -4027,6 +4062,9 @@
// callback can't be set after codec is executing,
// or before it's initialized (as the callback
// will be cleared when it goes to INITIALIZED)
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid to call %s; only valid at Initialized state",
+ apiStateString().c_str()));
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4058,6 +4096,9 @@
case kWhatConfigure:
{
if (mState != INITIALIZED) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "configure() is valid only at Initialized state; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(msg, INVALID_OPERATION);
break;
}
@@ -4115,6 +4156,8 @@
CHECK(msg->findInt32("flags", (int32_t *)&flags));
if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) {
if (!(mFlags & kFlagIsAsync)) {
+ mErrorLog.log(
+ LOG_TAG, "Block model is only valid with callback set (async mode)");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4187,9 +4230,13 @@
sp<Surface> surface = static_cast<Surface *>(obj.get());
if (mSurface == NULL) {
// do not support setting surface if it was not set
+ mErrorLog.log(LOG_TAG,
+ "Cannot set surface if the codec is not configured with "
+ "a surface already");
err = INVALID_OPERATION;
} else if (obj == NULL) {
// do not support unsetting surface
+ mErrorLog.log(LOG_TAG, "Unsetting surface is not supported");
err = BAD_VALUE;
} else {
err = connectToSurface(surface);
@@ -4220,6 +4267,9 @@
}
default:
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "setSurface() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
err = INVALID_OPERATION;
break;
}
@@ -4233,6 +4283,9 @@
{
// Must be configured, but can't have been started yet.
if (mState != CONFIGURED) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "setInputSurface() is valid only at Configured state; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(msg, INVALID_OPERATION);
break;
}
@@ -4268,6 +4321,9 @@
PostReplyWithError(msg, OK);
break;
} else if (mState != CONFIGURED) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "start() is valid only at Configured state; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(msg, INVALID_OPERATION);
break;
}
@@ -4345,6 +4401,7 @@
if (mFlags & kFlagIsAsync) {
onError(DEAD_OBJECT, ACTION_CODE_FATAL);
}
+ mErrorLog.log(LOG_TAG, "Released by resource manager");
mReleasedByResourceManager = true;
}
@@ -4381,6 +4438,7 @@
// the previous stop/release completes and then reply with OK.
status_t err = mState == targetState ? OK : INVALID_OPERATION;
response->setInt32("err", err);
+ // TODO: mErrorLog
if (err == OK && targetState == UNINITIALIZED) {
mComponentName.clear();
}
@@ -4489,13 +4547,13 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (mFlags & kFlagIsAsync) {
- ALOGE("dequeueInputBuffer can't be used in async mode");
+ mErrorLog.log(LOG_TAG, "dequeueInputBuffer can't be used in async mode");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
if (mHaveInputSurface) {
- ALOGE("dequeueInputBuffer can't be used with input surface");
+ mErrorLog.log(LOG_TAG, "dequeueInputBuffer can't be used with input surface");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4550,6 +4608,9 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "queueInputBuffer() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4577,7 +4638,7 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (mFlags & kFlagIsAsync) {
- ALOGE("dequeueOutputBuffer can't be used in async mode");
+ mErrorLog.log(LOG_TAG, "dequeueOutputBuffer can't be used in async mode");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4632,6 +4693,9 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "releaseOutputBuffer() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4655,7 +4719,15 @@
case kWhatSignalEndOfInputStream:
{
- if (!isExecuting() || !mHaveInputSurface) {
+ if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "signalEndOfInputStream() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
+ PostReplyWithError(msg, INVALID_OPERATION);
+ break;
+ } else if (!mHaveInputSurface) {
+ mErrorLog.log(
+ LOG_TAG, "signalEndOfInputStream() called without an input surface set");
PostReplyWithError(msg, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4679,7 +4751,14 @@
{
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- if (!isExecuting() || (mFlags & kFlagIsAsync)) {
+ if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "getInput/OutputBuffers() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ break;
+ } else if (mFlags & kFlagIsAsync) {
+ mErrorLog.log(LOG_TAG, "getInput/OutputBuffers() is not supported with callbacks");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4712,6 +4791,9 @@
case kWhatFlush:
{
if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "flush() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(msg, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4751,10 +4833,17 @@
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- if ((mState != CONFIGURED && mState != STARTING &&
- mState != STARTED && mState != FLUSHING &&
- mState != FLUSHED)
- || format == NULL) {
+ if (mState != CONFIGURED && mState != STARTING &&
+ mState != STARTED && mState != FLUSHING &&
+ mState != FLUSHED) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "getInput/OutputFormat() is valid at Executing states "
+ "and Configured state; currently %s",
+ apiStateString().c_str()));
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ break;
+ } else if (format == NULL) {
+ mErrorLog.log(LOG_TAG, "Fatal error: format is not initialized");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4789,6 +4878,7 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (mComponentName.empty()) {
+ mErrorLog.log(LOG_TAG, "Fatal error: name is not set");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4956,7 +5046,7 @@
size_t i = 0;
for (;;) {
sp<ABuffer> csd;
- if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
+ if (!format->findBuffer(base::StringPrintf("csd-%zu", i).c_str(), &csd)) {
break;
}
if (csd->size() == 0) {
@@ -4991,7 +5081,7 @@
}
sDealer = new MemoryDealer(
newDealerCapacity,
- AStringPrintf("CSD(%dMB)", newDealerCapacity / 1048576).c_str());
+ base::StringPrintf("CSD(%zuMB)", newDealerCapacity / 1048576).c_str());
mem = sDealer->allocate(csd->size());
}
memcpy(mem->unsecurePointer(), csd->data(), csd->size());
@@ -5002,9 +5092,14 @@
FetchLinearBlock(csd->size(), {std::string{mComponentName.c_str()}});
C2WriteView view{block->map().get()};
if (view.error() != C2_OK) {
+ mErrorLog.log(LOG_TAG, "Fatal error: failed to allocate and map a block");
return -EINVAL;
}
if (csd->size() > view.capacity()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: allocated block is too small "
+ "(csd size %zu; block cap %u)",
+ csd->size(), view.capacity()));
return -EINVAL;
}
memcpy(view.base(), csd->data(), csd->size());
@@ -5015,10 +5110,16 @@
const sp<MediaCodecBuffer> &codecInputData = info.mData;
if (csd->size() > codecInputData->capacity()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "CSD is too large to fit in input buffer "
+ "(csd size %zu; buffer cap %zu)",
+ csd->size(), codecInputData->capacity()));
return -EINVAL;
}
if (codecInputData->data() == NULL) {
ALOGV("Input buffer %zu is not properly allocated", bufferIndex);
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: input buffer %zu is not properly allocated", bufferIndex));
return -EINVAL;
}
@@ -5071,6 +5172,7 @@
mActivityNotify.clear();
mCallback.clear();
+ mErrorLog.clear();
}
if (newState == UNINITIALIZED) {
@@ -5191,6 +5293,7 @@
if (!hasCryptoOrDescrambler()) {
ALOGE("[%s] queuing secure buffer without mCrypto or mDescrambler!",
mComponentName.c_str());
+ mErrorLog.log(LOG_TAG, "queuing secure buffer without mCrypto or mDescrambler!");
return -EINVAL;
}
@@ -5214,6 +5317,8 @@
}
if (index >= mPortBuffers[kPortIndexInput].size()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "index out of range (index=%zu)", mPortBuffers[kPortIndexInput].size()));
return -ERANGE;
}
@@ -5234,6 +5339,7 @@
memory, (mFlags & kFlagIsSecure), key, iv, mode, pattern,
offset, subSamples, numSubSamples, buffer);
} else {
+ mErrorLog.log(LOG_TAG, "Fatal error: invalid queue request without a buffer");
err = UNKNOWN_ERROR;
}
@@ -5256,17 +5362,28 @@
offset = buffer->offset();
size = buffer->size();
if (err != OK) {
- ALOGI("block model buffer attach failed: err = %s (%d)",
+ ALOGE("block model buffer attach failed: err = %s (%d)",
StrMediaError(err).c_str(), err);
return err;
}
}
- if (buffer == nullptr || !info->mOwnedByClient) {
+ if (buffer == nullptr) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: failed to fetch buffer for index %zu", index));
+ return -EACCES;
+ }
+ if (!info->mOwnedByClient) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "client does not own the buffer #%zu", index));
return -EACCES;
}
if (offset + size > buffer->capacity()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "buffer offset and size goes beyond the capacity: "
+ "offset=%zu, size=%zu, cap=%zu",
+ offset, size, buffer->capacity()));
return -EINVAL;
}
@@ -5371,8 +5488,8 @@
if (it->getRenderTimeNs() < 0) {
continue; // dropped frame from tracking
}
- msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
- msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
+ msg->setInt64(base::StringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
+ msg->setInt64(base::StringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
++index;
}
return index;
@@ -5388,16 +5505,28 @@
}
if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "releaseOutputBuffer() is valid at Executing states; currently %s",
+ apiStateString().c_str()));
return -EINVAL;
}
if (index >= mPortBuffers[kPortIndexOutput].size()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "index out of range (index=%zu)", mPortBuffers[kPortIndexOutput].size()));
return -ERANGE;
}
BufferInfo *info = &mPortBuffers[kPortIndexOutput][index];
- if (info->mData == nullptr || !info->mOwnedByClient) {
+ if (!info->mOwnedByClient) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "client does not own the buffer #%zu", index));
+ return -EACCES;
+ }
+ if (info->mData == nullptr) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: null buffer for index %zu", index));
return -EACCES;
}
@@ -5464,7 +5593,7 @@
status_t err = mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
if (err == NO_INIT) {
- ALOGE("rendering to non-initilized(obsolete) surface");
+ mErrorLog.log(LOG_TAG, "rendering to non-initialized(obsolete) surface");
return err;
}
if (err != OK) {
@@ -5737,12 +5866,14 @@
memcpy(csd->data() + 4, nalStart, nalSize);
mOutputFormat->setBuffer(
- AStringPrintf("csd-%u", csdIndex).c_str(), csd);
+ base::StringPrintf("csd-%u", csdIndex).c_str(), csd);
++csdIndex;
}
if (csdIndex != 2) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "codec config data contains %u NAL units; expected 2.", csdIndex));
return ERROR_MALFORMED;
}
} else {
@@ -5784,6 +5915,32 @@
mDeferredMessages.clear();
}
+std::string MediaCodec::apiStateString() {
+ const char *rval = NULL;
+ char rawbuffer[16]; // room for "%d"
+
+ switch (mState) {
+ case UNINITIALIZED:
+ rval = (mFlags & kFlagStickyError) ? "at Error state" : "at Released state";
+ break;
+ case INITIALIZING: rval = "while constructing"; break;
+ case INITIALIZED: rval = "at Uninitialized state"; break;
+ case CONFIGURING: rval = "during configure()"; break;
+ case CONFIGURED: rval = "at Configured state"; break;
+ case STARTING: rval = "during start()"; break;
+ case STARTED: rval = "at Running state"; break;
+ case FLUSHING: rval = "during flush()"; break;
+ case FLUSHED: rval = "at Flushed state"; break;
+ case STOPPING: rval = "during stop()"; break;
+ case RELEASING: rval = "during release()"; break;
+ default:
+ snprintf(rawbuffer, sizeof(rawbuffer), "at %d", mState);
+ rval = rawbuffer;
+ break;
+ }
+ return rval;
+}
+
std::string MediaCodec::stateString(State state) {
const char *rval = NULL;
char rawbuffer[16]; // room for "%d"
diff --git a/media/libstagefright/include/media/stagefright/CodecErrorLog.h b/media/libstagefright/include/media/stagefright/CodecErrorLog.h
new file mode 100644
index 0000000..673117a
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/CodecErrorLog.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC_ERROR_LOG_H_
+
+#define CODEC_ERROR_LOG_H_
+
+#include <sstream>
+#include <string>
+
+#include <android-base/thread_annotations.h>
+
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+/**
+ * CodecErrorLog gathers what happened during codec failures, and make them
+ * available to clients for debugging purpose.
+ */
+class CodecErrorLog {
+public:
+ CodecErrorLog() = default;
+
+ /**
+ * Log a line of message.
+ *
+ * \note the message should be readable to developers who may not be
+ * familiar with MediaCodec internals
+ */
+ void log(const char *tag, const char *message);
+ void log(const char *tag, const std::string &message);
+
+ /**
+ * Extract the accumulated log as string. This operation clears the log.
+ */
+ std::string extract();
+
+ /**
+ * Clears the previous log.
+ */
+ void clear();
+
+private:
+ mutable std::mutex mLock;
+ std::stringstream mStream GUARDED_BY(mLock);
+};
+
+} // namespace android
+
+#endif // CODEC_ERROR_LOG_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 29b196f..ec2d13b 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -28,6 +28,7 @@
#include <media/MediaMetrics.h>
#include <media/MediaProfiles.h>
#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/CodecErrorLog.h>
#include <media/stagefright/FrameRenderTracker.h>
#include <utils/Vector.h>
@@ -297,6 +298,8 @@
T value;
};
+ inline CodecErrorLog &getErrorLog() { return mErrorLog; }
+
protected:
virtual ~MediaCodec();
virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -321,6 +324,7 @@
RELEASING,
};
std::string stateString(State state);
+ std::string apiStateString();
enum {
kPortIndexInput = 0,
@@ -692,6 +696,8 @@
std::function<status_t(const AString &, sp<MediaCodecInfo> *)> mGetCodecInfo;
friend class MediaTestHelper;
+ CodecErrorLog mErrorLog;
+
DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
};
diff --git a/media/libstagefright/tests/HEVC/Android.bp b/media/libstagefright/tests/HEVC/Android.bp
index 7f2ff12..7a0ba52 100644
--- a/media/libstagefright/tests/HEVC/Android.bp
+++ b/media/libstagefright/tests/HEVC/Android.bp
@@ -56,7 +56,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest.zip?unzip=true",
- ],
}
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
index 20ebe44..a067284 100644
--- a/media/libstagefright/tests/extractorFactory/Android.bp
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -66,7 +66,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true",
- ],
}
diff --git a/media/libstagefright/timedtext/test/Android.bp b/media/libstagefright/timedtext/test/Android.bp
index 953da79..ae97c50 100644
--- a/media/libstagefright/timedtext/test/Android.bp
+++ b/media/libstagefright/timedtext/test/Android.bp
@@ -62,7 +62,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest.zip?unzip=true",
- ],
}
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
index b81f27e..58aa7cd 100644
--- a/media/libstagefright/writer_fuzzers/Android.bp
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -57,6 +57,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers target the APIs of all the various writers",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrnb/dec/test/Android.bp b/media/module/codecs/amrnb/dec/test/Android.bp
index de69cfc..74258e0 100644
--- a/media/module/codecs/amrnb/dec/test/Android.bp
+++ b/media/module/codecs/amrnb/dec/test/Android.bp
@@ -58,7 +58,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/amrnb/enc/fuzzer/Android.bp b/media/module/codecs/amrnb/enc/fuzzer/Android.bp
index 2c041b7..bcbcee2 100644
--- a/media/module/codecs/amrnb/enc/fuzzer/Android.bp
+++ b/media/module/codecs/amrnb/enc/fuzzer/Android.bp
@@ -48,5 +48,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_amrnbenc library",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrnb/enc/test/Android.bp b/media/module/codecs/amrnb/enc/test/Android.bp
index 5871486..7e393e3 100644
--- a/media/module/codecs/amrnb/enc/test/Android.bp
+++ b/media/module/codecs/amrnb/enc/test/Android.bp
@@ -58,7 +58,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/amrnb/fuzzer/Android.bp b/media/module/codecs/amrnb/fuzzer/Android.bp
index 833a7ba..3f29267 100644
--- a/media/module/codecs/amrnb/fuzzer/Android.bp
+++ b/media/module/codecs/amrnb/fuzzer/Android.bp
@@ -48,5 +48,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_amrnbdec library",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrwb/dec/fuzzer/Android.bp b/media/module/codecs/amrwb/dec/fuzzer/Android.bp
index 16f08fa..31a20ff 100644
--- a/media/module/codecs/amrwb/dec/fuzzer/Android.bp
+++ b/media/module/codecs/amrwb/dec/fuzzer/Android.bp
@@ -48,5 +48,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_amrwbdec library",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrwb/dec/test/Android.bp b/media/module/codecs/amrwb/dec/test/Android.bp
index 7ea39ef..7d0c964 100644
--- a/media/module/codecs/amrwb/dec/test/Android.bp
+++ b/media/module/codecs/amrwb/dec/test/Android.bp
@@ -57,7 +57,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/amrwb/enc/fuzzer/Android.bp b/media/module/codecs/amrwb/enc/fuzzer/Android.bp
index f74fa4f..c2c13e1 100644
--- a/media/module/codecs/amrwb/enc/fuzzer/Android.bp
+++ b/media/module/codecs/amrwb/enc/fuzzer/Android.bp
@@ -48,5 +48,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_amrwbenc library",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrwb/enc/test/Android.bp b/media/module/codecs/amrwb/enc/test/Android.bp
index f095d62..942f6c9 100644
--- a/media/module/codecs/amrwb/enc/test/Android.bp
+++ b/media/module/codecs/amrwb/enc/test/Android.bp
@@ -57,7 +57,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/g711/fuzzer/Android.bp b/media/module/codecs/g711/fuzzer/Android.bp
index 376cce7..397fb9a 100644
--- a/media/module/codecs/g711/fuzzer/Android.bp
+++ b/media/module/codecs/g711/fuzzer/Android.bp
@@ -44,6 +44,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of codecs_g711dec library with a special focus on Alaw APIs",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
@@ -61,5 +69,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of codecs_g711dec library with a special focus on Mlaw APIs",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/m4v_h263/dec/test/Android.bp b/media/module/codecs/m4v_h263/dec/test/Android.bp
index 9dc756c..d8de569 100644
--- a/media/module/codecs/m4v_h263/dec/test/Android.bp
+++ b/media/module/codecs/m4v_h263/dec/test/Android.bp
@@ -76,7 +76,4 @@
],
cfi: true,
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.1.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/m4v_h263/enc/test/Android.bp b/media/module/codecs/m4v_h263/enc/test/Android.bp
index d75e2d1..2b5e49c 100644
--- a/media/module/codecs/m4v_h263/enc/test/Android.bp
+++ b/media/module/codecs/m4v_h263/enc/test/Android.bp
@@ -55,7 +55,4 @@
],
cfi: true,
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/m4v_h263/fuzzer/Android.bp b/media/module/codecs/m4v_h263/fuzzer/Android.bp
index a052c11..4d0ed18 100644
--- a/media/module/codecs/m4v_h263/fuzzer/Android.bp
+++ b/media/module/codecs/m4v_h263/fuzzer/Android.bp
@@ -50,6 +50,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers target the APIs of libstagefright_m4vh263dec library",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
@@ -98,6 +106,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers target the APIs of libstagefright_m4vh263enc library",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/mp3dec/fuzzer/Android.bp b/media/module/codecs/mp3dec/fuzzer/Android.bp
index 514a8a8..c5e0b1f 100644
--- a/media/module/codecs/mp3dec/fuzzer/Android.bp
+++ b/media/module/codecs/mp3dec/fuzzer/Android.bp
@@ -44,5 +44,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_mp3dec",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/mp3dec/test/Android.bp b/media/module/codecs/mp3dec/test/Android.bp
index dd06bdc..f10b6ae 100644
--- a/media/module/codecs/mp3dec/test/Android.bp
+++ b/media/module/codecs/mp3dec/test/Android.bp
@@ -56,7 +56,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true",
- ],
}
diff --git a/media/module/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
index b3e34d2..91ca7b1 100644
--- a/media/module/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -72,6 +72,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers targets the APIs of all the various extractors",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/extractors/tests/Android.bp b/media/module/extractors/tests/Android.bp
index f5eadbd..d6e79c7 100644
--- a/media/module/extractors/tests/Android.bp
+++ b/media/module/extractors/tests/Android.bp
@@ -100,7 +100,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.4.zip?unzip=true",
- ],
}
diff --git a/media/module/foundation/tests/OpusHeader/Android.bp b/media/module/foundation/tests/OpusHeader/Android.bp
index f052650..fa2b40e 100644
--- a/media/module/foundation/tests/OpusHeader/Android.bp
+++ b/media/module/foundation/tests/OpusHeader/Android.bp
@@ -54,7 +54,4 @@
],
cfi: true,
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true",
- ],
}
diff --git a/media/module/id3/test/Android.bp b/media/module/id3/test/Android.bp
index 0481e48..52cdfa5 100644
--- a/media/module/id3/test/Android.bp
+++ b/media/module/id3/test/Android.bp
@@ -57,7 +57,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true",
- ],
}
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/Android.bp b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
index f98b27d..459f0ae 100644
--- a/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
@@ -26,25 +26,16 @@
name: "MediaTranscoderBenchmark",
srcs: ["MediaTranscoderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
- ],
}
cc_test {
name: "MediaSampleReaderBenchmark",
srcs: ["MediaSampleReaderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
- ],
}
cc_test {
name: "MediaTrackTranscoderBenchmark",
srcs: ["MediaTrackTranscoderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
- ],
}
diff --git a/media/module/mpeg2ts/test/Android.bp b/media/module/mpeg2ts/test/Android.bp
index 4b1bacd..34a8d3e 100644
--- a/media/module/mpeg2ts/test/Android.bp
+++ b/media/module/mpeg2ts/test/Android.bp
@@ -74,7 +74,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true",
- ],
}
diff --git a/media/utils/include/mediautils/MethodStatistics.h b/media/utils/include/mediautils/MethodStatistics.h
index 6d7e990..c8b36d8 100644
--- a/media/utils/include/mediautils/MethodStatistics.h
+++ b/media/utils/include/mediautils/MethodStatistics.h
@@ -59,7 +59,7 @@
void event(C&& code, FloatType executeMs) {
std::lock_guard lg(mLock);
auto it = mStatisticsMap.lower_bound(code);
- if (it != mStatisticsMap.end() && it->first == code) {
+ if (it != mStatisticsMap.end() && it->first == static_cast<Code>(code)) {
it->second.add(executeMs);
} else {
// StatsType ctor takes an optional array of data for initialization.
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 6d4c3a3..f1797e6 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -19,11 +19,127 @@
],
}
+tidy_errors = [
+ // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+ // For many categories, the checks are too many to specify individually.
+ // Feel free to disable as needed - as warnings are generally ignored,
+ // we treat warnings as errors.
+ "android-*",
+ "bugprone-*",
+ "cert-*",
+ "clang-analyzer-security*",
+ "google-*",
+ "misc-*",
+ //"modernize-*", // explicitly list the modernize as they can be subjective.
+ "modernize-avoid-bind",
+ //"modernize-avoid-c-arrays", // std::array<> can be verbose
+ "modernize-concat-nested-namespaces",
+ //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+ "modernize-deprecated-ios-base-aliases",
+ "modernize-loop-convert",
+ "modernize-make-shared",
+ "modernize-make-unique",
+ // "modernize-pass-by-value",
+ "modernize-raw-string-literal",
+ "modernize-redundant-void-arg",
+ "modernize-replace-auto-ptr",
+ "modernize-replace-random-shuffle",
+ "modernize-return-braced-init-list",
+ "modernize-shrink-to-fit",
+ "modernize-unary-static-assert",
+ // "modernize-use-auto", // found in MediaMetricsService.h, debatable - auto can obscure type
+ "modernize-use-bool-literals",
+ "modernize-use-default-member-init",
+ "modernize-use-emplace",
+ "modernize-use-equals-default",
+ "modernize-use-equals-delete",
+ // "modernize-use-nodiscard",
+ "modernize-use-noexcept",
+ "modernize-use-nullptr",
+ "modernize-use-override",
+ //"modernize-use-trailing-return-type", // not necessarily more readable
+ "modernize-use-transparent-functors",
+ "modernize-use-uncaught-exceptions",
+ "modernize-use-using",
+ "performance-*",
+
+ // Remove some pedantic stylistic requirements.
+ "-google-readability-casting", // C++ casts not always necessary and may be verbose
+ "-google-readability-todo", // do not require TODO(info)
+
+ "-bugprone-unhandled-self-assignment",
+ "-bugprone-suspicious-string-compare",
+ "-cert-oop54-cpp", // found in TransactionLog.h
+ "-bugprone-narrowing-conversions", // b/182410845
+
+ // TODO(b/275642749) Reenable these warnings
+ "-bugprone-assignment-in-if-condition",
+ "-bugprone-forward-declaration-namespace",
+ "-bugprone-parent-virtual-call",
+ "-cert-dcl59-cpp",
+ "-cert-err34-c",
+ "-google-build-namespaces",
+ "-google-build-using-namespace",
+ "-google-default-arguments",
+ "-google-runtime-int",
+ "-misc-const-correctness",
+ "-misc-non-private-member-variables-in-classes",
+ "-modernize-concat-nested-namespaces",
+ "-modernize-loop-convert",
+ "-modernize-use-default-member-init",
+ "-modernize-use-equals-default",
+ "-modernize-use-nullptr",
+ "-modernize-use-override",
+ "-modernize-use-using",
+ "-performance-no-int-to-ptr",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+ name: "audioflinger_flags_defaults",
+ // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
+ cflags: [
+ "-Wall",
+ "-Wdeprecated",
+ "-Werror",
+ "-Werror=implicit-fallthrough",
+ "-Werror=sometimes-uninitialized",
+ "-Werror=conditional-uninitialized",
+ "-Wextra",
+
+ // suppress some warning chatter.
+ "-Wno-deprecated-copy-with-dtor",
+ "-Wno-deprecated-copy-with-user-provided-dtor",
+
+ "-Wredundant-decls",
+ "-Wshadow",
+ "-Wstrict-aliasing",
+ "-fstrict-aliasing",
+ "-Wthread-safety",
+ //"-Wthread-safety-negative", // experimental - looks broken in R.
+ "-Wunreachable-code",
+ "-Wunreachable-code-break",
+ "-Wunreachable-code-return",
+ "-Wunused",
+ "-Wused-but-marked-unused",
+ "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
+ ],
+ // https://clang.llvm.org/extra/clang-tidy/
+ tidy: true,
+ tidy_checks: tidy_errors,
+ tidy_checks_as_errors: tidy_errors,
+ tidy_flags: [
+ "-format-style=file",
+ ],
+}
+
cc_library_shared {
name: "libaudioflinger",
defaults: [
"latest_android_media_audio_common_types_cpp_shared",
+ "audioflinger_flags_defaults",
],
srcs: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ba7c6b6..2ef4feb 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -229,6 +229,7 @@
BINDER_METHOD_ENTRY(getAAudioMixerBurstCount) \
BINDER_METHOD_ENTRY(getAAudioHardwareBurstMinUsec) \
BINDER_METHOD_ENTRY(setDeviceConnectedState) \
+BINDER_METHOD_ENTRY(setSimulateDeviceConnections) \
BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
BINDER_METHOD_ENTRY(setBluetoothVariableLatencyEnabled) \
@@ -499,6 +500,25 @@
return final_result;
}
+status_t AudioFlinger::setSimulateDeviceConnections(bool enabled) {
+ bool at_least_one_succeeded = false;
+ status_t last_error = INVALID_OPERATION;
+ Mutex::Autolock _l(mLock);
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_SET_SIMULATE_CONNECTIONS;
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
+ status_t result = dev->setSimulateDeviceConnections(enabled);
+ if (result == OK) {
+ at_least_one_succeeded = true;
+ } else {
+ last_error = result;
+ }
+ }
+ mHardwareStatus = AUDIO_HW_IDLE;
+ return at_least_one_succeeded ? OK : last_error;
+}
+
// getDefaultVibratorInfo_l must be called with AudioFlinger lock held.
std::optional<media::AudioVibratorInfo> AudioFlinger::getDefaultVibratorInfo_l() {
if (mAudioVibratorInfos.empty()) {
@@ -694,7 +714,7 @@
}
status_t AudioFlinger::addEffectToHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
AutoMutex lock(mHardwareLock);
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
if (audioHwDevice == nullptr) {
@@ -704,7 +724,7 @@
}
status_t AudioFlinger::removeEffectFromHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
AutoMutex lock(mHardwareLock);
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
if (audioHwDevice == nullptr) {
@@ -822,6 +842,7 @@
}
status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
if (!dumpAllowed()) {
dumpPermissionDenial(fd, args);
@@ -924,7 +945,6 @@
// to lookup the service if it's not running, as it will block for a second
if (sMediaLogServiceAsBinder != 0) {
dprintf(fd, "\nmedia.log:\n");
- Vector<String16> args;
sMediaLogServiceAsBinder->dump(fd, args);
}
@@ -1421,8 +1441,9 @@
if (NO_ERROR == ret) {
Mutex::Autolock _l(mLock);
mMode = mode;
- for (size_t i = 0; i < mPlaybackThreads.size(); i++)
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->setMode(mode);
+ }
}
mediametrics::LogItem(mMetricsId)
@@ -1760,7 +1781,7 @@
// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
void AudioFlinger::forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
- std::function<bool(const sp<PlaybackThread>&)> useThread)
+ const std::function<bool(const sp<PlaybackThread>&)>& useThread)
{
std::vector<PatchPanel::SoftwarePatch> swPatches;
if (mPatchPanel.getDownstreamSoftwarePatches(upStream, &swPatches) != OK) return;
@@ -1776,7 +1797,7 @@
// Update downstream patches for all playback threads attached to an MSD module
void AudioFlinger::updateDownStreamPatches_l(const struct audio_patch *patch,
- const std::set<audio_io_handle_t> streams)
+ const std::set<audio_io_handle_t>& streams)
{
for (const audio_io_handle_t stream : streams) {
PlaybackThread *playbackThread = checkPlaybackThread_l(stream);
@@ -1982,24 +2003,29 @@
mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+
std::vector<audio_channel_mask_t> channelMasks = {channelMask};
- if (channelMask != AUDIO_CHANNEL_IN_MONO)
+ if (channelMask != AUDIO_CHANNEL_IN_MONO) {
channelMasks.push_back(AUDIO_CHANNEL_IN_MONO);
- if (channelMask != AUDIO_CHANNEL_IN_STEREO)
+ }
+ if (channelMask != AUDIO_CHANNEL_IN_STEREO) {
channelMasks.push_back(AUDIO_CHANNEL_IN_STEREO);
+ }
std::vector<audio_format_t> formats = {format};
- if (format != AUDIO_FORMAT_PCM_16_BIT)
+ if (format != AUDIO_FORMAT_PCM_16_BIT) {
formats.push_back(AUDIO_FORMAT_PCM_16_BIT);
+ }
std::vector<uint32_t> sampleRates = {sampleRate};
static const uint32_t SR_44100 = 44100;
static const uint32_t SR_48000 = 48000;
-
- if (sampleRate != SR_48000)
+ if (sampleRate != SR_48000) {
sampleRates.push_back(SR_48000);
- if (sampleRate != SR_44100)
+ }
+ if (sampleRate != SR_44100) {
sampleRates.push_back(SR_44100);
+ }
mHardwareStatus = AUDIO_HW_IDLE;
@@ -2468,7 +2494,7 @@
// session and move it to this thread.
sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l(thread->mLock);
+ Mutex::Autolock _l2(thread->mLock);
thread->addEffectChain_l(chain);
}
break;
@@ -2848,7 +2874,7 @@
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *halConfig,
- audio_config_base_t *mixerConfig __unused,
+ audio_config_base_t *mixerConfig,
audio_devices_t deviceType,
const String8& address,
audio_output_flags_t flags)
@@ -2970,7 +2996,6 @@
aidl2legacy_int32_t_audio_output_flags_t_mask(request.flags));
audio_io_handle_t output;
- uint32_t latencyMs;
ALOGI("openOutput() this %p, module %d Device %s, SamplingRate %d, Format %#08x, "
"Channels %#x, flags %#x",
@@ -2993,6 +3018,7 @@
sp<ThreadBase> thread = openOutput_l(module, &output, &halConfig,
&mixerConfig, deviceType, address, flags);
if (thread != 0) {
+ uint32_t latencyMs = 0;
if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
latencyMs = playbackThread->latency();
@@ -3341,7 +3367,7 @@
continue;
}
if (t->hasAudioSession(chain->sessionId()) != 0) {
- Mutex::Autolock _l(t->mLock);
+ Mutex::Autolock _l2(t->mLock);
ALOGV("closeInput() found thread %d for effect session %d",
t->id(), chain->sessionId());
t->addEffectChain_l(chain);
@@ -3546,7 +3572,8 @@
}
for (size_t i = 0; i < chains.size(); i++) {
- sp<EffectChain> ec = chains[i];
+ // clang-tidy suggests const ref
+ sp<EffectChain> ec = chains[i]; // NOLINT(performance-unnecessary-copy-initialization)
int sessionid = ec->sessionId();
sp<ThreadBase> t = ec->thread().promote();
if (t == 0) {
@@ -3715,7 +3742,7 @@
PlaybackThread *thread = primaryPlaybackThread_l();
if (thread == NULL) {
- return DeviceTypeSet();
+ return {};
}
return thread->outDeviceTypes();
@@ -4227,7 +4254,7 @@
// session and used it instead of creating a new one.
sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l(thread->mLock);
+ Mutex::Autolock _l2(thread->mLock);
thread->addEffectChain_l(chain);
}
}
@@ -4345,6 +4372,7 @@
status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
AudioFlinger::PlaybackThread *srcThread,
AudioFlinger::PlaybackThread *dstThread)
+NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
{
ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
sessionId, srcThread, dstThread);
@@ -4374,11 +4402,12 @@
// transfer all effects one by one so that new effect chain is created on new thread with
// correct buffer sizes and audio parameters and effect engines reconfigured accordingly
sp<EffectChain> dstChain;
- sp<EffectModule> effect = chain->getEffectFromId_l(0);
Vector< sp<EffectModule> > removed;
status_t status = NO_ERROR;
std::string errorString;
- while (effect != nullptr) {
+ // process effects one by one.
+ for (sp<EffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
+ effect = chain->getEffectFromId_l(0)) {
srcThread->removeEffect_l(effect);
removed.add(effect);
status = dstThread->addEffect_l(effect);
@@ -4399,7 +4428,6 @@
break;
}
}
- effect = chain->getEffectFromId_l(0);
}
size_t restored = 0;
@@ -4503,6 +4531,7 @@
}
bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
+NO_THREAD_SAFETY_ANALYSIS // thread lock for getEffectChain_l.
{
if (mGlobalEffectEnableTime != 0 &&
((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ebfe32c..9079be9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -293,6 +293,8 @@
virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected);
+ virtual status_t setSimulateDeviceConnections(bool enabled);
+
virtual status_t setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode);
@@ -328,12 +330,12 @@
static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
status_t addEffectToHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect);
status_t removeEffectFromHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect);
void updateDownStreamPatches_l(const struct audio_patch *patch,
- const std::set<audio_io_handle_t> streams);
+ const std::set<audio_io_handle_t>& streams);
std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l();
@@ -376,7 +378,7 @@
audio_session_t triggerSession,
audio_session_t listenerSession,
sync_event_callback_t callBack,
- wp<RefBase> cookie)
+ const wp<RefBase>& cookie)
: mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
mCallback(callBack), mCookie(cookie)
{}
@@ -848,7 +850,7 @@
void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
void forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
- std::function<bool(const sp<PlaybackThread>&)> useThread = nullptr);
+ const std::function<bool(const sp<PlaybackThread>&)>& useThread = nullptr);
// AudioStreamIn is immutable, so their fields are const.
// For emphasis, we could also make all pointers to them be "const *",
@@ -861,7 +863,8 @@
sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
- AudioStreamIn(AudioHwDevice *dev, sp<StreamInHalInterface> in, audio_input_flags_t flags) :
+ AudioStreamIn(AudioHwDevice *dev, const sp<StreamInHalInterface>& in,
+ audio_input_flags_t flags) :
audioHwDev(dev), stream(in), flags(flags) {}
status_t read(void *buffer, size_t bytes, size_t *read) override {
return stream->read(buffer, bytes, read);
@@ -932,6 +935,7 @@
AUDIO_HW_GET_MASTER_MUTE, // get_master_mute
AUDIO_HW_GET_MICROPHONES, // getMicrophones
AUDIO_HW_SET_CONNECTED_STATE, // setConnectedState
+ AUDIO_HW_SET_SIMULATE_CONNECTIONS, // setSimulateDeviceConnections
};
mutable hardware_call_state mHardwareStatus; // for dump only
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index 1749f3f..d071922 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -46,7 +46,7 @@
AudioHwDevice(audio_module_handle_t handle,
const char *moduleName,
- sp<DeviceHalInterface> hwDevice,
+ const sp<DeviceHalInterface>& hwDevice,
Flags flags)
: mHandle(handle)
, mModuleName(strdup(moduleName))
diff --git a/services/audioflinger/AutoPark.h b/services/audioflinger/AutoPark.h
index 9ac7b65..83f6b7d 100644
--- a/services/audioflinger/AutoPark.h
+++ b/services/audioflinger/AutoPark.h
@@ -58,4 +58,4 @@
FastThreadState::Command mPreviousCommand;
}; // class AutoPark
-} // namespace
+} // namespace android
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 3a8c1bc..8484f95 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -160,7 +160,9 @@
return status;
}
-void AudioFlinger::DeviceEffectManager::dump(int fd) {
+void AudioFlinger::DeviceEffectManager::dump(int fd)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
+{
const bool locked = dumpTryLock(mLock);
if (!locked) {
String8 result("DeviceEffectManager may be deadlocked\n");
@@ -264,7 +266,7 @@
return false;
}
-void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(sp<Command> command) {
+void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(const sp<Command>& command) {
Mutex::Autolock _l(mLock);
mCommands.push_back(command);
mWaitWorkCV.signal();
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index d2faa70..493800e 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -47,11 +47,11 @@
int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *effect);
status_t addEffectToHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId,
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
return mAudioFlinger.addEffectToHal(deviceId, hwModuleId, effect);
};
status_t removeEffectFromHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId,
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
return mAudioFlinger.removeEffectFromHal(deviceId, hwModuleId, effect);
};
@@ -73,7 +73,7 @@
RELEASE_AUDIO_PATCH,
};
- CommandThread(DeviceEffectManager& manager)
+ explicit CommandThread(DeviceEffectManager& manager)
: Thread(false), mManager(manager) {}
~CommandThread() override;
@@ -94,7 +94,7 @@
class Command: public RefBase {
public:
Command() = default;
- Command(int command, sp<CommandData> data)
+ Command(int command, const sp<CommandData>& data)
: mCommand(command), mData(data) {}
int mCommand = -1;
@@ -117,13 +117,13 @@
class ReleaseAudioPatchData : public CommandData {
public:
- ReleaseAudioPatchData(audio_patch_handle_t handle)
+ explicit ReleaseAudioPatchData(audio_patch_handle_t handle)
: mHandle(handle) {}
audio_patch_handle_t mHandle;
};
- void sendCommand(sp<Command> command);
+ void sendCommand(const sp<Command>& command);
Mutex mLock;
Condition mWaitWorkCV;
@@ -145,7 +145,7 @@
class DeviceEffectManagerCallback : public EffectCallbackInterface {
public:
- DeviceEffectManagerCallback(DeviceEffectManager *manager)
+ explicit DeviceEffectManagerCallback(DeviceEffectManager *manager)
: mManager(*manager) {}
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -176,10 +176,10 @@
size_t frameCount() const override { return 0; }
uint32_t latency() const override { return 0; }
- status_t addEffectToHal(sp<EffectHalInterface> effect __unused) override {
+ status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) override {
return NO_ERROR;
}
- status_t removeEffectFromHal(sp<EffectHalInterface> effect __unused) override {
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) override {
return NO_ERROR;
}
@@ -204,11 +204,11 @@
int newEffectId() { return mManager.audioFlinger().nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT); }
status_t addEffectToHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
return mManager.addEffectToHal(deviceId, hwModuleId, effect);
}
status_t removeEffectFromHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
return mManager.removeEffectFromHal(deviceId, hwModuleId, effect);
}
private:
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 98829d0..e912bff 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -498,6 +498,7 @@
}
void AudioFlinger::EffectBase::dump(int fd, const Vector<String16>& args __unused)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
String8 result;
@@ -1249,13 +1250,13 @@
return -EINVAL;
}
if (cmdCode == EFFECT_CMD_GET_PARAM &&
- (maxReplySize < sizeof(effect_param_t) ||
+ (maxReplySize < static_cast<signed>(sizeof(effect_param_t)) ||
param->psize > maxReplySize - sizeof(effect_param_t))) {
android_errorWriteLog(0x534e4554, "29251553");
return -EINVAL;
}
if (cmdCode == EFFECT_CMD_GET_PARAM &&
- (sizeof(effect_param_t) > maxReplySize
+ (static_cast<signed>(sizeof(effect_param_t)) > maxReplySize
|| param->psize > maxReplySize - sizeof(effect_param_t)
|| param->vsize > maxReplySize - sizeof(effect_param_t)
- param->psize
@@ -1685,6 +1686,7 @@
}
void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
EffectBase::dump(fd, args);
@@ -1939,7 +1941,7 @@
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
// Client destructor must run with AudioFlinger client mutex locked
- Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
+ Mutex::Autolock _l2(mClient->audioFlinger()->mClientLock);
mClient.clear();
}
}
@@ -2003,14 +2005,14 @@
}
if (cmdCode == EFFECT_CMD_ENABLE) {
- if (maxResponseSize < sizeof(int)) {
+ if (maxResponseSize < static_cast<signed>(sizeof(int))) {
android_errorWriteLog(0x534e4554, "32095713");
RETURN(BAD_VALUE);
}
writeToBuffer(NO_ERROR, response);
return enable(_aidl_return);
} else if (cmdCode == EFFECT_CMD_DISABLE) {
- if (maxResponseSize < sizeof(int)) {
+ if (maxResponseSize < static_cast<signed>(sizeof(int))) {
android_errorWriteLog(0x534e4554, "32095713");
RETURN(BAD_VALUE);
}
@@ -2034,7 +2036,7 @@
RETURN(INVALID_OPERATION);
}
- if (maxResponseSize < sizeof(int)) {
+ if (maxResponseSize < (signed)sizeof(int)) {
android_errorWriteLog(0x534e4554, "32095713");
RETURN(BAD_VALUE);
}
@@ -2043,7 +2045,7 @@
// No need to trylock() here as this function is executed in the binder thread serving a
// particular client process: no risk to block the whole media server process or mixer
// threads if we are stuck here
- Mutex::Autolock _l(mCblk->lock);
+ Mutex::Autolock _l2(mCblk->lock);
// keep local copy of index in case of client corruption b/32220769
const uint32_t clientIndex = mCblk->clientIndex;
const uint32_t serverIndex = mCblk->serverIndex;
@@ -2146,6 +2148,7 @@
}
void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
@@ -2400,7 +2403,7 @@
}
} else {
effect->setInBuffer(mInBuffer);
- if (idx_insert == previousSize) {
+ if (idx_insert == static_cast<ssize_t>(previousSize)) {
if (idx_insert != 0) {
mEffects[idx_insert-1]->configure();
mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
@@ -2460,7 +2463,7 @@
}
// remember position of first insert effect and by default
// select this as insert position for new effect
- if (idx_insert == size) {
+ if (idx_insert == static_cast<ssize_t>(size)) {
idx_insert = i;
}
// remember position of last insert effect claiming
@@ -2690,6 +2693,7 @@
}
void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
String8 result;
@@ -3027,7 +3031,7 @@
}
status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
status_t result = NO_INIT;
sp<ThreadBase> t = thread().promote();
if (t == nullptr) {
@@ -3043,7 +3047,7 @@
}
status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
status_t result = NO_INIT;
sp<ThreadBase> t = thread().promote();
if (t == nullptr) {
@@ -3185,15 +3189,20 @@
return t->frameCount();
}
-uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const {
+uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const
+NO_THREAD_SAFETY_ANALYSIS // latency_l() access
+{
sp<ThreadBase> t = thread().promote();
if (t == nullptr) {
return 0;
}
+ // TODO(b/275956781) - this requires the thread lock.
return t->latency_l();
}
-void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const {
+void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
+NO_THREAD_SAFETY_ANALYSIS // setVolumeForOutput_l() access
+{
sp<ThreadBase> t = thread().promote();
if (t == nullptr) {
return;
@@ -3437,7 +3446,7 @@
}
status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
if (mHalEffect == nullptr) {
return NO_INIT;
}
@@ -3446,7 +3455,7 @@
}
status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
if (mHalEffect == nullptr) {
return NO_INIT;
}
@@ -3484,7 +3493,9 @@
return audio_channel_count_from_in_mask(channelMask());
}
-void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces) {
+void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
+{
const Vector<String16> args;
EffectBase::dump(fd, args);
@@ -3563,7 +3574,7 @@
}
status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return NO_INIT;
@@ -3572,7 +3583,7 @@
}
status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return NO_INIT;
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 78788df..bad86bc 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -45,8 +45,8 @@
// Non trivial methods usually implemented with help from ThreadBase:
// pay attention to mutex locking order
virtual uint32_t latency() const { return 0; }
- virtual status_t addEffectToHal(sp<EffectHalInterface> effect) = 0;
- virtual status_t removeEffectFromHal(sp<EffectHalInterface> effect) = 0;
+ virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+ virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
virtual void setVolumeForOutput(float left, float right) const = 0;
virtual bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) = 0;
virtual void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
@@ -159,8 +159,8 @@
bool isPinned() const { return mPinned; }
void unPin() { mPinned = false; }
- void lock() { mLock.lock(); }
- void unlock() { mLock.unlock(); }
+ void lock() ACQUIRE(mLock) { mLock.lock(); }
+ void unlock() RELEASE(mLock) { mLock.unlock(); }
status_t updatePolicyState();
@@ -459,10 +459,10 @@
void process_l();
- void lock() {
+ void lock() ACQUIRE(mLock) {
mLock.lock();
}
- void unlock() {
+ void unlock() RELEASE(mLock) {
mLock.unlock();
}
@@ -605,8 +605,8 @@
size_t frameCount() const override;
uint32_t latency() const override;
- status_t addEffectToHal(sp<EffectHalInterface> effect) override;
- status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+ status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
void setVolumeForOutput(float left, float right) const override;
@@ -721,8 +721,8 @@
size_t removeEffect(const sp<EffectModule>& effect);
- status_t addEffectToHal(sp<EffectHalInterface> effect);
- status_t removeEffectFromHal(sp<EffectHalInterface> effect);
+ status_t addEffectToHal(const sp<EffectHalInterface>& effect);
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& effect);
const AudioDeviceTypeAddr& device() { return mDevice; };
bool isOutput() const;
@@ -766,8 +766,8 @@
size_t frameCount() const override { return 0; }
uint32_t latency() const override { return 0; }
- status_t addEffectToHal(sp<EffectHalInterface> effect) override;
- status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+ status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
void setVolumeForOutput(float left __unused, float right __unused) const override {}
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/FastCaptureDumpState.cpp
index b8b3866..243dfa5 100644
--- a/services/audioflinger/FastCaptureDumpState.cpp
+++ b/services/audioflinger/FastCaptureDumpState.cpp
@@ -51,4 +51,4 @@
periodSec * 1e3, mSilenced ? "true" : "false");
}
-} // android
+} // namespace android
diff --git a/services/audioflinger/FastCaptureDumpState.h b/services/audioflinger/FastCaptureDumpState.h
index a1b8706..34ce456 100644
--- a/services/audioflinger/FastCaptureDumpState.h
+++ b/services/audioflinger/FastCaptureDumpState.h
@@ -38,6 +38,6 @@
bool mSilenced = false; // capture is silenced
};
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
diff --git a/services/audioflinger/FastCaptureState.cpp b/services/audioflinger/FastCaptureState.cpp
index c4d5e45..918ba9c 100644
--- a/services/audioflinger/FastCaptureState.cpp
+++ b/services/audioflinger/FastCaptureState.cpp
@@ -42,4 +42,4 @@
LOG_ALWAYS_FATAL("%s", __func__);
}
-} // android
+} // namespace android
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/FastMixerDumpState.cpp
index 3f20282..d041882 100644
--- a/services/audioflinger/FastMixerDumpState.cpp
+++ b/services/audioflinger/FastMixerDumpState.cpp
@@ -203,4 +203,4 @@
}
}
-} // android
+} // namespace android
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/FastMixerDumpState.h
index 9b91cbc..294ef78 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/FastMixerDumpState.h
@@ -81,6 +81,6 @@
TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
};
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/FastThread.h
index 3f6b206..2f0f73f 100644
--- a/services/audioflinger/FastThread.h
+++ b/services/audioflinger/FastThread.h
@@ -92,6 +92,6 @@
}; // class FastThread
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_THREAD_H
diff --git a/services/audioflinger/FastThreadDumpState.cpp b/services/audioflinger/FastThreadDumpState.cpp
index 964a725..e91073f 100644
--- a/services/audioflinger/FastThreadDumpState.cpp
+++ b/services/audioflinger/FastThreadDumpState.cpp
@@ -56,4 +56,4 @@
}
#endif
-} // android
+} // namespace android
diff --git a/services/audioflinger/FastThreadDumpState.h b/services/audioflinger/FastThreadDumpState.h
index 1ce0914..0b20e55 100644
--- a/services/audioflinger/FastThreadDumpState.h
+++ b/services/audioflinger/FastThreadDumpState.h
@@ -67,6 +67,6 @@
}; // struct FastThreadDumpState
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
diff --git a/services/audioflinger/FastThreadState.h b/services/audioflinger/FastThreadState.h
index 54c0dc6..9fb4e06 100644
--- a/services/audioflinger/FastThreadState.h
+++ b/services/audioflinger/FastThreadState.h
@@ -50,6 +50,6 @@
static const char *commandToString(Command command);
}; // struct FastThreadState
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_THREAD_STATE_H
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 68a3800..5555766 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -199,7 +199,7 @@
return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; }
- void setThread(sp<ThreadBase> thread) { mThread = thread; }
+ void setThread(const sp<ThreadBase>& thread) { mThread = thread; }
wp<ThreadBase> thread() const { return mThread; }
// returns the latency of the patch (from record to playback).
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp
index 9d4188f..38ce2c2 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/StateQueue.cpp
@@ -187,7 +187,9 @@
} // namespace android
-// hack for gcc
+// Hack to avoid explicit template instantiation of
+// template class StateQueue<FastCaptureState>;
+// template class StateQueue<FastMixerState>;
#ifdef STATE_QUEUE_INSTANTIATIONS
-#include STATE_QUEUE_INSTANTIATIONS
+#include STATE_QUEUE_INSTANTIATIONS // NOLINT(bugprone-suspicious-include)
#endif
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 16c72cc..2821f1f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -374,7 +374,7 @@
// try three times to get the clock offset, choose the one
// with the minimum gap in measurements.
const int tries = 3;
- nsecs_t bestGap, measured;
+ nsecs_t bestGap = 0, measured = 0; // not required, initialized for clang-tidy
for (int i = 0; i < tries; ++i) {
const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
const nsecs_t tbase = systemTime(clockbase);
@@ -623,6 +623,7 @@
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from processConfigEvents_l().
status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
+NO_THREAD_SAFETY_ANALYSIS // condition variable
{
status_t status = NO_ERROR;
@@ -936,6 +937,7 @@
}
void AudioFlinger::ThreadBase::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
dprintf(fd, "\n%s thread %p, name %s, tid %d, type %d (%s):\n", isOutput() ? "Output" : "Input",
this, mThreadName, getTid(), type(), threadTypeToString(type()));
@@ -1304,7 +1306,9 @@
void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
audio_session_t sessionId,
- bool threadLocked) {
+ bool threadLocked)
+NO_THREAD_SAFETY_ANALYSIS // manual locking
+{
if (!threadLocked) {
mLock.lock();
}
@@ -1768,6 +1772,7 @@
void AudioFlinger::ThreadBase::lockEffectChains_l(
Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::lock()
{
effectChains = mEffectChains;
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -1777,6 +1782,7 @@
void AudioFlinger::ThreadBase::unlockEffectChains(
const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::unlock()
{
for (size_t i = 0; i < effectChains.size(); i++) {
effectChains[i]->unlock();
@@ -1884,7 +1890,7 @@
template <typename T>
void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState(
- sp<ThreadBase> thread, bool force) {
+ const sp<ThreadBase>& thread, bool force) {
// Updates ActiveTracks client uids to the thread wakelock.
if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
thread->updateWakeLockUids_l(getWakeLockUids());
@@ -2716,6 +2722,7 @@
// addTrack_l() must be called with ThreadBase::mLock held
status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
status_t status = ALREADY_EXISTS;
@@ -2868,7 +2875,7 @@
if (initCheck() == NO_ERROR && mOutput->stream->getParameters(keys, &out_s8) == OK) {
return out_s8;
}
- return String8();
+ return {};
}
status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
@@ -3578,10 +3585,10 @@
size_t numSamples = mNormalFrameCount
* (audio_channel_count_from_out_mask(mMixerChannelMask)
+ mHapticChannelCount);
- status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+ const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
numSamples * sizeof(effect_buffer_t),
&halInBuffer);
- if (result != OK) return result;
+ if (allocateStatus != OK) return allocateStatus;
#ifdef FLOAT_EFFECT_CHAIN
buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
#else
@@ -3667,8 +3674,8 @@
}
// detach all tracks with same session ID from this chain
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
+ for (size_t j = 0; j < mTracks.size(); ++j) {
+ sp<Track> track = mTracks[j];
if (session == track->sessionId()) {
track->setMainBuffer(reinterpret_cast<effect_buffer_t*>(mSinkBuffer));
chain->decTrackCnt();
@@ -3721,6 +3728,7 @@
}
bool AudioFlinger::PlaybackThread::threadLoop()
+NO_THREAD_SAFETY_ANALYSIS // manual locking of AudioFlinger
{
tlNBLogWriter = mNBLogWriter.get();
@@ -3789,7 +3797,7 @@
// is more informational.
if (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
std::vector<PatchPanel::SoftwarePatch> swPatches;
- double latencyMs;
+ double latencyMs = 0.; // not required; initialized for clang-tidy
status_t status = INVALID_OPERATION;
audio_patch_handle_t downstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
if (mAudioFlinger->mPatchPanel.getDownstreamSoftwarePatches(id(), &swPatches) == OK
@@ -3809,8 +3817,7 @@
ALOGVV("new downstream latency %lf ms", latencyMs);
} else {
ALOGD("out of range downstream latency %lf ms", latencyMs);
- if (latencyMs < minLatency) latencyMs = minLatency;
- else if (latencyMs > maxLatency) latencyMs = maxLatency;
+ latencyMs = std::clamp(latencyMs, minLatency, maxLatency);
}
mDownstreamLatencyStatMs.add(latencyMs);
}
@@ -4492,6 +4499,7 @@
// removeTracks_l() must be called with ThreadBase::mLock held
void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
for (const auto& track : tracksToRemove) {
mActiveTracks.remove(track);
@@ -4612,8 +4620,8 @@
"as it does not support audio patches",
patch->sinks[i].ext.device.type);
type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
- deviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
- patch->sinks[i].ext.device.address));
+ deviceTypeAddrs.emplace_back(patch->sinks[i].ext.device.type,
+ patch->sinks[i].ext.device.address);
}
audio_port_handle_t sinkPortId = patch->sinks[0].id;
@@ -4821,14 +4829,15 @@
// When it wakes up after a maximum latency, it runs a few cycles quickly before
// finally blocking. Note the pipe implementation rounds up the request to a power of 2.
MonoPipe *monoPipe = new MonoPipe(mNormalFrameCount * 4, format, true /*writeCanBlock*/);
- const NBAIO_Format offers[1] = {format};
- size_t numCounterOffers = 0;
+ const NBAIO_Format offersFast[1] = {format};
+ size_t numCounterOffersFast = 0;
#if !LOG_NDEBUG
ssize_t index =
#else
(void)
#endif
- monoPipe->negotiate(offers, 1, NULL, numCounterOffers);
+ monoPipe->negotiate(offersFast, std::size(offersFast),
+ nullptr /* counterOffers */, numCounterOffersFast);
ALOG_ASSERT(index == 0);
monoPipe->setAvgFrames((mScreenState & 1) ?
(monoPipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);
@@ -5240,7 +5249,7 @@
// tallyUnderrunFrames() is called to update the track counters
// with the number of underrun frames for a particular mixer period.
// We defer tallying until we know the final mixer status.
- void tallyUnderrunFrames(sp<Track> track, size_t underrunFrames) {
+ void tallyUnderrunFrames(const sp<Track>& track, size_t underrunFrames) {
mUnderrunFrames.emplace_back(track, underrunFrames);
}
@@ -5489,7 +5498,7 @@
// during last round
size_t desiredFrames;
const uint32_t sampleRate = track->mAudioTrackServerProxy->getSampleRate();
- AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
+ const AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
desiredFrames = sourceFramesNeededWithTimestretch(
sampleRate, mNormalFrameCount, mSampleRate, playbackRate.mSpeed);
@@ -5673,12 +5682,12 @@
AudioMixer::SAMPLE_RATE,
(void *)(uintptr_t)reqSampleRate);
- AudioPlaybackRate playbackRate = proxy->getPlaybackRate();
mAudioMixer->setParameter(
trackId,
AudioMixer::TIMESTRETCH,
AudioMixer::PLAYBACK_RATE,
- &playbackRate);
+ // cast away constness for this generic API.
+ const_cast<void *>(reinterpret_cast<const void *>(&playbackRate)));
/*
* Select the appropriate output buffer for the track.
@@ -6062,12 +6071,12 @@
mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
for (const auto &track : mTracks) {
const int trackId = track->id();
- status_t status = mAudioMixer->create(
+ const status_t createStatus = mAudioMixer->create(
trackId,
track->mChannelMask,
track->mFormat,
track->mSessionId);
- ALOGW_IF(status != NO_ERROR,
+ ALOGW_IF(createStatus != NO_ERROR,
"%s(): AudioMixer cannot create track(%d)"
" mask %#x, format %#x, sessionId %d",
__func__,
@@ -6196,12 +6205,17 @@
if (left > GAIN_FLOAT_UNITY) {
left = GAIN_FLOAT_UNITY;
}
- left *= v * mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
right = float_from_gain(gain_minifloat_unpack_right(vlr));
if (right > GAIN_FLOAT_UNITY) {
right = GAIN_FLOAT_UNITY;
}
- right *= v * mMasterBalanceRight;
+ left *= v;
+ right *= v;
+ if (mAudioFlinger->getMode() != AUDIO_MODE_IN_COMMUNICATION
+ || audio_channel_count_from_out_mask(mChannelMask) > 1) {
+ left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
+ right *= mMasterBalanceRight;
+ }
}
if (lastTrack) {
@@ -7114,7 +7128,7 @@
void AudioFlinger::DuplicatingThread::threadLoop_mix()
{
// mix buffers...
- if (outputsReady(outputTracks)) {
+ if (outputsReady()) {
mAudioMixer->process();
} else {
if (mMixerBufferValid) {
@@ -7185,7 +7199,7 @@
}
}
-void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
MixerThread::dumpInternals_l(fd, args);
@@ -7289,9 +7303,7 @@
}
}
-
-bool AudioFlinger::DuplicatingThread::outputsReady(
- const SortedVector< sp<OutputTrack> > &outputTracks)
+bool AudioFlinger::DuplicatingThread::outputsReady()
{
for (size_t i = 0; i < outputTracks.size(); i++) {
sp<ThreadBase> thread = outputTracks[i]->thread().promote();
@@ -7620,14 +7632,16 @@
// pipe will be shared directly with fast clients, so clear to avoid leaking old information
memset(pipeBuffer, 0, pipeSize);
Pipe *pipe = new Pipe(pipeFramesP2, format, pipeBuffer);
- const NBAIO_Format offers[1] = {format};
- size_t numCounterOffers = 0;
- [[maybe_unused]] ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
+ const NBAIO_Format offersFast[1] = {format};
+ size_t numCounterOffersFast = 0;
+ [[maybe_unused]] ssize_t index = pipe->negotiate(offersFast, std::size(offersFast),
+ nullptr /* counterOffers */, numCounterOffersFast);
ALOG_ASSERT(index == 0);
mPipeSink = pipe;
PipeReader *pipeReader = new PipeReader(*pipe);
- numCounterOffers = 0;
- index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
+ numCounterOffersFast = 0;
+ index = pipeReader->negotiate(offersFast, std::size(offersFast),
+ nullptr /* counterOffers */, numCounterOffersFast);
ALOG_ASSERT(index == 0);
mPipeSource = pipeReader;
mPipeFramesP2 = pipeFramesP2;
@@ -7975,7 +7989,7 @@
// copy to the right place. Permitted because mRsmpInBuffer was over-allocated.
int32_t rear = mRsmpInRear & (mRsmpInFramesP2 - 1);
- ssize_t framesRead;
+ ssize_t framesRead = 0; // not needed, remove clang-tidy warning.
const int64_t lastIoBeginNs = systemTime(); // start IO timing
// If an NBAIO source is present, use it to read the normal capture's data
@@ -8168,8 +8182,9 @@
// straight from RecordThread buffer to RecordTrack buffer.
AudioBufferProvider::Buffer buffer;
buffer.frameCount = framesOut;
- status_t status = activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
- if (status == OK && buffer.frameCount != 0) {
+ const status_t getNextBufferStatus =
+ activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
+ if (getNextBufferStatus == OK && buffer.frameCount != 0) {
ALOGV_IF(buffer.frameCount != framesOut,
"%s() read less than expected (%zu vs %zu)",
__func__, buffer.frameCount, framesOut);
@@ -8179,7 +8194,7 @@
} else {
framesOut = 0;
ALOGE("%s() cannot fill request, status: %d, frameCount: %zu",
- __func__, status, buffer.frameCount);
+ __func__, getNextBufferStatus, buffer.frameCount);
}
} else {
// process frames from the RecordThread buffer provider to the RecordTrack
@@ -8599,7 +8614,6 @@
// or using a separate command thread
recordTrack->mState = TrackBase::STARTING_1;
mActiveTracks.add(recordTrack);
- status_t status = NO_ERROR;
if (recordTrack->isExternalTrack()) {
mLock.unlock();
status = AudioSystem::startInput(recordTrack->portId());
@@ -8790,7 +8804,7 @@
// "best effort" behavior of the API.
if (sharedOffset < 0) {
sharedAudioStartFrames = mRsmpInRear;
- } else if (sharedOffset > mRsmpInFrames) {
+ } else if (sharedOffset > static_cast<signed>(mRsmpInFrames)) {
sharedAudioStartFrames =
audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
}
@@ -9165,7 +9179,7 @@
return out_s8;
}
}
- return String8();
+ return {};
}
void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
@@ -9400,7 +9414,7 @@
maxFilled = filled;
}
}
- if (maxFilled > mRsmpInFrames) {
+ if (maxFilled > static_cast<signed>(mRsmpInFrames)) {
(void)__builtin_sub_overflow(mRsmpInRear, mRsmpInFrames, &oldestFront);
}
return oldestFront;
@@ -9592,7 +9606,7 @@
AudioFlinger::MmapThread::MmapThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady, bool isOut)
+ AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady, bool isOut)
: ThreadBase(audioFlinger, id, (isOut ? MMAP_PLAYBACK : MMAP_CAPTURE), systemReady, isOut),
mSessionId(AUDIO_SESSION_NONE),
mPortId(AUDIO_PORT_HANDLE_NONE),
@@ -9797,8 +9811,10 @@
mHalVolFloat = -1.0f;
} else if (!track->isSilenced_l()) {
for (const sp<MmapTrack> &t : mActiveTracks) {
- if (t->isSilenced_l() && t->uid() != client.attributionSource.uid)
+ if (t->isSilenced_l()
+ && t->uid() != static_cast<uid_t>(client.attributionSource.uid)) {
t->invalidate();
+ }
}
}
@@ -10024,7 +10040,7 @@
if (initCheck() == NO_ERROR && mHalStream->getParameters(keys, &out_s8) == OK) {
return out_s8;
}
- return String8();
+ return {};
}
void AudioFlinger::MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
@@ -10054,6 +10070,7 @@
status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle)
+NO_THREAD_SAFETY_ANALYSIS // elease and re-acquire mLock
{
status_t status = NO_ERROR;
@@ -10071,8 +10088,8 @@
"as it does not support audio patches",
patch->sinks[i].ext.device.type);
type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
- sinkDeviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
- patch->sinks[i].ext.device.address));
+ sinkDeviceTypeAddrs.emplace_back(patch->sinks[i].ext.device.type,
+ patch->sinks[i].ext.device.address);
}
deviceId = patch->sinks[0].id;
numDevices = mPatch.num_sinks;
@@ -10275,6 +10292,7 @@
}
void AudioFlinger::MmapThread::checkInvalidTracks_l()
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
sp<MmapStreamCallback> callback;
for (const sp<MmapTrack> &track : mActiveTracks) {
@@ -10429,6 +10447,7 @@
}
void AudioFlinger::MmapPlaybackThread::processVolume_l()
+NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
{
float volume;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index ce90767..63ad4e6 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -163,7 +163,7 @@
class SetParameterConfigEventData : public ConfigEventData {
public:
- explicit SetParameterConfigEventData(String8 keyValuePairs) :
+ explicit SetParameterConfigEventData(const String8& keyValuePairs) :
mKeyValuePairs(keyValuePairs) {}
virtual void dump(char *buffer, size_t size) {
@@ -175,7 +175,7 @@
class SetParameterConfigEvent : public ConfigEvent {
public:
- explicit SetParameterConfigEvent(String8 keyValuePairs) :
+ explicit SetParameterConfigEvent(const String8& keyValuePairs) :
ConfigEvent(CFG_EVENT_SET_PARAMETER) {
mData = new SetParameterConfigEventData(keyValuePairs);
mWaitStatus = true;
@@ -789,7 +789,7 @@
// ThreadBase thread.
void clear();
// periodically called in the threadLoop() to update power state uids.
- void updatePowerState(sp<ThreadBase> thread, bool force = false);
+ void updatePowerState(const sp<ThreadBase>& thread, bool force = false);
/** @return true if one or move active tracks was added or removed since the
* last time this function was called or the vector was created.
@@ -1260,7 +1260,7 @@
template <typename T>
class Tracks {
public:
- Tracks(bool saveDeletedTrackIds) :
+ explicit Tracks(bool saveDeletedTrackIds) :
mSaveDeletedTrackIds(saveDeletedTrackIds) { }
// SortedVector methods
@@ -1289,7 +1289,7 @@
return mTracks.end();
}
- size_t processDeletedTrackIds(std::function<void(int)> f) {
+ size_t processDeletedTrackIds(const std::function<void(int)>& f) {
for (const int trackId : mDeletedTrackIds) {
f(trackId);
}
@@ -1411,7 +1411,7 @@
class IsTimestampAdvancing {
public:
// The timestamp will not be checked any faster than the specified time.
- IsTimestampAdvancing(nsecs_t minimumTimeBetweenChecksNs)
+ explicit IsTimestampAdvancing(nsecs_t minimumTimeBetweenChecksNs)
: mMinimumTimeBetweenChecksNs(minimumTimeBetweenChecksNs)
{
clear();
@@ -1700,7 +1700,7 @@
void dumpInternals_l(int fd, const Vector<String16>& args) override;
private:
- bool outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks);
+ bool outputsReady();
protected:
// threadLoop snippets
virtual void threadLoop_mix();
@@ -2066,7 +2066,7 @@
#include "MmapTracks.h"
MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady,
+ AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady,
bool isOut);
virtual ~MmapThread();
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 20bfbb0..42f7b47 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -122,7 +122,7 @@
* This may be called without the thread lock.
*/
virtual double bufferLatencyMs() const {
- return mServerProxy->framesReadySafe() * 1000 / sampleRate();
+ return mServerProxy->framesReadySafe() * 1000. / sampleRate();
}
/** returns whether the track supports server latency computation.
@@ -430,7 +430,7 @@
{
public:
using Timeout = std::optional<std::chrono::nanoseconds>;
- PatchTrackBase(sp<ClientProxy> proxy, const ThreadBase& thread,
+ PatchTrackBase(const sp<ClientProxy>& proxy, const ThreadBase& thread,
const Timeout& timeout);
void setPeerTimeout(std::chrono::nanoseconds timeout);
template <typename T>
diff --git a/services/audioflinger/TrackMetrics.h b/services/audioflinger/TrackMetrics.h
index 6fc70d6..ed3928a 100644
--- a/services/audioflinger/TrackMetrics.h
+++ b/services/audioflinger/TrackMetrics.h
@@ -113,7 +113,8 @@
mDeviceStartupMs.add(startupMs);
}
- void updateMinMaxVolume(int64_t durationNs, double deviceVolume) {
+ void updateMinMaxVolume_l(int64_t durationNs, double deviceVolume)
+ REQUIRES(mLock) {
if (deviceVolume > mMaxVolume) {
mMaxVolume = deviceVolume;
mMaxVolumeDurationNs = durationNs;
@@ -165,7 +166,7 @@
mDeviceTimeNs += durationNs;
mCumulativeTimeNs += durationNs;
}
- updateMinMaxVolume(durationNs, mVolume); // always update.
+ updateMinMaxVolume_l(durationNs, mVolume); // always update.
mVolume = volume;
mLastVolumeChangeTimeNs = timeNs;
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 300ad9f..123d5a9 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -303,7 +303,7 @@
return NO_ERROR;
}
-AudioFlinger::ThreadBase::PatchTrackBase::PatchTrackBase(sp<ClientProxy> proxy,
+AudioFlinger::ThreadBase::PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
const ThreadBase& thread,
const Timeout& timeout)
: mProxy(proxy)
@@ -1298,8 +1298,9 @@
// must be called with thread lock held
void AudioFlinger::PlaybackThread::Track::flushAck()
{
- if (!isOffloaded() && !isDirect())
+ if (!isOffloaded() && !isDirect()) {
return;
+ }
// Clear the client ring buffer so that the app can prime the buffer while paused.
// Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
@@ -1812,23 +1813,23 @@
//To be called with thread lock held
bool AudioFlinger::PlaybackThread::Track::isResumePending() {
-
- if (mState == RESUMING)
+ if (mState == RESUMING) {
return true;
+ }
/* Resume is pending if track was stopping before pause was called */
if (mState == STOPPING_1 &&
- mResumeToStopping)
+ mResumeToStopping) {
return true;
+ }
return false;
}
//To be called with thread lock held
void AudioFlinger::PlaybackThread::Track::resumeAck() {
-
-
- if (mState == RESUMING)
+ if (mState == RESUMING) {
mState = ACTIVE;
+ }
// Other possibility of pending resume is stopping_1 state
// Do not update the state from stopping as this prevents
@@ -2094,7 +2095,10 @@
if (thread != 0 && !thread->standby()) {
if (mBufferQueue.size() < kMaxOverFlowBuffers) {
pInBuffer = new Buffer;
- pInBuffer->mBuffer = malloc(inBuffer.frameCount * mFrameSize);
+ const size_t bufferSize = inBuffer.frameCount * mFrameSize;
+ pInBuffer->mBuffer = malloc(bufferSize);
+ LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
+ "%s: Unable to malloc size %zu", __func__, bufferSize);
pInBuffer->frameCount = inBuffer.frameCount;
pInBuffer->raw = pInBuffer->mBuffer;
memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
@@ -2258,7 +2262,7 @@
buf.mFrameCount = buffer->frameCount;
buf.mRaw = buffer->raw;
mPeerProxy->releaseBuffer(&buf);
- TrackBase::releaseBuffer(buffer);
+ TrackBase::releaseBuffer(buffer); // Note: this is the base class.
}
status_t AudioFlinger::PlaybackThread::PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
@@ -2872,7 +2876,7 @@
{
void *ptr = nullptr;
(void)posix_memalign(&ptr, alignment, size);
- return std::unique_ptr<void, decltype(free)*>(ptr, free);
+ return {ptr, free};
}
AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord(
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 496591a..7ad9f6c 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -245,6 +245,8 @@
unsigned int *num_ports,
struct audio_port_v7 *ports,
unsigned int *generation) = 0;
+ virtual status_t listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* result) = 0;
virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 7d21ae0..de501ee 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -162,6 +162,10 @@
DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const override;
+ void initializeDeviceSelectionCache() override;
+
+ void updateDeviceSelectionCache() override;
+
private:
/**
* Get media devices as the given role
@@ -190,6 +194,28 @@
/** current forced use configuration. */
audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT] = {};
+
+protected:
+ /**
+ * Set the device information for a given strategy.
+ *
+ * @param strategy the strategy to set devices information
+ * @param devices the devices selected for the strategy
+ */
+ virtual void setStrategyDevices(const sp<ProductStrategy>& /*strategy*/,
+ const DeviceVector& /*devices*/) {
+ // In EngineBase, do nothing. It is up to the actual engine to decide if it is needed to
+ // set devices information for the given strategy.
+ }
+
+ /**
+ * Get devices that will be used for the given product strategy.
+ *
+ * @param strategy the strategy to query
+ */
+ virtual DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const = 0;
+
+ DeviceStrategyMap mDevicesForStrategies;
};
} // namespace audio_policy
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 99507ee..83a8e4d 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -627,6 +627,26 @@
return activeDevices;
}
+void EngineBase::initializeDeviceSelectionCache() {
+ // Initializing the device selection cache with default device won't be harmful, it will be
+ // updated after the audio modules are initialized.
+ auto defaultDevices = DeviceVector(getApmObserver()->getDefaultOutputDevice());
+ for (const auto &iter : getProductStrategies()) {
+ const auto &strategy = iter.second;
+ mDevicesForStrategies[strategy->getId()] = defaultDevices;
+ setStrategyDevices(strategy, defaultDevices);
+ }
+}
+
+void EngineBase::updateDeviceSelectionCache() {
+ for (const auto &iter : getProductStrategies()) {
+ const auto& strategy = iter.second;
+ auto devices = getDevicesForProductStrategy(strategy->getId());
+ mDevicesForStrategies[strategy->getId()] = devices;
+ setStrategyDevices(strategy, devices);
+ }
+}
+
void EngineBase::dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const
{
dst->appendFormat("\n%*sDevice role per capture preset dump:", spaces, "");
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index 518f86e..57174c7 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -421,6 +421,16 @@
*/
virtual DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const = 0;
+ /**
+ * @brief initializeDeviceSelectionCache. Device selection for AudioAttribute / Streams is
+ * cached in the engine in order to speed up process when the audio system is stable. When the
+ * audio system is initializing, not all audio devices information will be available. In that
+ * case, calling this function can allow the engine to initialize the device selection cache
+ * with default values.
+ * This must only be called when audio policy manager is initializing.
+ */
+ virtual void initializeDeviceSelectionCache() = 0;
+
virtual void dump(String8 *dst) const = 0;
protected:
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 2831a9b..a802646 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -354,14 +354,6 @@
return availableInputDevices.getDevice(deviceType, String8(address.c_str()), AUDIO_FORMAT_DEFAULT);
}
-void Engine::updateDeviceSelectionCache()
-{
- for (const auto &iter : getProductStrategies()) {
- const auto &strategy = iter.second;
- mDevicesForStrategies[strategy->getId()] = getDevicesForProductStrategy(strategy->getId());
- }
-}
-
void Engine::setDeviceAddressForProductStrategy(product_strategy_t strategy,
const std::string &address)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4b559f0..001dde9 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -66,8 +66,6 @@
sp<AudioPolicyMix> *mix = nullptr)
const override;
- void updateDeviceSelectionCache() override;
-
///
/// from AudioPolicyPluginInterface
///
@@ -122,15 +120,17 @@
status_t loadAudioPolicyEngineConfig();
- DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
DeviceVector getCachedDevices(product_strategy_t ps) const;
+ ///
+ /// from EngineBase
+ ///
+ DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
+
/**
* Policy Parameter Manager hidden through a wrapper.
*/
ParameterManagerWrapper *mPolicyParameterMgr;
-
- DeviceStrategyMap mDevicesForStrategies;
};
} // namespace audio_policy
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 45c5eac..e72249f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -279,7 +279,8 @@
getLastRemovableMediaDevices(GROUP_NONE, {AUDIO_DEVICE_OUT_BLE_HEADSET}));
if (!devices.isEmpty()) break;
devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE});
+ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE,
+ AUDIO_DEVICE_OUT_SPEAKER});
} break;
case STRATEGY_SONIFICATION:
@@ -641,15 +642,9 @@
return device;
}
-void Engine::updateDeviceSelectionCache()
-{
- for (const auto &iter : getProductStrategies()) {
- const auto& strategy = iter.second;
- auto devices = getDevicesForProductStrategy(strategy->getId());
- mDevicesForStrategies[strategy->getId()] = devices;
- strategy->setDeviceTypes(devices.types());
- strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
- }
+void Engine::setStrategyDevices(const sp<ProductStrategy>& strategy, const DeviceVector &devices) {
+ strategy->setDeviceTypes(devices.types());
+ strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
}
product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 595e289..be9f4cc 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -67,7 +67,10 @@
sp<AudioPolicyMix> *mix = nullptr)
const override;
- void updateDeviceSelectionCache() override;
+ void setStrategyDevices(const sp<ProductStrategy>& strategy,
+ const DeviceVector& devices) override;
+
+ DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
private:
/* Copy facilities are put private to disable copy. */
@@ -87,8 +90,6 @@
DeviceVector availableOutputDevices,
const SwAudioOutputCollection &outputs) const;
- DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
-
sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
@@ -97,8 +98,6 @@
DeviceVector getPreferredAvailableDevicesForProductStrategy(
const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
- DeviceStrategyMap mDevicesForStrategies;
-
std::map<product_strategy_t, legacy_strategy> mLegacyStrategyMap;
};
} // namespace audio_policy
diff --git a/services/audiopolicy/fuzzer/Android.bp b/services/audiopolicy/fuzzer/Android.bp
index 9f6b703..621f643 100644
--- a/services/audiopolicy/fuzzer/Android.bp
+++ b/services/audiopolicy/fuzzer/Android.bp
@@ -63,6 +63,15 @@
],
data: [":audiopolicyfuzzer_configuration_files"],
fuzz_config: {
- cc: ["mnaganov@google.com"],
+ cc: ["mnaganov@google.com"],
+ componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libaudiopolicy",
+ vector: "local_no_privileges_required",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c64497f..7b6b0fe 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4242,6 +4242,28 @@
return NO_ERROR;
}
+status_t AudioPolicyManager::listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* _aidl_return) {
+ auto pushPort = [&](const sp<DeviceDescriptor>& dev) -> status_t {
+ audio_port_v7 port;
+ dev->toAudioPort(&port);
+ auto aidlPort = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port));
+ _aidl_return->push_back(std::move(aidlPort));
+ return OK;
+ };
+
+ for (const auto& module : mHwModulesAll) {
+ for (const auto& dev : module->getDeclaredDevices()) {
+ if (role == media::AudioPortRole::NONE ||
+ ((role == media::AudioPortRole::SOURCE)
+ == audio_is_input_device(dev->type()))) {
+ RETURN_STATUS_IF_ERROR(pushPort(dev));
+ }
+ }
+ }
+ return OK;
+}
+
status_t AudioPolicyManager::getAudioPort(struct audio_port_v7 *port)
{
if (port == nullptr || port->id == AUDIO_PORT_HANDLE_NONE) {
@@ -5652,7 +5674,9 @@
}
}
- mEngine->updateDeviceSelectionCache();
+ // The actual device selection cache will be updated when calling `updateDevicesAndOutputs`
+ // at the end of this function.
+ mEngine->initializeDeviceSelectionCache();
mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 8466d097..e0411ab 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -261,6 +261,8 @@
unsigned int *num_ports,
struct audio_port_v7 *ports,
unsigned int *generation);
+ status_t listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* result) override;
virtual status_t getAudioPort(struct audio_port_v7 *port);
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index fdf5787..f34427c 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1516,6 +1516,17 @@
return Status::ok();
}
+Status AudioPolicyService::listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* _aidl_return) {
+ Mutex::Autolock _l(mLock);
+ if (mAudioPolicyManager == NULL) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+ AutoCallerClear acc;
+ return binderStatusFromStatusT(mAudioPolicyManager->listDeclaredDevicePorts(
+ role, _aidl_return));
+}
+
Status AudioPolicyService::getAudioPort(int portId,
media::AudioPortFw* _aidl_return) {
audio_port_v7 port{ .id = portId };
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 860bd18..7f682c8 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -174,6 +174,8 @@
binder::Status listAudioPorts(media::AudioPortRole role, media::AudioPortType type,
Int* count, std::vector<media::AudioPortFw>* ports,
int32_t* _aidl_return) override;
+ binder::Status listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* _aidl_return) override;
binder::Status getAudioPort(int portId,
media::AudioPortFw* _aidl_return) override;
binder::Status createAudioPatch(const media::AudioPatchFw& patch, int32_t handle,
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 1c40cfd..3821f97 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1681,19 +1681,19 @@
// Connecting a valid output device with valid parameters should trigger a routing update
ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- "a", "b", AUDIO_FORMAT_DEFAULT));
+ "00:11:22:33:44:55", "b", AUDIO_FORMAT_DEFAULT));
ASSERT_EQ(1, mClient->getRoutingUpdatedCounter());
// Disconnecting a connected device should succeed and trigger a routing update
ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- "a", "b", AUDIO_FORMAT_DEFAULT));
+ "00:11:22:33:44:55", "b", AUDIO_FORMAT_DEFAULT));
ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
// Disconnecting a disconnected device should fail and not trigger a routing update
ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- "a", "b", AUDIO_FORMAT_DEFAULT));
+ "00:11:22:33:44:55", "b", AUDIO_FORMAT_DEFAULT));
ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
// Changing force use should trigger an update
@@ -1820,9 +1820,9 @@
DeviceConnectionTestParams({AUDIO_DEVICE_OUT_HDMI, "test_out_hdmi",
"audio_policy_test_out_hdmi"}),
DeviceConnectionTestParams({AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "bt_hfp_in",
- "hfp_client_in"}),
+ "00:11:22:33:44:55"}),
DeviceConnectionTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "bt_hfp_out",
- "hfp_client_out"})
+ "00:11:22:33:44:55"})
)
);
diff --git a/services/medialog/fuzzer/Android.bp b/services/medialog/fuzzer/Android.bp
index 9ff0ce4..c96c37b 100644
--- a/services/medialog/fuzzer/Android.bp
+++ b/services/medialog/fuzzer/Android.bp
@@ -38,5 +38,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libmedialogservice library",
+ vector: "local_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "future_version",
},
}
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
index 9f08eca..e5f7190 100644
--- a/services/mediametrics/statsd_drm.cpp
+++ b/services/mediametrics/statsd_drm.cpp
@@ -281,9 +281,9 @@
const int32_t uid = IPCThreadState::self()->getCallingUid();
int32_t frontend = 0;
if (!item->getInt32("frontend", &frontend)) return false;
- int32_t requested_security_level = -1;
+ int32_t requested_security_level = 0;
if (!item->getInt32("requested_security_level", &requested_security_level)) return false;
- int32_t opened_security_level = -1;
+ int32_t opened_security_level = 0;
if (!item->getInt32("opened_security_level", &opened_security_level)) return false;
// Optional to be included
@@ -325,12 +325,10 @@
if (!item->getInt32("frontend", &frontend)) return false;
std::string object_nonce = "";
if (!item->getString("object_nonce", &object_nonce)) return false;
- int32_t security_level = -1;
- if (!item->getInt32("security_level", &security_level)) return false;
std::string api_str = "";
if (!item->getString("api", &api_str)) return false;
const int32_t api = MediaDrmStatsdHelper::findDrmApi(api_str);
- int32_t error_code = -1;
+ int32_t error_code = 0;
if (!item->getInt32("error_code", &error_code)) return false;
// Optional to be included
@@ -338,12 +336,14 @@
item->getString("version", &version);
std::string session_nonce = "";
item->getString("session_nonce", &session_nonce);
+ int32_t security_level = 0;
+ item->getInt32("security_level", &security_level);
int32_t cdm_err = 0;
item->getInt32("cdm_err", &cdm_err);
int32_t oem_err = 0;
item->getInt32("oem_err", &oem_err);
- int32_t error_context = -1;
+ int32_t error_context = 0;
item->getInt32("error_context", &error_context);
const int result = stats_write(stats::media_metrics::MEDIA_DRM_ERRORED, scheme, uuid_lsb,