Merge "Skip frames out limit for non pcm" into main
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 24a11e3..0d20f52 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -111,6 +111,7 @@
cc_library_shared {
name: "libcamera2ndk_vendor",
+ cpp_std: "gnu++17",
vendor: true,
srcs: [
"ndk_vendor/impl/ACameraDevice.cpp",
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 5558259..947352f 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -565,7 +565,8 @@
AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE);
append_AudioDeviceDescription(pairs,
AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
- AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
+ AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY,
+ GET_DEVICE_DESC_CONNECTION(VIRTUAL));
append_AudioDeviceDescription(pairs,
AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
diff --git a/media/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index 73cae93..ac0a077 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -6,7 +6,6 @@
// use libcodec2-aidl-client-defaults instead
cc_library {
name: "libcodec2_aidl_client",
- min_sdk_version: "31",
srcs: [
"BufferTypes.cpp",
@@ -36,7 +35,6 @@
],
static_libs: [
- "libPlatformProperties",
"libaidlcommonsupport",
],
@@ -55,7 +53,7 @@
// use libcodec2-aidl-defaults instead
cc_library {
name: "libcodec2_aidl",
- min_sdk_version: "31",
+ min_sdk_version: "30",
vendor_available: true,
apex_available: [
"//apex_available:platform",
@@ -98,7 +96,6 @@
],
static_libs: [
- "libPlatformProperties",
"libaidlcommonsupport",
],
@@ -134,7 +131,7 @@
// public dependency for Codec 2.0 HAL service implementations
cc_defaults {
name: "libcodec2-aidl-defaults",
- min_sdk_version: "31",
+ min_sdk_version: "30",
defaults: ["libcodec2-impl-defaults"],
shared_libs: [
@@ -147,7 +144,6 @@
// public dependency for Codec 2.0 HAL client
cc_defaults {
name: "libcodec2-aidl-client-defaults",
- min_sdk_version: "31",
defaults: ["libcodec2-impl-defaults"],
shared_libs: [
diff --git a/media/codec2/hal/aidl/ParamTypes.cpp b/media/codec2/hal/aidl/ParamTypes.cpp
index 41e6f50..495e748 100644
--- a/media/codec2/hal/aidl/ParamTypes.cpp
+++ b/media/codec2/hal/aidl/ParamTypes.cpp
@@ -19,7 +19,9 @@
#include <android-base/logging.h>
#include <android/binder_manager.h>
-#include <android/sysprop/MediaProperties.sysprop.h>
+// NOTE: due to dependency from mainline modules cannot use libsysprop
+// #include <android/sysprop/MediaProperties.sysprop.h>
+#include <android-base/properties.h>
#include <codec2/aidl/ParamTypes.h>
#include <codec2/common/ParamTypes.h>
@@ -167,6 +169,8 @@
// Cannot select AIDL if not enabled
return false;
}
+#if 0
+ // NOTE: due to dependency from mainline modules cannot use libsysprop
using ::android::sysprop::MediaProperties::codec2_hal_selection;
using ::android::sysprop::MediaProperties::codec2_hal_selection_values;
constexpr codec2_hal_selection_values AIDL = codec2_hal_selection_values::AIDL;
@@ -180,6 +184,16 @@
default:
LOG(FATAL) << "Unexpected codec2 HAL selection value: " << (int)selection;
}
+#else
+ std::string selection = ::android::base::GetProperty("media.c2.hal.selection", "hidl");
+ if (selection == "aidl") {
+ return true;
+ } else if (selection == "hidl") {
+ return false;
+ } else {
+ LOG(FATAL) << "Unexpected codec2 HAL selection value: " << selection;
+ }
+#endif
return false;
}
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index 1e9aa7f..ce10109 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -46,6 +46,7 @@
#include <aidl/android/hardware/media/c2/StructDescriptor.h>
#include <aidlcommonsupport/NativeHandle.h>
+#include <android/api-level.h>
#include <android/binder_auto_utils.h>
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
@@ -1440,12 +1441,16 @@
std::vector<std::string> names;
if (c2_aidl::utils::IsSelected()) {
- // Get AIDL service names
- AServiceManager_forEachDeclaredInstance(
- AidlBase::descriptor, &names, [](const char *name, void *context) {
- std::vector<std::string> *names = (std::vector<std::string> *)context;
- names->emplace_back(name);
- });
+ if (__builtin_available(android __ANDROID_API_S__, *)) {
+ // Get AIDL service names
+ AServiceManager_forEachDeclaredInstance(
+ AidlBase::descriptor, &names, [](const char *name, void *context) {
+ std::vector<std::string> *names = (std::vector<std::string> *)context;
+ names->emplace_back(name);
+ });
+ } else {
+ LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
+ }
} else {
// Get HIDL service names
using ::android::hardware::media::c2::V1_0::IComponentStore;
@@ -1547,21 +1552,25 @@
LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
if (c2_aidl::utils::IsSelected()) {
- std::string instanceName =
- ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
- if (AServiceManager_isDeclared(instanceName.c_str())) {
- std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
- ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
- CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
- " inaccessible for unknown reasons.";
- LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
- std::shared_ptr<c2_aidl::IConfigurable> configurable;
- ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
- CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
- "does not have IConfigurable.";
- return std::make_shared<Codec2Client>(baseStore, configurable, index);
+ if (__builtin_available(android __ANDROID_API_S__, *)) {
+ std::string instanceName =
+ ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
+ if (AServiceManager_isDeclared(instanceName.c_str())) {
+ std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
+ ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
+ CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
+ " inaccessible for unknown reasons.";
+ LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
+ std::shared_ptr<c2_aidl::IConfigurable> configurable;
+ ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
+ CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
+ "does not have IConfigurable.";
+ return std::make_shared<Codec2Client>(baseStore, configurable, index);
+ } else {
+ LOG(ERROR) << "Codec2 AIDL service \"" << name << "\" is not declared";
+ }
} else {
- LOG(ERROR) << "Codec2 AIDL service \"" << name << "\" is not declared";
+ LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
}
} else {
std::string instanceName = "android.hardware.media.c2/" + name;
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index 501831d..2ab8053 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -79,8 +79,8 @@
bool equals(const sp<DeviceDescriptorBase>& other) const;
- status_t writeToParcelable(media::AudioPortFw* parcelable) const;
- status_t readFromParcelable(const media::AudioPortFw& parcelable);
+ virtual status_t writeToParcelable(media::AudioPortFw* parcelable) const;
+ virtual status_t readFromParcelable(const media::AudioPortFw& parcelable);
protected:
AudioDeviceTypeAddr mDeviceTypeAddr;
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index e2233c7..5bc25ae 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -28,6 +28,7 @@
#include <media/AidlConversionNdkCpp.h>
#include <media/AidlConversionUtil.h>
#include <mediautils/TimeCheck.h>
+#include <system/audio.h>
#include <Utils.h>
#include <utils/Log.h>
@@ -41,6 +42,7 @@
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::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
@@ -185,23 +187,77 @@
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
__func__, mInstance.c_str());
- std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
- [](const auto& p) { return std::make_pair(p.id, p); });
mDefaultInputPortId = mDefaultOutputPortId = -1;
const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
- for (const auto& pair : mPorts) {
- const auto& p = pair.second;
- if (p.ext.getTag() == AudioPortExt::Tag::device &&
- (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
- if (p.flags.getTag() == AudioIoFlags::Tag::input) {
- mDefaultInputPortId = p.id;
- } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
- mDefaultOutputPortId = p.id;
+ for (auto it = ports.begin(); it != ports.end(); ) {
+ const auto& port = *it;
+ if (port.ext.getTag() != AudioPortExt::Tag::device) {
+ ++it;
+ continue;
+ }
+ const AudioPortDeviceExt& deviceExt = port.ext.get<AudioPortExt::Tag::device>();
+ if ((deviceExt.flags & defaultDeviceFlag) != 0) {
+ if (port.flags.getTag() == AudioIoFlags::Tag::input) {
+ mDefaultInputPortId = port.id;
+ } else if (port.flags.getTag() == AudioIoFlags::Tag::output) {
+ mDefaultOutputPortId = port.id;
}
}
+ // For compatibility with HIDL, hide "template" remote submix ports from ports list.
+ if (const auto& devDesc = deviceExt.device;
+ (devDesc.type.type == AudioDeviceType::IN_SUBMIX ||
+ devDesc.type.type == AudioDeviceType::OUT_SUBMIX) &&
+ devDesc.type.connection == AudioDeviceDescription::CONNECTION_VIRTUAL) {
+ if (devDesc.type.type == AudioDeviceType::IN_SUBMIX) {
+ mRemoteSubmixIn = port;
+ } else {
+ mRemoteSubmixOut = port;
+ }
+ it = ports.erase(it);
+ } else {
+ ++it;
+ }
}
+ if (mRemoteSubmixIn.has_value() != mRemoteSubmixOut.has_value()) {
+ ALOGE("%s: The configuration only has input or output remote submix device, must have both",
+ __func__);
+ mRemoteSubmixIn.reset();
+ mRemoteSubmixOut.reset();
+ }
+ if (mRemoteSubmixIn.has_value()) {
+ AudioPort connectedRSubmixIn = *mRemoteSubmixIn;
+ connectedRSubmixIn.ext.get<AudioPortExt::Tag::device>().device.address =
+ AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS;
+ ALOGD("%s: connecting remote submix input", __func__);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
+ connectedRSubmixIn, &connectedRSubmixIn)));
+ // The template port for the remote submix input couldn't be "default" because it is not
+ // attached. The connected port can now be made default because we never disconnect it.
+ if (mDefaultInputPortId == -1) {
+ mDefaultInputPortId = connectedRSubmixIn.id;
+ }
+ ports.push_back(std::move(connectedRSubmixIn));
+
+ // Remote submix output must not be connected until the framework actually starts
+ // using it, however for legacy compatibility we need to provide an "augmented template"
+ // port with an address and profiles. It is obtained by connecting the output and then
+ // immediately disconnecting it. This is a cheap operation as we don't open any streams.
+ AudioPort tempConnectedRSubmixOut = *mRemoteSubmixOut;
+ tempConnectedRSubmixOut.ext.get<AudioPortExt::Tag::device>().device.address =
+ AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS;
+ ALOGD("%s: temporarily connecting and disconnecting remote submix output", __func__);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
+ tempConnectedRSubmixOut, &tempConnectedRSubmixOut)));
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
+ tempConnectedRSubmixOut.id)));
+ tempConnectedRSubmixOut.id = mRemoteSubmixOut->id;
+ ports.push_back(std::move(tempConnectedRSubmixOut));
+ }
+
ALOGI("%s: module %s default port ids: input %d, output %d",
__func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
+ std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
+ [](const auto& p) { return std::make_pair(p.id, p); });
RETURN_STATUS_IF_ERROR(updateRoutes());
std::vector<AudioPortConfig> portConfigs;
RETURN_STATUS_IF_ERROR(
@@ -1079,6 +1135,7 @@
}
status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mModule) return NO_INIT;
if (port == nullptr) {
@@ -1104,20 +1161,43 @@
}
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()) {
- // Since 'setConnectedState' is called for all modules, it is normal when the device
- // port not found in every one of them.
- return BAD_VALUE;
+ std::optional<AudioPort> templatePort;
+ auto erasePortAfterConnectionIt = mPorts.end();
+ // Connection of remote submix out with address "0" is a special case. Since there is
+ // already an "augmented template" port with this address in mPorts, we need to replace
+ // it with a connected port.
+ // Connection of remote submix outs with any other address is done as usual except that
+ // the template port is in `mRemoteSubmixOut`.
+ if (mRemoteSubmixOut.has_value() &&
+ matchDevice.type.type == AudioDeviceType::OUT_SUBMIX) {
+ if (matchDevice.address == AudioDeviceAddress::make<AudioDeviceAddress::id>(
+ AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS)) {
+ erasePortAfterConnectionIt = findPort(matchDevice);
+ }
+ templatePort = mRemoteSubmixOut;
+ } else if (mRemoteSubmixIn.has_value() &&
+ matchDevice.type.type == AudioDeviceType::IN_SUBMIX) {
+ templatePort = mRemoteSubmixIn;
} else {
- ALOGD("%s: device port for device %s found in the module %s",
- __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ // Reset the device address to find the "template" port.
+ matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
+ }
+ if (!templatePort.has_value()) {
+ auto portsIt = findPort(matchDevice);
+ if (portsIt == mPorts.end()) {
+ // Since 'setConnectedState' is called for all modules, it is normal when the device
+ // port not found in every one of them.
+ return BAD_VALUE;
+ } else {
+ ALOGD("%s: device port for device %s found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ }
+ templatePort = portsIt->second;
}
resetUnusedPatchesAndPortConfigs();
+
// Use the ID of the "template" port, use all the information from the provided port.
- aidlPort.id = portsIt->first;
+ aidlPort.id = templatePort->id;
AudioPort connectedPort;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
aidlPort, &connectedPort)));
@@ -1127,6 +1207,9 @@
__func__, mInstance.c_str(), connectedPort.toString().c_str(),
it->second.toString().c_str());
mConnectedPorts[connectedPort.id] = false;
+ if (erasePortAfterConnectionIt != mPorts.end()) {
+ mPorts.erase(erasePortAfterConnectionIt);
+ }
} else { // !connected
AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
auto portsIt = findPort(matchDevice);
@@ -1139,14 +1222,24 @@
__func__, matchDevice.toString().c_str(), mInstance.c_str());
}
resetUnusedPatchesAndPortConfigs();
+
+ // Disconnection of remote submix out with address "0" is a special case. We need to replace
+ // the connected port entry with the "augmented template".
+ const int32_t portId = portsIt->second.id;
+ if (mRemoteSubmixOut.has_value() && matchDevice.type.type == AudioDeviceType::OUT_SUBMIX &&
+ matchDevice.address == AudioDeviceAddress::make<AudioDeviceAddress::id>(
+ AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS)) {
+ mDisconnectedPortReplacement = std::make_pair(portId, *mRemoteSubmixOut);
+ auto& port = mDisconnectedPortReplacement.second;
+ port.ext.get<AudioPortExt::Tag::device>().device = matchDevice;
+ port.profiles = portsIt->second.profiles;
+ }
// Streams are closed by AudioFlinger independently from device disconnections.
// It is possible that the stream has not been closed yet.
- const int32_t portId = portsIt->second.id;
if (!isPortHeldByAStream(portId)) {
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mModule->disconnectExternalDevice(portId)));
- mPorts.erase(portsIt);
- mConnectedPorts.erase(portId);
+ eraseConnectedPort(portId);
} else {
ALOGD("%s: since device port ID %d is used by a stream, "
"external device disconnection postponed", __func__, portId);
@@ -1216,6 +1309,17 @@
return OK;
}
+void DeviceHalAidl::eraseConnectedPort(int32_t portId) {
+ mPorts.erase(portId);
+ mConnectedPorts.erase(portId);
+ if (mDisconnectedPortReplacement.first == portId) {
+ const auto& port = mDisconnectedPortReplacement.second;
+ mPorts.insert(std::make_pair(port.id, port));
+ ALOGD("%s: disconnected port replacement: %s", __func__, port.toString().c_str());
+ mDisconnectedPortReplacement = std::pair<int32_t, AudioPort>();
+ }
+}
+
status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
AudioParameter &keys, AudioParameter *result) {
TIME_CHECK();
@@ -1847,8 +1951,7 @@
if (!isPortHeldByAStream(portId)) {
TIME_CHECK();
if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
- mPorts.erase(portId);
- mConnectedPorts.erase(portId);
+ eraseConnectedPort(portId);
ALOGD("%s: executed postponed external device disconnection for port ID %d",
__func__, portId);
}
@@ -1865,6 +1968,30 @@
statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
__func__, mInstance.c_str());
+ if (mRemoteSubmixIn.has_value()) {
+ // Remove mentions of the template remote submix input from routes.
+ int32_t rSubmixInId = mRemoteSubmixIn->id;
+ // Remove mentions of the template remote submix out only if it is not in mPorts
+ // (that means there is a connected port in mPorts).
+ int32_t rSubmixOutId = mPorts.find(mRemoteSubmixOut->id) == mPorts.end() ?
+ mRemoteSubmixOut->id : -1;
+ for (auto it = mRoutes.begin(); it != mRoutes.end();) {
+ auto& route = *it;
+ if (route.sinkPortId == rSubmixOutId) {
+ it = mRoutes.erase(it);
+ continue;
+ }
+ if (auto sourceIt = std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(),
+ rSubmixInId); sourceIt != route.sourcePortIds.end()) {
+ route.sourcePortIds.erase(sourceIt);
+ if (route.sourcePortIds.empty()) {
+ it = mRoutes.erase(it);
+ continue;
+ }
+ }
+ ++it;
+ }
+ }
mRoutingMatrix.clear();
for (const auto& r : mRoutes) {
for (auto portId : r.sourcePortIds) {
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index e1fe4d1..99e8503 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -223,6 +223,7 @@
status_t createOrUpdatePortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
PortConfigs::iterator* result, bool *created);
+ void eraseConnectedPort(int32_t portId);
status_t filterAndRetrieveBtA2dpParameters(AudioParameter &keys, AudioParameter *result);
status_t filterAndUpdateBtA2dpParameters(AudioParameter ¶meters);
status_t filterAndUpdateBtHfpParameters(AudioParameter ¶meters);
@@ -313,6 +314,10 @@
std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>
mSoundDose = nullptr;
Ports mPorts;
+ // Remote submix "template" ports (no address specified, no profiles).
+ // They are excluded from `mPorts` as their presence confuses the framework code.
+ std::optional<::aidl::android::media::audio::common::AudioPort> mRemoteSubmixIn;
+ std::optional<::aidl::android::media::audio::common::AudioPort> mRemoteSubmixOut;
int32_t mDefaultInputPortId = -1;
int32_t mDefaultOutputPortId = -1;
PortConfigs mPortConfigs;
@@ -326,6 +331,8 @@
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
ConnectedPorts mConnectedPorts;
+ std::pair<int32_t, ::aidl::android::media::audio::common::AudioPort>
+ mDisconnectedPortReplacement;
};
} // namespace android
diff --git a/media/mediaserver/manifest_media_c2_software.xml b/media/mediaserver/manifest_media_c2_software.xml
index a5b4896..d7fb1a0 100644
--- a/media/mediaserver/manifest_media_c2_software.xml
+++ b/media/mediaserver/manifest_media_c2_software.xml
@@ -8,4 +8,9 @@
<instance>software</instance>
</interface>
</hal>
+ <hal format="aidl">
+ <name>android.hardware.media.c2</name>
+ <version>1</version>
+ <fqname>IComponentStore/software</fqname>
+ </hal>
</manifest>
diff --git a/media/module/TEST_MAPPING b/media/module/TEST_MAPPING
new file mode 100644
index 0000000..c59df72
--- /dev/null
+++ b/media/module/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "postsubmit": [
+ {
+ "name": "hal_implementation_test"
+ }
+ ]
+}
+
diff --git a/media/module/codecserviceregistrant/Android.bp b/media/module/codecserviceregistrant/Android.bp
index 9ee81a4..becb98a 100644
--- a/media/module/codecserviceregistrant/Android.bp
+++ b/media/module/codecserviceregistrant/Android.bp
@@ -64,6 +64,7 @@
],
defaults: [
+ "libcodec2-aidl-defaults",
"libcodec2-hidl-defaults",
"libcodec2-runtime-libs",
],
diff --git a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
index 1de9efe..65d537b 100644
--- a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
+++ b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
@@ -20,15 +20,25 @@
#include <android/api-level.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
#include <C2Component.h>
#include <C2PlatformSupport.h>
+
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.1/ComponentStore.h>
#include <codec2/hidl/1.2/ComponentStore.h>
#include <codec2/hidl/1.2/Configurable.h>
#include <codec2/hidl/1.2/types.h>
#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/ParamTypes.h>
+
#include <media/CodecServiceRegistrant.h>
namespace /* unnamed */ {
@@ -36,59 +46,142 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
-using ::android::hardware::Void;
using ::android::sp;
-using namespace ::android::hardware::media::c2::V1_2;
-using namespace ::android::hardware::media::c2::V1_2::utils;
+using ::ndk::ScopedAStatus;
+namespace c2_hidl = ::android::hardware::media::c2::V1_2;
+namespace c2_aidl = ::aidl::android::hardware::media::c2;
constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
// Converter from IComponentStore to C2ComponentStore.
class H2C2ComponentStore : public C2ComponentStore {
protected:
- using IComponentStore =
+ using HidlComponentStore =
::android::hardware::media::c2::V1_0::IComponentStore;
- using IConfigurable =
+ using HidlConfigurable =
::android::hardware::media::c2::V1_0::IConfigurable;
- sp<IComponentStore> mStore;
- sp<IConfigurable> mConfigurable;
+ sp<HidlComponentStore> mHidlStore;
+ sp<HidlConfigurable> mHidlConfigurable;
+
+ using AidlComponentStore =
+ ::aidl::android::hardware::media::c2::IComponentStore;
+ using AidlConfigurable =
+ ::aidl::android::hardware::media::c2::IConfigurable;
+ std::shared_ptr<AidlComponentStore> mAidlStore;
+ std::shared_ptr<AidlConfigurable> mAidlConfigurable;
public:
- explicit H2C2ComponentStore(sp<IComponentStore> const& store)
- : mStore{store},
- mConfigurable{[store]() -> sp<IConfigurable>{
+ explicit H2C2ComponentStore(nullptr_t) {
+ }
+
+ explicit H2C2ComponentStore(sp<HidlComponentStore> const& store)
+ : mHidlStore{store},
+ mHidlConfigurable{[store]() -> sp<HidlConfigurable>{
if (!store) {
return nullptr;
}
- Return<sp<IConfigurable>> transResult =
+ Return<sp<HidlConfigurable>> transResult =
store->getConfigurable();
return transResult.isOk() ?
- static_cast<sp<IConfigurable>>(transResult) :
+ static_cast<sp<HidlConfigurable>>(transResult) :
nullptr;
}()} {
- if (!mConfigurable) {
+ if (!mHidlConfigurable) {
+ LOG(ERROR) << "Preferred store is corrupted.";
+ }
+ }
+
+ explicit H2C2ComponentStore(std::shared_ptr<AidlComponentStore> const& store)
+ : mAidlStore{store},
+ mAidlConfigurable{[store]() -> std::shared_ptr<AidlConfigurable>{
+ if (!store) {
+ return nullptr;
+ }
+ std::shared_ptr<AidlConfigurable> configurable;
+ ScopedAStatus status = store->getConfigurable(&configurable);
+ if (!status.isOk()) {
+ return nullptr;
+ }
+ return configurable;
+ }()} {
+ if (!mAidlConfigurable) {
LOG(ERROR) << "Preferred store is corrupted.";
}
}
virtual ~H2C2ComponentStore() override = default;
- virtual c2_status_t config_sm(
+ c2_status_t config_sm(
std::vector<C2Param*> const ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures
) override {
- Params hidlParams;
- if (!createParamsBlob(&hidlParams, params)) {
+ if (mAidlStore) {
+ return config_sm_aidl(params, failures);
+ } else if (mHidlStore) {
+ return config_sm_hidl(params, failures);
+ } else {
+ return C2_OMITTED;
+ }
+ }
+
+ c2_status_t config_sm_aidl(
+ std::vector<C2Param*> const ¶ms,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) {
+ c2_aidl::Params aidlParams;
+ if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
+ LOG(ERROR) << "config -- bad input.";
+ return C2_TRANSACTION_FAILED;
+ }
+ c2_status_t status = C2_OK;
+ c2_aidl::IConfigurable::ConfigResult configResult;
+ ScopedAStatus transResult = mAidlConfigurable->config(
+ aidlParams, true, &configResult);
+ if (!transResult.isOk()) {
+ if (transResult.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ status = c2_status_t(transResult.getServiceSpecificError());
+ if (status != C2_BAD_INDEX) {
+ LOG(DEBUG) << "config -- call failed: "
+ << status << ".";
+ }
+ } else {
+ LOG(ERROR) << "config -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+ size_t i = failures->size();
+ failures->resize(i + configResult.failures.size());
+ for (const c2_aidl::SettingResult& sf : configResult.failures) {
+ if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
+ LOG(ERROR) << "config -- "
+ << "invalid SettingResult returned.";
+ status = C2_CORRUPTED;
+ }
+ }
+ if (!c2_aidl::utils::UpdateParamsFromBlob(params, configResult.params)) {
+ LOG(ERROR) << "config -- "
+ << "failed to parse returned params.";
+ status = C2_CORRUPTED;
+ }
+ return status;
+ };
+
+ c2_status_t config_sm_hidl(
+ std::vector<C2Param*> const ¶ms,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) {
+ c2_hidl::Params hidlParams;
+ if (!c2_hidl::utils::createParamsBlob(&hidlParams, params)) {
LOG(ERROR) << "config -- bad input.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status{};
- Return<void> transResult = mConfigurable->config(
+ Return<void> transResult = mHidlConfigurable->config(
hidlParams,
true,
[&status, ¶ms, failures](
- Status s,
- const hidl_vec<SettingResult> f,
- const Params& o) {
+ c2_hidl::Status s,
+ const hidl_vec<c2_hidl::SettingResult> f,
+ const c2_hidl::Params& o) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK && status != C2_BAD_INDEX) {
LOG(DEBUG) << "config -- call failed: "
@@ -96,14 +189,14 @@
}
size_t i = failures->size();
failures->resize(i + f.size());
- for (const SettingResult& sf : f) {
- if (!objcpy(&(*failures)[i++], sf)) {
+ for (const c2_hidl::SettingResult& sf : f) {
+ if (!c2_hidl::utils::objcpy(&(*failures)[i++], sf)) {
LOG(ERROR) << "config -- "
<< "invalid SettingResult returned.";
return;
}
}
- if (!updateParamsFromBlob(params, o)) {
+ if (!c2_hidl::utils::updateParamsFromBlob(params, o)) {
LOG(ERROR) << "config -- "
<< "failed to parse returned params.";
status = C2_CORRUPTED;
@@ -116,33 +209,142 @@
return status;
};
- virtual c2_status_t copyBuffer(
+ c2_status_t copyBuffer(
std::shared_ptr<C2GraphicBuffer>,
std::shared_ptr<C2GraphicBuffer>) override {
LOG(ERROR) << "copyBuffer -- not supported.";
return C2_OMITTED;
}
- virtual c2_status_t createComponent(
+ c2_status_t createComponent(
C2String, std::shared_ptr<C2Component> *const component) override {
component->reset();
LOG(ERROR) << "createComponent -- not supported.";
return C2_OMITTED;
}
- virtual c2_status_t createInterface(
- C2String, std::shared_ptr<C2ComponentInterface> *const interface) {
+ c2_status_t createInterface(
+ C2String, std::shared_ptr<C2ComponentInterface> *const interface) override {
interface->reset();
LOG(ERROR) << "createInterface -- not supported.";
return C2_OMITTED;
}
- virtual c2_status_t query_sm(
+ c2_status_t query_sm(
const std::vector<C2Param *> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
- std::vector<std::unique_ptr<C2Param>> *const heapParams) const
- override {
- hidl_vec<ParamIndex> indices(
+ std::vector<std::unique_ptr<C2Param>> *const heapParams) const override {
+ if (mAidlStore) {
+ return query_sm_aidl(stackParams, heapParamIndices, heapParams);
+ } else if (mHidlStore) {
+ return query_sm_hidl(stackParams, heapParamIndices, heapParams);
+ } else {
+ return C2_OMITTED;
+ }
+ }
+
+ static c2_status_t UpdateQueryResult(
+ const std::vector<C2Param *> ¶mPointers,
+ size_t numStackIndices,
+ const std::vector<C2Param *> &stackParams,
+ std::vector<std::unique_ptr<C2Param>> *const heapParams) {
+ c2_status_t status = C2_OK;
+ size_t i = 0;
+ for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
+ C2Param* paramPointer = *it;
+ if (numStackIndices > 0) {
+ --numStackIndices;
+ if (!paramPointer) {
+ LOG(WARNING) << "query -- null stack param.";
+ ++it;
+ continue;
+ }
+ for (; i < stackParams.size() && !stackParams[i]; ) {
+ ++i;
+ }
+ if (i >= stackParams.size()) {
+ LOG(ERROR) << "query -- unexpected error.";
+ status = C2_CORRUPTED;
+ break;
+ }
+ if (stackParams[i]->index() != paramPointer->index()) {
+ LOG(WARNING) << "query -- param skipped: "
+ "index = "
+ << stackParams[i]->index() << ".";
+ stackParams[i++]->invalidate();
+ continue;
+ }
+ if (!stackParams[i++]->updateFrom(*paramPointer)) {
+ LOG(WARNING) << "query -- param update failed: "
+ "index = "
+ << paramPointer->index() << ".";
+ }
+ } else {
+ if (!paramPointer) {
+ LOG(WARNING) << "query -- null heap param.";
+ ++it;
+ continue;
+ }
+ if (!heapParams) {
+ LOG(WARNING) << "query -- "
+ "unexpected extra stack param.";
+ } else {
+ heapParams->emplace_back(
+ C2Param::Copy(*paramPointer));
+ }
+ }
+ ++it;
+ }
+ return status;
+ }
+
+ c2_status_t query_sm_aidl(
+ const std::vector<C2Param *> &stackParams,
+ const std::vector<C2Param::Index> &heapParamIndices,
+ std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
+ std::vector<int32_t> indices;
+ size_t numIndices = 0;
+ for (C2Param* const& stackParam : stackParams) {
+ if (!stackParam) {
+ LOG(WARNING) << "query -- null stack param encountered.";
+ continue;
+ }
+ indices[numIndices++] = stackParam->index();
+ }
+ size_t numStackIndices = numIndices;
+ for (const C2Param::Index& index : heapParamIndices) {
+ indices[numIndices++] = static_cast<uint32_t>(index);
+ }
+ indices.resize(numIndices);
+ if (heapParams) {
+ heapParams->reserve(heapParams->size() + numIndices);
+ }
+ c2_status_t status = C2_OK;
+ c2_aidl::Params aidlParams;
+ ScopedAStatus transResult = mAidlConfigurable->query(indices, true, &aidlParams);
+ if (!transResult.isOk()) {
+ if (transResult.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ status = c2_status_t(transResult.getServiceSpecificError());
+ LOG(DEBUG) << "query -- call failed: " << status << ".";
+ return status;
+ } else {
+ LOG(ERROR) << "query -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+ std::vector<C2Param*> paramPointers;
+ if (!c2_aidl::utils::ParseParamsBlob(¶mPointers, aidlParams)) {
+ LOG(ERROR) << "query -- error while parsing params.";
+ return C2_CORRUPTED;
+ }
+ return UpdateQueryResult(paramPointers, numStackIndices, stackParams, heapParams);
+ }
+
+ c2_status_t query_sm_hidl(
+ const std::vector<C2Param *> &stackParams,
+ const std::vector<C2Param::Index> &heapParamIndices,
+ std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
+ hidl_vec<c2_hidl::ParamIndex> indices(
stackParams.size() + heapParamIndices.size());
size_t numIndices = 0;
for (C2Param* const& stackParam : stackParams) {
@@ -150,23 +352,23 @@
LOG(WARNING) << "query -- null stack param encountered.";
continue;
}
- indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
+ indices[numIndices++] = static_cast<c2_hidl::ParamIndex>(stackParam->index());
}
size_t numStackIndices = numIndices;
for (const C2Param::Index& index : heapParamIndices) {
indices[numIndices++] =
- static_cast<ParamIndex>(static_cast<uint32_t>(index));
+ static_cast<c2_hidl::ParamIndex>(static_cast<uint32_t>(index));
}
indices.resize(numIndices);
if (heapParams) {
heapParams->reserve(heapParams->size() + numIndices);
}
c2_status_t status;
- Return<void> transResult = mConfigurable->query(
+ Return<void> transResult = mHidlConfigurable->query(
indices,
true,
[&status, &numStackIndices, &stackParams, heapParams](
- Status s, const Params& p) {
+ c2_hidl::Status s, const c2_hidl::Params& p) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK && status != C2_BAD_INDEX) {
LOG(DEBUG) << "query -- call failed: "
@@ -174,58 +376,13 @@
return;
}
std::vector<C2Param*> paramPointers;
- if (!parseParamsBlob(¶mPointers, p)) {
+ if (!c2_hidl::utils::parseParamsBlob(¶mPointers, p)) {
LOG(ERROR) << "query -- error while parsing params.";
status = C2_CORRUPTED;
return;
}
- size_t i = 0;
- for (auto it = paramPointers.begin();
- it != paramPointers.end(); ) {
- C2Param* paramPointer = *it;
- if (numStackIndices > 0) {
- --numStackIndices;
- if (!paramPointer) {
- LOG(WARNING) << "query -- null stack param.";
- ++it;
- continue;
- }
- for (; i < stackParams.size() && !stackParams[i]; ) {
- ++i;
- }
- if (i >= stackParams.size()) {
- LOG(ERROR) << "query -- unexpected error.";
- status = C2_CORRUPTED;
- return;
- }
- if (stackParams[i]->index() != paramPointer->index()) {
- LOG(WARNING) << "query -- param skipped: "
- "index = "
- << stackParams[i]->index() << ".";
- stackParams[i++]->invalidate();
- continue;
- }
- if (!stackParams[i++]->updateFrom(*paramPointer)) {
- LOG(WARNING) << "query -- param update failed: "
- "index = "
- << paramPointer->index() << ".";
- }
- } else {
- if (!paramPointer) {
- LOG(WARNING) << "query -- null heap param.";
- ++it;
- continue;
- }
- if (!heapParams) {
- LOG(WARNING) << "query -- "
- "unexpected extra stack param.";
- } else {
- heapParams->emplace_back(
- C2Param::Copy(*paramPointer));
- }
- }
- ++it;
- }
+ status = UpdateQueryResult(
+ paramPointers, numStackIndices, stackParams, heapParams);
});
if (!transResult.isOk()) {
LOG(ERROR) << "query -- transaction failed.";
@@ -234,15 +391,58 @@
return status;
}
- virtual c2_status_t querySupportedParams_nb(
+ c2_status_t querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override {
+ if (mAidlStore) {
+ return querySupportedParams_nb_aidl(params);
+ } else if (mHidlStore) {
+ return querySupportedParams_nb_hidl(params);
+ } else {
+ return C2_OMITTED;
+ }
+ }
+
+ c2_status_t querySupportedParams_nb_aidl(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
+ c2_status_t status = C2_OK;
+ std::vector<c2_aidl::ParamDescriptor> aidlParams;
+ ScopedAStatus transResult = mAidlConfigurable->querySupportedParams(
+ std::numeric_limits<uint32_t>::min(),
+ std::numeric_limits<uint32_t>::max(),
+ &aidlParams);
+ if (!transResult.isOk()) {
+ if (transResult.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ status = c2_status_t(transResult.getServiceSpecificError());
+ LOG(DEBUG) << "querySupportedParams -- call failed: "
+ << status << ".";
+ return status;
+ } else {
+ LOG(ERROR) << "querySupportedParams -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+
+ size_t i = params->size();
+ params->resize(i + aidlParams.size());
+ for (const c2_aidl::ParamDescriptor& sp : aidlParams) {
+ if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
+ LOG(ERROR) << "querySupportedParams -- "
+ << "invalid returned ParamDescriptor.";
+ break;
+ }
+ }
+ return status;
+ }
+
+ c2_status_t querySupportedParams_nb_hidl(
std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
c2_status_t status;
- Return<void> transResult = mConfigurable->querySupportedParams(
+ Return<void> transResult = mHidlConfigurable->querySupportedParams(
std::numeric_limits<uint32_t>::min(),
std::numeric_limits<uint32_t>::max(),
[&status, params](
- Status s,
- const hidl_vec<ParamDescriptor>& p) {
+ c2_hidl::Status s,
+ const hidl_vec<c2_hidl::ParamDescriptor>& p) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
LOG(DEBUG) << "querySupportedParams -- call failed: "
@@ -251,8 +451,8 @@
}
size_t i = params->size();
params->resize(i + p.size());
- for (const ParamDescriptor& sp : p) {
- if (!objcpy(&(*params)[i++], sp)) {
+ for (const c2_hidl::ParamDescriptor& sp : p) {
+ if (!c2_hidl::utils::objcpy(&(*params)[i++], sp)) {
LOG(ERROR) << "querySupportedParams -- "
<< "invalid returned ParamDescriptor.";
return;
@@ -266,23 +466,75 @@
return status;
}
- virtual c2_status_t querySupportedValues_sm(
+ c2_status_t querySupportedValues_sm(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const override {
+ if (mAidlStore) {
+ return querySupportedValues_sm_aidl(fields);
+ } else if (mHidlStore) {
+ return querySupportedValues_sm_hidl(fields);
+ } else {
+ return C2_OMITTED;
+ }
+ }
+
+ c2_status_t querySupportedValues_sm_aidl(
std::vector<C2FieldSupportedValuesQuery> &fields) const {
- hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
+ std::vector<c2_aidl::FieldSupportedValuesQuery> aidlFields(fields.size());
for (size_t i = 0; i < fields.size(); ++i) {
- if (!objcpy(&inFields[i], fields[i])) {
+ if (!c2_aidl::utils::ToAidl(&aidlFields[i], fields[i])) {
+ LOG(ERROR) << "querySupportedValues -- bad input";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+
+ c2_status_t status = C2_OK;
+ std::vector<c2_aidl::FieldSupportedValuesQueryResult> queryResults;
+ ScopedAStatus transResult = mAidlConfigurable->querySupportedValues(
+ aidlFields, true, &queryResults);
+ if (!transResult.isOk()) {
+ if (transResult.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ status = c2_status_t(transResult.getServiceSpecificError());
+ LOG(DEBUG) << "querySupportedValues -- call failed: "
+ << status << ".";
+ return status;
+ } else {
+ LOG(ERROR) << "querySupportedValues -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+ if (queryResults.size() != fields.size()) {
+ LOG(ERROR) << "querySupportedValues -- "
+ "input and output lists "
+ "have different sizes.";
+ return C2_CORRUPTED;
+ }
+ for (size_t i = 0; i < fields.size(); ++i) {
+ if (!c2_aidl::utils::FromAidl(&fields[i], aidlFields[i], queryResults[i])) {
+ LOG(ERROR) << "querySupportedValues -- "
+ "invalid returned value.";
+ return C2_CORRUPTED;
+ }
+ }
+ return status;
+ }
+
+ c2_status_t querySupportedValues_sm_hidl(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const {
+ hidl_vec<c2_hidl::FieldSupportedValuesQuery> inFields(fields.size());
+ for (size_t i = 0; i < fields.size(); ++i) {
+ if (!c2_hidl::utils::objcpy(&inFields[i], fields[i])) {
LOG(ERROR) << "querySupportedValues -- bad input";
return C2_TRANSACTION_FAILED;
}
}
c2_status_t status;
- Return<void> transResult = mConfigurable->querySupportedValues(
+ Return<void> transResult = mHidlConfigurable->querySupportedValues(
inFields,
true,
[&status, &inFields, &fields](
- Status s,
- const hidl_vec<FieldSupportedValuesQueryResult>& r) {
+ c2_hidl::Status s,
+ const hidl_vec<c2_hidl::FieldSupportedValuesQueryResult>& r) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
LOG(DEBUG) << "querySupportedValues -- call failed: "
@@ -297,7 +549,7 @@
return;
}
for (size_t i = 0; i < fields.size(); ++i) {
- if (!objcpy(&fields[i], inFields[i], r[i])) {
+ if (!c2_hidl::utils::objcpy(&fields[i], inFields[i], r[i])) {
LOG(ERROR) << "querySupportedValues -- "
"invalid returned value.";
status = C2_CORRUPTED;
@@ -312,31 +564,83 @@
return status;
}
- virtual C2String getName() const {
- C2String outName;
- Return<void> transResult = mConfigurable->getName(
- [&outName](const hidl_string& name) {
- outName = name.c_str();
- });
- if (!transResult.isOk()) {
- LOG(ERROR) << "getName -- transaction failed.";
+ C2String getName() const override {
+ C2String outName = "(unknown)";
+ if (mAidlStore) {
+ ScopedAStatus transResult = mAidlConfigurable->getName(&outName);
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "getName -- transaction failed.";
+ }
+ } else if (mHidlStore) {
+ Return<void> transResult = mHidlConfigurable->getName(
+ [&outName](const hidl_string& name) {
+ outName = name.c_str();
+ });
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "getName -- transaction failed.";
+ }
}
return outName;
}
- virtual std::shared_ptr<C2ParamReflector> getParamReflector() const
- override {
+ virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override {
struct SimpleParamReflector : public C2ParamReflector {
- virtual std::unique_ptr<C2StructDescriptor> describe(
+ std::unique_ptr<C2StructDescriptor> describe(
+ C2Param::CoreIndex coreIndex) const override {
+ if (mAidlBase) {
+ return describe_aidl(coreIndex);
+ } else if (mHidlBase) {
+ return describe_hidl(coreIndex);
+ } else {
+ return nullptr;
+ }
+ }
+
+ std::unique_ptr<C2StructDescriptor> describe_aidl(
C2Param::CoreIndex coreIndex) const {
- hidl_vec<ParamIndex> indices(1);
- indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
+ std::vector<int32_t> indices(1);
+ indices[0] = coreIndex.coreIndex();
std::unique_ptr<C2StructDescriptor> descriptor;
- Return<void> transResult = mBase->getStructDescriptors(
+ std::vector<c2_aidl::StructDescriptor> aidlDescs;
+ ScopedAStatus transResult = mAidlBase->getStructDescriptors(
+ indices, &aidlDescs);
+ if (!transResult.isOk()) {
+ c2_status_t status = C2_TRANSACTION_FAILED;
+ if (transResult.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ status = c2_status_t(transResult.getServiceSpecificError());
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() failed: "
+ << status << ".";
+ return nullptr;
+ }
+ }
+ if (aidlDescs.size() != 1) {
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() "
+ "returned vector of size "
+ << aidlDescs.size() << ". "
+ "It should be 1.";
+ return nullptr;
+ }
+ if (!c2_aidl::utils::FromAidl(&descriptor, aidlDescs[0])) {
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() returned "
+ "corrupted data.";
+ return nullptr;
+ }
+ return descriptor;
+ }
+
+ std::unique_ptr<C2StructDescriptor> describe_hidl(
+ C2Param::CoreIndex coreIndex) const {
+ hidl_vec<c2_hidl::ParamIndex> indices(1);
+ indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
+ std::unique_ptr<C2StructDescriptor> descriptor;
+ Return<void> transResult = mHidlBase->getStructDescriptors(
indices,
[&descriptor](
- Status s,
- const hidl_vec<StructDescriptor>& sd) {
+ c2_hidl::Status s,
+ const hidl_vec<c2_hidl::StructDescriptor>& sd) {
c2_status_t status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
LOG(DEBUG) << "SimpleParamReflector -- "
@@ -354,7 +658,7 @@
descriptor.reset();
return;
}
- if (!objcpy(&descriptor, sd[0])) {
+ if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
LOG(DEBUG) << "SimpleParamReflector -- "
"getStructDescriptors() returned "
"corrupted data.";
@@ -365,13 +669,23 @@
return descriptor;
}
- explicit SimpleParamReflector(sp<IComponentStore> base)
- : mBase(base) { }
+ explicit SimpleParamReflector(const sp<HidlComponentStore> &base)
+ : mHidlBase(base) { }
- sp<IComponentStore> mBase;
+ explicit SimpleParamReflector(const std::shared_ptr<AidlComponentStore> &base)
+ : mAidlBase(base) { }
+
+ std::shared_ptr<AidlComponentStore> mAidlBase;
+ sp<HidlComponentStore> mHidlBase;
};
- return std::make_shared<SimpleParamReflector>(mStore);
+ if (mAidlStore) {
+ return std::make_shared<SimpleParamReflector>(mAidlStore);
+ } else if (mHidlStore) {
+ return std::make_shared<SimpleParamReflector>(mHidlStore);
+ } else {
+ return nullptr;
+ }
}
virtual std::vector<std::shared_ptr<const C2Component::Traits>>
@@ -406,6 +720,12 @@
} // unnamed namespace
extern "C" void RegisterCodecServices() {
+ const bool aidlSelected = c2_aidl::utils::IsSelected();
+ constexpr int kThreadCount = 64;
+ ABinderProcess_setThreadPoolMaxThreadCount(kThreadCount);
+ ABinderProcess_startThreadPool();
+ ::android::hardware::configureRpcThreadpool(kThreadCount, false);
+
LOG(INFO) << "Creating software Codec2 service...";
std::shared_ptr<C2ComponentStore> store =
android::GetCodec2PlatformComponentStore();
@@ -417,28 +737,27 @@
using namespace ::android::hardware::media::c2;
int platformVersion = android_get_device_api_level();
+ // STOPSHIP: Remove code name checking once platform version bumps up to 35.
+ std::string codeName =
+ android::base::GetProperty("ro.build.version.codename", "");
+ if (codeName == "VanillaIceCream") {
+ platformVersion = __ANDROID_API_V__;
+ }
- if (platformVersion >= __ANDROID_API_S__) {
- android::sp<V1_2::IComponentStore> storeV1_2 =
- new V1_2::utils::ComponentStore(store);
- if (storeV1_2->registerAsService("software") != android::OK) {
- LOG(ERROR) << "Cannot register software Codec2 v1.2 service.";
- return;
- }
+ android::sp<V1_0::IComponentStore> hidlStore;
+ std::shared_ptr<c2_aidl::IComponentStore> aidlStore;
+ const char *hidlVer = "(unknown)";
+ if (aidlSelected) {
+ aidlStore = ::ndk::SharedRefBase::make<c2_aidl::utils::ComponentStore>(store);
+ } else if (platformVersion >= __ANDROID_API_S__) {
+ hidlStore = ::android::sp<V1_2::utils::ComponentStore>::make(store);
+ hidlVer = "1.2";
} else if (platformVersion == __ANDROID_API_R__) {
- android::sp<V1_1::IComponentStore> storeV1_1 =
- new V1_1::utils::ComponentStore(store);
- if (storeV1_1->registerAsService("software") != android::OK) {
- LOG(ERROR) << "Cannot register software Codec2 v1.1 service.";
- return;
- }
+ hidlStore = ::android::sp<V1_1::utils::ComponentStore>::make(store);
+ hidlVer = "1.1";
} else if (platformVersion == __ANDROID_API_Q__) {
- android::sp<V1_0::IComponentStore> storeV1_0 =
- new V1_0::utils::ComponentStore(store);
- if (storeV1_0->registerAsService("software") != android::OK) {
- LOG(ERROR) << "Cannot register software Codec2 v1.0 service.";
- return;
- }
+ hidlStore = ::android::sp<V1_0::utils::ComponentStore>::make(store);
+ hidlVer = "1.0";
} else { // platformVersion < __ANDROID_API_Q__
LOG(ERROR) << "The platform version " << platformVersion <<
" is not supported.";
@@ -448,19 +767,70 @@
using IComponentStore =
::android::hardware::media::c2::V1_0::IComponentStore;
std::string const preferredStoreName = "default";
- sp<IComponentStore> preferredStore =
- IComponentStore::getService(preferredStoreName.c_str());
- if (preferredStore) {
- ::android::SetPreferredCodec2ComponentStore(
- std::make_shared<H2C2ComponentStore>(preferredStore));
- LOG(INFO) <<
- "Preferred Codec2 store is set to \"" <<
- preferredStoreName << "\".";
+ if (aidlSelected) {
+ std::shared_ptr<c2_aidl::IComponentStore> preferredStore;
+ if (__builtin_available(android __ANDROID_API_S__, *)) {
+ std::string instanceName = ::android::base::StringPrintf(
+ "%s/%s", c2_aidl::IComponentStore::descriptor, preferredStoreName.c_str());
+ if (AServiceManager_isDeclared(instanceName.c_str())) {
+ preferredStore = c2_aidl::IComponentStore::fromBinder(::ndk::SpAIBinder(
+ AServiceManager_waitForService(instanceName.c_str())));
+ }
+ }
+ if (preferredStore) {
+ ::android::SetPreferredCodec2ComponentStore(
+ std::make_shared<H2C2ComponentStore>(preferredStore));
+ LOG(INFO) <<
+ "Preferred Codec2 AIDL store is set to \"" <<
+ preferredStoreName << "\".";
+ } else {
+ LOG(INFO) <<
+ "Preferred Codec2 AIDL store is defaulted to \"software\".";
+ }
} else {
- LOG(INFO) <<
- "Preferred Codec2 store is defaulted to \"software\".";
+ sp<IComponentStore> preferredStore =
+ IComponentStore::getService(preferredStoreName.c_str());
+ if (preferredStore) {
+ ::android::SetPreferredCodec2ComponentStore(
+ std::make_shared<H2C2ComponentStore>(preferredStore));
+ LOG(INFO) <<
+ "Preferred Codec2 HIDL store is set to \"" <<
+ preferredStoreName << "\".";
+ } else {
+ LOG(INFO) <<
+ "Preferred Codec2 HIDL store is defaulted to \"software\".";
+ }
}
}
+
+ if (platformVersion >= __ANDROID_API_V__) {
+ if (!aidlStore) {
+ aidlStore = ::ndk::SharedRefBase::make<c2_aidl::utils::ComponentStore>(
+ std::make_shared<H2C2ComponentStore>(nullptr));
+ }
+ const std::string serviceName =
+ std::string(c2_aidl::IComponentStore::descriptor) + "/software";
+ binder_exception_t ex = AServiceManager_addService(
+ aidlStore->asBinder().get(), serviceName.c_str());
+ if (ex != EX_NONE) {
+ LOG(ERROR) << "Cannot register software Codec2 AIDL service.";
+ return;
+ }
+ }
+
+ if (!hidlStore) {
+ hidlStore = ::android::sp<V1_0::utils::ComponentStore>::make(
+ std::make_shared<H2C2ComponentStore>(nullptr));
+ hidlVer = "1.0";
+ }
+ if (hidlStore->registerAsService("software") != android::OK) {
+ LOG(ERROR) << "Cannot register software Codec2 v" << hidlVer << " service.";
+ return;
+ }
+
LOG(INFO) << "Software Codec2 service created and registered.";
+
+ ABinderProcess_joinThreadPool();
+ ::android::hardware::joinRpcThreadpool();
}
diff --git a/media/module/codecserviceregistrant/fuzzer/Android.bp b/media/module/codecserviceregistrant/fuzzer/Android.bp
index 1cb8c2b..f4e8751 100644
--- a/media/module/codecserviceregistrant/fuzzer/Android.bp
+++ b/media/module/codecserviceregistrant/fuzzer/Android.bp
@@ -34,6 +34,7 @@
"libmedia_headers",
],
defaults: [
+ "libcodec2-aidl-defaults",
"libcodec2-hidl-defaults",
],
fuzz_config: {
diff --git a/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
index fba4230..4868e0c 100644
--- a/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
+++ b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
@@ -86,8 +86,8 @@
}
string const preferredStoreName = string(kServiceName);
- sp<IComponentStore> preferredStore =
- IComponentStore::getService(preferredStoreName.c_str());
+ sp<V1_0::IComponentStore> preferredStore =
+ V1_0::IComponentStore::getService(preferredStoreName.c_str());
mH2C2 = new H2C2ComponentStore(preferredStore);
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 7358398..180c150 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1890,7 +1890,7 @@
return 0;
}
if ((sampleRate == 0) ||
- !audio_is_valid_format(format) || !audio_has_proportional_frames(format) ||
+ !audio_is_valid_format(format) ||
!audio_is_input_channel(channelMask)) {
return 0;
}
@@ -1913,6 +1913,10 @@
std::vector<audio_format_t> formats = {format};
if (format != AUDIO_FORMAT_PCM_16_BIT) {
+ // For compressed format, buffer size may be queried using PCM. Allow this for compatibility
+ // in cases the primary hw dev does not support the format.
+ // TODO: replace with a table of formats and nominal buffer sizes (based on nominal bitrate
+ // and codec frame size).
formats.push_back(AUDIO_FORMAT_PCM_16_BIT);
}
@@ -2091,7 +2095,8 @@
}
}
-void AudioFlinger::ioConfigChanged(audio_io_config_event_t event,
+// Hold either AudioFlinger::mutex or ThreadBase::mutex
+void AudioFlinger::ioConfigChanged_l(audio_io_config_event_t event,
const sp<AudioIoDescriptor>& ioDesc,
pid_t pid) {
media::AudioIoConfigEvent eventAidl = VALUE_OR_FATAL(
@@ -2263,8 +2268,8 @@
}
adjAttributionSource = afutils::checkAttributionSourcePackage(
adjAttributionSource);
- // we don't yet support anything other than linear PCM
- if (!audio_is_valid_format(input.config.format) || !audio_is_linear_pcm(input.config.format)) {
+ // further format checks are performed by createRecordTrack_l()
+ if (!audio_is_valid_format(input.config.format)) {
ALOGE("createRecord() invalid format %#x", input.config.format);
lStatus = BAD_VALUE;
goto Exit;
@@ -2945,7 +2950,7 @@
latencyMs = playbackThread->latency();
// notify client processes of the new output creation
- playbackThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
+ playbackThread->ioConfigChanged_l(AUDIO_OUTPUT_OPENED);
// the first primary output opened designates the primary hw device if no HW module
// named "primary" was already loaded.
@@ -2959,7 +2964,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
}
} else {
- thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
+ thread->ioConfigChanged_l(AUDIO_OUTPUT_OPENED);
}
response->output = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
response->config = VALUE_OR_RETURN_STATUS(
@@ -2992,7 +2997,7 @@
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
// notify client processes of the new output creation
- thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
+ thread->ioConfigChanged_l(AUDIO_OUTPUT_OPENED);
return id;
}
@@ -3052,7 +3057,7 @@
mMmapThreads.removeItem(output);
ALOGD("closing mmapThread %p", mmapThread.get());
}
- ioConfigChanged(AUDIO_OUTPUT_CLOSED, sp<AudioIoDescriptor>::make(output));
+ ioConfigChanged_l(AUDIO_OUTPUT_CLOSED, sp<AudioIoDescriptor>::make(output));
mPatchPanel->notifyStreamClosed(output);
}
// The thread entity (active unit of execution) is no longer running here,
@@ -3155,7 +3160,7 @@
if (thread != 0) {
// notify client processes of the new input creation
- thread->ioConfigChanged(AUDIO_INPUT_OPENED);
+ thread->ioConfigChanged_l(AUDIO_INPUT_OPENED);
return NO_ERROR;
}
return NO_INIT;
@@ -3314,7 +3319,7 @@
dumpToThreadLog_l(mmapThread);
mMmapThreads.removeItem(input);
}
- ioConfigChanged(AUDIO_INPUT_CLOSED, sp<AudioIoDescriptor>::make(input));
+ ioConfigChanged_l(AUDIO_INPUT_CLOSED, sp<AudioIoDescriptor>::make(input));
}
// FIXME: calling thread->exit() without mutex() held should not be needed anymore now that
// we have a different lock for notification client
@@ -3694,7 +3699,8 @@
return {};
}
- return thread->outDeviceTypes();
+ audio_utils::lock_guard l(thread->mutex());
+ return thread->outDeviceTypes_l();
}
IAfPlaybackThread* AudioFlinger::fastPlaybackThread_l() const
@@ -4488,8 +4494,9 @@
}
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- sp<IAfEffectChain> ec =
- mPlaybackThreads.valueAt(i)->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+ const auto thread = mPlaybackThreads.valueAt(i);
+ audio_utils::lock_guard l(thread->mutex());
+ const sp<IAfEffectChain> ec = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
if (ec != 0 && ec->isNonOffloadableEnabled()) {
return true;
}
@@ -4749,16 +4756,6 @@
mediautils::TimeCheck::kDefaultSecondChanceDuration,
true /* crashOnTimeout */);
- // Make sure we connect to Audio Policy Service before calling into AudioFlinger:
- // - AudioFlinger can call into Audio Policy Service with its global mutex held
- // - If this is the first time Audio Policy Service is queried from inside audioserver process
- // this will trigger Audio Policy Manager initialization.
- // - Audio Policy Manager initialization calls into AudioFlinger which will try to lock
- // its global mutex and a deadlock will occur.
- if (IPCThreadState::self()->getCallingPid() != getpid()) {
- AudioSystem::get_audio_policy_service();
- }
-
return delegate();
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index e7f9255..b1751da 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -342,7 +342,8 @@
// ----- begin IAfThreadCallback interface
- bool isNonOffloadableGlobalEffectEnabled_l() const final REQUIRES(mutex());
+ bool isNonOffloadableGlobalEffectEnabled_l() const final
+ REQUIRES(mutex()) EXCLUDES_ThreadBase_Mutex;
bool btNrecIsOff() const final { return mBtNrecIsOff.load(); }
float masterVolume_l() const final REQUIRES(mutex());
bool masterMute_l() const final REQUIRES(mutex());
@@ -387,7 +388,8 @@
const audioflinger::SyncEventCallback& callBack,
const wp<IAfTrackBase>& cookie) final EXCLUDES_AudioFlinger_Mutex;
- void ioConfigChanged(audio_io_config_event_t event,
+ // Hold either AudioFlinger::mutex or ThreadBase::mutex
+ void ioConfigChanged_l(audio_io_config_event_t event,
const sp<AudioIoDescriptor>& ioDesc,
pid_t pid = 0) final EXCLUDES_AudioFlinger_ClientMutex;
void onNonOffloadableGlobalEffectEnable() final EXCLUDES_AudioFlinger_Mutex;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 0f3e130..95fed5b 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -2570,6 +2570,7 @@
uint32_t rightZero = 0;
volumeControlEffect->setVolume(&leftZero, &rightZero, true /*controller*/);
}
+ mVolumeControlEffect = volumeControlEffect;
}
mLeftVolume = newLeft;
mRightVolume = newRight;
@@ -3084,7 +3085,10 @@
return t->sampleRate();
}
-audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const {
+audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const
+NO_THREAD_SAFETY_ANALYSIS
+// calling function 'hasAudioSession_l' requires holding mutex 'ThreadBase_Mutex' exclusively
+{
const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
@@ -3120,7 +3124,10 @@
return audio_channel_count_from_out_mask(inChannelMask(id));
}
-audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const {
+audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const
+NO_THREAD_SAFETY_ANALYSIS
+// calling function 'hasAudioSession_l' requires holding mutex 'ThreadBase_Mutex' exclusively
+{
const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index aeb0fea..8869b69 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -488,8 +488,10 @@
bool isBitPerfectCompatible() const final;
// isCompatibleWithThread_l() must be called with thread->mutex() held
- bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final;
+ bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final
+ REQUIRES(audio_utils::ThreadBase_Mutex);
+ // Requires either IAfThreadBase::mutex() or EffectChain::mutex() held
bool containsHapticGeneratingEffect_l() final;
void setHapticIntensity_l(int id, os::HapticScale intensity) final;
@@ -648,7 +650,7 @@
const sp<EffectCallback> mEffectCallback;
- wp<EffectModule> mVolumeControlEffect;
+ wp<IAfEffectModule> mVolumeControlEffect;
};
class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase {
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
index fc2f805..5a7429d 100644
--- a/services/audioflinger/IAfThread.h
+++ b/services/audioflinger/IAfThread.h
@@ -70,7 +70,7 @@
virtual audio_utils::mutex& mutex() const
RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
virtual bool isNonOffloadableGlobalEffectEnabled_l() const
- REQUIRES(mutex()) = 0; // Tracks
+ REQUIRES(mutex()) EXCLUDES_ThreadBase_Mutex = 0; // Tracks
virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
virtual bool btNrecIsOff() const = 0;
virtual float masterVolume_l() const
@@ -110,7 +110,8 @@
const wp<IAfTrackBase>& cookie)
EXCLUDES_AudioFlinger_Mutex = 0;
- virtual void ioConfigChanged(audio_io_config_event_t event,
+ // Hold either AudioFlinger::mutex or ThreadBase::mutex
+ virtual void ioConfigChanged_l(audio_io_config_event_t event,
const sp<AudioIoDescriptor>& ioDesc,
pid_t pid = 0) EXCLUDES_AudioFlinger_ClientMutex = 0;
virtual void onNonOffloadableGlobalEffectEnable() EXCLUDES_AudioFlinger_Mutex = 0;
@@ -140,7 +141,7 @@
static bool isValidPcmSinkFormat(audio_format_t format);
virtual status_t readyToRun() = 0;
- virtual void clearPowerManager() = 0;
+ virtual void clearPowerManager() EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t initCheck() const = 0;
virtual type_t type() const = 0;
virtual bool isDuplicating() const = 0;
@@ -156,21 +157,23 @@
virtual size_t frameCount() const = 0;
virtual audio_channel_mask_t hapticChannelMask() const = 0;
virtual uint32_t hapticChannelCount() const = 0;
- virtual uint32_t latency_l() const = 0;
- virtual void setVolumeForOutput_l(float left, float right) const = 0;
+ virtual uint32_t latency_l() const = 0; // NO_THREAD_SAFETY_ANALYSIS
+ virtual void setVolumeForOutput_l(float left, float right) const REQUIRES(mutex()) = 0;
// Return's the HAL's frame count i.e. fast mixer buffer size.
virtual size_t frameCountHAL() const = 0;
virtual size_t frameSize() const = 0;
// Should be "virtual status_t requestExitAndWait()" and override same
// method in Thread, but Thread::requestExitAndWait() is not yet virtual.
- virtual void exit() = 0;
- virtual bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) = 0;
- virtual status_t setParameters(const String8& keyValuePairs) = 0;
- virtual String8 getParameters(const String8& keys) = 0;
- virtual void ioConfigChanged(
+ virtual void exit() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual bool checkForNewParameter_l(const String8& keyValuePair, status_t& status)
+ REQUIRES(mutex()) = 0;
+ virtual status_t setParameters(const String8& keyValuePairs) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual String8 getParameters(const String8& keys) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void ioConfigChanged_l(
audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE)
+ /* holds either AF::mutex or TB::mutex */ = 0;
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from
@@ -178,38 +181,53 @@
// status_t sendConfigEvent_l(sp<ConfigEvent>& event);
virtual void sendIoConfigEvent(
audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) EXCLUDES_ThreadBase_Mutex = 0;
virtual void sendIoConfigEvent_l(
audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
- virtual void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) = 0;
- virtual void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp) = 0;
- virtual status_t sendSetParameterConfigEvent_l(const String8& keyValuePair) = 0;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) REQUIRES(mutex()) = 0;
+ virtual void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp)
+ REQUIRES(mutex()) = 0;
+ virtual status_t sendSetParameterConfigEvent_l(const String8& keyValuePair)
+ REQUIRES(mutex()) = 0;
virtual status_t sendCreateAudioPatchConfigEvent(
- const struct audio_patch* patch, audio_patch_handle_t* handle) = 0;
- virtual status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) = 0;
+ const struct audio_patch* patch, audio_patch_handle_t* handle)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t sendUpdateOutDeviceConfigEvent(
- const DeviceDescriptorBaseVector& outDevices) = 0;
- virtual void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs) = 0;
- virtual void sendCheckOutputStageEffectsEvent() = 0;
- virtual void sendCheckOutputStageEffectsEvent_l() = 0;
- virtual void sendHalLatencyModesChangedEvent_l() = 0;
+ const DeviceDescriptorBaseVector& outDevices) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs)
+ REQUIRES(mutex()) = 0;
+ virtual void sendCheckOutputStageEffectsEvent() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void sendCheckOutputStageEffectsEvent_l()
+ REQUIRES(mutex()) = 0;
+ virtual void sendHalLatencyModesChangedEvent_l()
+ REQUIRES(mutex()) = 0;
- virtual void processConfigEvents_l() = 0;
- virtual void setCheckOutputStageEffects() = 0;
- virtual void cacheParameters_l() = 0;
+ virtual void processConfigEvents_l()
+ REQUIRES(mutex()) = 0;
+ virtual void setCheckOutputStageEffects() = 0; // no mutex needed
+ virtual void cacheParameters_l()
+ REQUIRES(mutex()) = 0;
virtual status_t createAudioPatch_l(
- const struct audio_patch* patch, audio_patch_handle_t* handle) = 0;
- virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle) = 0;
- virtual void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) = 0;
- virtual void toAudioPortConfig(struct audio_port_config* config) = 0;
- virtual void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) = 0;
+ const struct audio_patch* patch, audio_patch_handle_t* handle)
+ REQUIRES(mutex()) = 0;
+ virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle)
+ REQUIRES(mutex()) = 0;
+ virtual void updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void toAudioPortConfig(struct audio_port_config* config)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs)
+ REQUIRES(mutex()) = 0;
// see note at declaration of mStandby, mOutDevice and mInDevice
virtual bool inStandby() const = 0;
- virtual const DeviceTypeSet outDeviceTypes() const = 0;
- virtual audio_devices_t inDeviceType() const = 0;
- virtual DeviceTypeSet getDeviceTypes() const = 0;
+ virtual const DeviceTypeSet outDeviceTypes_l() const REQUIRES(mutex()) = 0;
+ virtual audio_devices_t inDeviceType_l() const REQUIRES(mutex()) = 0;
+ virtual DeviceTypeSet getDeviceTypes_l() const REQUIRES(mutex()) = 0;
virtual const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const = 0;
virtual const AudioDeviceTypeAddr& inDeviceTypeAddr() const = 0;
virtual bool isOutput() const = 0;
@@ -226,7 +244,7 @@
bool pinned,
bool probe,
bool notifyFramesProcessed)
- REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+ REQUIRES(audio_utils::AudioFlinger_Mutex) EXCLUDES_ThreadBase_Mutex = 0;
// return values for hasAudioSession (bit field)
enum effect_state {
@@ -243,28 +261,39 @@
};
// get effect chain corresponding to session Id.
- virtual sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const = 0;
+ virtual sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const
+ EXCLUDES_ThreadBase_Mutex = 0;
// same as getEffectChain() but must be called with ThreadBase mutex locked
- virtual sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const = 0;
- virtual std::vector<int> getEffectIds_l(audio_session_t sessionId) const = 0;
+ virtual sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const
+ REQUIRES(mutex()) = 0;
+ virtual std::vector<int> getEffectIds_l(audio_session_t sessionId) const
+ REQUIRES(mutex()) = 0;
// add an effect chain to the chain list (mEffectChains)
- virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
+ virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain)
+ REQUIRES(mutex()) = 0;
// remove an effect chain from the chain list (mEffectChains)
- virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
+ virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain)
+ REQUIRES(mutex()) = 0;
// lock all effect chains Mutexes. Must be called before releasing the
// ThreadBase mutex before processing the mixer and effects. This guarantees the
// integrity of the chains during the process.
// Also sets the parameter 'effectChains' to current value of mEffectChains.
- virtual void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) = 0;
+ virtual void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains)
+ REQUIRES(mutex()) = 0;
// unlock effect chains after process
- virtual void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) = 0;
+ virtual void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains)
+ EXCLUDES_ThreadBase_Mutex = 0;
// get a copy of mEffectChains vector
- virtual Vector<sp<IAfEffectChain>> getEffectChains_l() const = 0;
+ virtual Vector<sp<IAfEffectChain>> getEffectChains_l() const
+ REQUIRES(mutex()) = 0;
// set audio mode to all effect chains
- virtual void setMode(audio_mode_t mode) = 0;
+ virtual void setMode(audio_mode_t mode)
+ EXCLUDES_ThreadBase_Mutex = 0;
// get effect module with corresponding ID on specified audio session
- virtual sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const = 0;
- virtual sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const = 0;
+ virtual sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const
+ REQUIRES(mutex()) = 0;
// add and effect module. Also creates the effect chain is none exists for
// the effects audio session. Only called in a context of moving an effect
// from one thread to another
@@ -272,29 +301,36 @@
REQUIRES(audio_utils::AudioFlinger_Mutex, mutex()) = 0;
// remove and effect module. Also removes the effect chain is this was the last
// effect
- virtual void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) = 0;
+ virtual void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false)
+ REQUIRES(mutex()) = 0;
// disconnect an effect handle from module and destroy module if last handle
- virtual void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast) = 0;
+ virtual void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast)
+ EXCLUDES_ThreadBase_Mutex = 0;
// detach all tracks connected to an auxiliary effect
- virtual void detachAuxEffect_l(int effectId) = 0;
+ virtual void detachAuxEffect_l(int effectId) REQUIRES(mutex()) = 0;
// returns a combination of:
// - EFFECT_SESSION if effects on this audio session exist in one chain
// - TRACK_SESSION if tracks on this audio session exist
// - FAST_SESSION if fast tracks on this audio session exist
// - SPATIALIZED_SESSION if spatialized tracks on this audio session exist
- virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const = 0;
- virtual uint32_t hasAudioSession(audio_session_t sessionId) const = 0;
+ virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const REQUIRES(mutex()) = 0;
+ virtual uint32_t hasAudioSession(audio_session_t sessionId) const
+ EXCLUDES_ThreadBase_Mutex = 0;
// the value returned by default implementation is not important as the
// strategy is only meaningful for PlaybackThread which implements this method
- virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const = 0;
+ virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const
+ REQUIRES(mutex()) = 0;
// check if some effects must be suspended/restored when an effect is enabled
// or disabled
virtual void checkSuspendOnEffectEnabled(
- bool enabled, audio_session_t sessionId, bool threadLocked) = 0;
+ bool enabled, audio_session_t sessionId, bool threadLocked)
+ EXCLUDES_ThreadBase_Mutex = 0;
- virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ // internally static, perhaps make static member.
virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const = 0;
// Return a reference to a per-thread heap which can be used to allocate IMemory
@@ -307,33 +343,35 @@
virtual sp<IMemory> pipeMemory() const = 0;
- virtual void systemReady() = 0;
+ virtual void systemReady() EXCLUDES_ThreadBase_Mutex = 0;
// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
virtual status_t checkEffectCompatibility_l(
- const effect_descriptor_t* desc, audio_session_t sessionId) = 0;
+ const effect_descriptor_t* desc, audio_session_t sessionId) REQUIRES(mutex()) = 0;
- virtual void broadcast_l() = 0;
+ virtual void broadcast_l() REQUIRES(mutex()) = 0;
- virtual bool isTimestampCorrectionEnabled() const = 0;
+ virtual bool isTimestampCorrectionEnabled_l() const REQUIRES(mutex()) = 0;
virtual bool isMsdDevice() const = 0;
- virtual void dump(int fd, const Vector<String16>& args) = 0;
+ virtual void dump(int fd, const Vector<String16>& args) EXCLUDES_ThreadBase_Mutex = 0;
// deliver stats to mediametrics.
- virtual void sendStatistics(bool force) = 0;
+ virtual void sendStatistics(bool force) EXCLUDES_ThreadBase_Mutex = 0;
virtual audio_utils::mutex& mutex() const
RETURN_CAPABILITY(audio_utils::ThreadBase_Mutex) = 0;
- virtual void onEffectEnable(const sp<IAfEffectModule>& effect) = 0;
- virtual void onEffectDisable() = 0;
+ virtual void onEffectEnable(const sp<IAfEffectModule>& effect) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void onEffectDisable() EXCLUDES_ThreadBase_Mutex = 0;
// invalidateTracksForAudioSession_l must be called with holding mLock.
- virtual void invalidateTracksForAudioSession_l(audio_session_t sessionId) const = 0;
+ virtual void invalidateTracksForAudioSession_l(audio_session_t sessionId) const
+ REQUIRES(mutex()) = 0;
// Invalidate all the tracks with the given audio session.
- virtual void invalidateTracksForAudioSession(audio_session_t sessionId) const = 0;
+ virtual void invalidateTracksForAudioSession(audio_session_t sessionId) const
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual bool isStreamInitialized() const = 0;
virtual void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor)
@@ -341,10 +379,12 @@
virtual void stopMelComputation_l()
REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual product_strategy_t getStrategyForStream(audio_stream_type_t stream) const = 0;
+ virtual product_strategy_t getStrategyForStream(audio_stream_type_t stream) const
+ EXCLUDES_AUDIO_ALL = 0;
virtual void setEffectSuspended_l(
- const effect_uuid_t* type, bool suspend, audio_session_t sessionId) = 0;
+ const effect_uuid_t* type, bool suspend, audio_session_t sessionId)
+ REQUIRES(mutex()) = 0;
// Dynamic cast to derived interface
virtual sp<IAfDirectOutputThread> asIAfDirectOutputThread() { return nullptr; }
@@ -392,7 +432,7 @@
// return estimated latency in milliseconds, as reported by HAL
virtual uint32_t latency() const = 0; // should be in IAfThreadBase?
- virtual uint32_t& fastTrackAvailMask_l() = 0;
+ virtual uint32_t& fastTrackAvailMask_l() REQUIRES(mutex()) = 0;
virtual sp<IAfTrack> createTrack_l(
const sp<Client>& client,
@@ -418,63 +458,70 @@
bool isBitPerfect)
REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual status_t addTrack_l(const sp<IAfTrack>& track) = 0;
- virtual bool destroyTrack_l(const sp<IAfTrack>& track) = 0;
- virtual bool isTrackActive(const sp<IAfTrack>& track) const = 0;
- virtual void addOutputTrack_l(const sp<IAfTrack>& track) = 0;
+ virtual status_t addTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
+ virtual bool destroyTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
+ virtual bool isTrackActive(const sp<IAfTrack>& track) const REQUIRES(mutex()) = 0;
+ virtual void addOutputTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
- virtual AudioStreamOut* getOutput_l() const = 0;
- virtual AudioStreamOut* getOutput() const = 0;
- virtual AudioStreamOut* clearOutput() = 0;
+ virtual AudioStreamOut* getOutput_l() const REQUIRES(mutex()) = 0;
+ virtual AudioStreamOut* getOutput() const EXCLUDES_ThreadBase_Mutex = 0;
+ virtual AudioStreamOut* clearOutput() EXCLUDES_ThreadBase_Mutex = 0;
// a very large number of suspend() will eventually wraparound, but unlikely
virtual void suspend() = 0;
virtual void restore() = 0;
virtual bool isSuspended() const = 0;
- virtual status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const = 0;
+ virtual status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const
+ EXCLUDES_ThreadBase_Mutex = 0;
// Consider also removing and passing an explicit mMainBuffer initialization
// parameter to AF::IAfTrack::Track().
virtual float* sinkBuffer() const = 0;
- virtual status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) = 0;
- virtual status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) = 0;
+ virtual status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId)
+ REQUIRES(mutex()) = 0;
// called with AudioFlinger lock held
- virtual bool invalidateTracks_l(audio_stream_type_t streamType) = 0;
- virtual bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) = 0;
- virtual void invalidateTracks(audio_stream_type_t streamType) = 0;
+ virtual bool invalidateTracks_l(audio_stream_type_t streamType) REQUIRES(mutex()) = 0;
+ virtual bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) REQUIRES(mutex()) = 0;
+ virtual void invalidateTracks(audio_stream_type_t streamType)
+ EXCLUDES_ThreadBase_Mutex = 0;
// Invalidate tracks by a set of port ids. The port id will be removed from
// the given set if the corresponding track is found and invalidated.
- virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds) = 0;
+ virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds)
+ EXCLUDES_ThreadBase_Mutex = 0;
- virtual status_t getTimestamp_l(AudioTimestamp& timestamp) = 0;
- virtual void addPatchTrack(const sp<IAfPatchTrack>& track) = 0;
- virtual void deletePatchTrack(const sp<IAfPatchTrack>& track) = 0;
+ virtual status_t getTimestamp_l(AudioTimestamp& timestamp) REQUIRES(mutex()) = 0;
+ virtual void addPatchTrack(const sp<IAfPatchTrack>& track) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void deletePatchTrack(const sp<IAfPatchTrack>& track) EXCLUDES_ThreadBase_Mutex = 0;
// Return the asynchronous signal wait time.
- virtual int64_t computeWaitTimeNs_l() const = 0;
+ virtual int64_t computeWaitTimeNs_l() const REQUIRES(mutex()) = 0;
// returns true if the track is allowed to be added to the thread.
virtual bool isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format, audio_session_t sessionId,
- uid_t uid) const = 0;
+ uid_t uid) const REQUIRES(mutex()) = 0;
virtual bool supportsHapticPlayback() const = 0;
- virtual void setDownStreamPatch(const struct audio_patch* patch) = 0;
+ virtual void setDownStreamPatch(const struct audio_patch* patch)
+ EXCLUDES_ThreadBase_Mutex = 0;
- virtual IAfTrack* getTrackById_l(audio_port_handle_t trackId) = 0;
+ virtual IAfTrack* getTrackById_l(audio_port_handle_t trackId) REQUIRES(mutex()) = 0;
virtual bool hasMixer() const = 0;
virtual status_t setRequestedLatencyMode(audio_latency_mode_t mode) = 0;
- virtual status_t getSupportedLatencyModes(std::vector<audio_latency_mode_t>* modes) = 0;
+ virtual status_t getSupportedLatencyModes(std::vector<audio_latency_mode_t>* modes)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t setBluetoothVariableLatencyEnabled(bool enabled) = 0;
- virtual void setStandby() = 0;
- virtual void setStandby_l() = 0;
- virtual bool waitForHalStart() = 0;
+ virtual void setStandby() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void setStandby_l() REQUIRES(mutex()) = 0;
+ virtual bool waitForHalStart() EXCLUDES_ThreadBase_Mutex = 0;
virtual bool hasFastMixer() const = 0;
virtual FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex) const = 0;
@@ -494,9 +541,9 @@
const sp<IAfThreadCallback>& afThreadCallback, IAfPlaybackThread* mainThread,
audio_io_handle_t id, bool systemReady);
- virtual void addOutputTrack(IAfPlaybackThread* thread) = 0;
+ virtual void addOutputTrack(IAfPlaybackThread* thread) EXCLUDES_ThreadBase_Mutex = 0;
virtual uint32_t waitTimeMs() const = 0;
- virtual void removeOutputTrack(IAfPlaybackThread* thread) = 0;
+ virtual void removeOutputTrack(IAfPlaybackThread* thread) EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfRecordThread : public virtual IAfThreadBase {
@@ -521,42 +568,49 @@
status_t* status /*non-NULL*/,
audio_port_handle_t portId,
int32_t maxSharedAudioHistoryMs)
- REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual void destroyTrack_l(const sp<IAfRecordTrack>& track) = 0;
- virtual void removeTrack_l(const sp<IAfRecordTrack>& track) = 0;
+ REQUIRES(audio_utils::AudioFlinger_Mutex) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void destroyTrack_l(const sp<IAfRecordTrack>& track) REQUIRES(mutex()) = 0;
+ virtual void removeTrack_l(const sp<IAfRecordTrack>& track) REQUIRES(mutex()) = 0;
virtual status_t start(
IAfRecordTrack* recordTrack, AudioSystem::sync_event_t event,
- audio_session_t triggerSession) = 0;
+ audio_session_t triggerSession) EXCLUDES_ThreadBase_Mutex = 0;
// ask the thread to stop the specified track, and
// return true if the caller should then do it's part of the stopping process
- virtual bool stop(IAfRecordTrack* recordTrack) = 0;
+ virtual bool stop(IAfRecordTrack* recordTrack) EXCLUDES_ThreadBase_Mutex = 0;
+ // NO_THREAD_SAFETY_ANALYSIS: consider atomics
virtual AudioStreamIn* getInput() const = 0;
virtual AudioStreamIn* clearInput() = 0;
virtual status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones) const = 0;
- virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
- virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones)
+ const EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom)
+ EXCLUDES_ThreadBase_Mutex = 0;
- virtual void addPatchTrack(const sp<IAfPatchRecord>& record) = 0;
- virtual void deletePatchTrack(const sp<IAfPatchRecord>& record) = 0;
+ virtual void addPatchTrack(const sp<IAfPatchRecord>& record)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void deletePatchTrack(const sp<IAfPatchRecord>& record)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual bool fastTrackAvailable() const = 0;
virtual void setFastTrackAvailable(bool available) = 0;
- virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual bool hasFastCapture() const = 0;
- virtual void checkBtNrec() = 0;
- virtual uint32_t getInputFramesLost() const = 0;
+ virtual void checkBtNrec() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual uint32_t getInputFramesLost() const EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t shareAudioHistory(
const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
- int64_t sharedAudioStartMs = -1) = 0;
- virtual void resetAudioHistory_l() = 0;
+ int64_t sharedAudioStartMs = -1) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void resetAudioHistory_l() REQUIRES(mutex()) = 0;
};
class IAfMmapThread : public virtual IAfThreadBase {
@@ -575,26 +629,32 @@
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
audio_port_handle_t deviceId,
- audio_port_handle_t portId) = 0;
- virtual void disconnect() = 0;
+ audio_port_handle_t portId) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void disconnect() EXCLUDES_ThreadBase_Mutex = 0;
// MmapStreamInterface handling (see adapter)
virtual status_t createMmapBuffer(
- int32_t minSizeFrames, struct audio_mmap_buffer_info* info) = 0;
- virtual status_t getMmapPosition(struct audio_mmap_position* position) const = 0;
+ int32_t minSizeFrames, struct audio_mmap_buffer_info* info)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t getMmapPosition(struct audio_mmap_position* position) const
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t start(
const AudioClient& client, const audio_attributes_t* attr,
- audio_port_handle_t* handle) = 0;
- virtual status_t stop(audio_port_handle_t handle) = 0;
- virtual status_t standby() = 0;
- virtual status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const = 0;
- virtual status_t reportData(const void* buffer, size_t frameCount) = 0;
+ audio_port_handle_t* handle) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t stop(audio_port_handle_t handle) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t standby() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t reportData(const void* buffer, size_t frameCount)
+ EXCLUDES_ThreadBase_Mutex = 0;
// TODO(b/291317898) move to IAfThreadBase?
- virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds) = 0;
+ virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds)
+ EXCLUDES_ThreadBase_Mutex = 0;
// Sets the UID records silence - TODO(b/291317898) move to IAfMmapCaptureThread
- virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual sp<IAfMmapPlaybackThread> asIAfMmapPlaybackThread() { return nullptr; }
virtual sp<IAfMmapCaptureThread> asIAfMmapCaptureThread() { return nullptr; }
@@ -606,7 +666,7 @@
const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice* hwDev, AudioStreamOut* output, bool systemReady);
- virtual AudioStreamOut* clearOutput() = 0;
+ virtual AudioStreamOut* clearOutput() EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfMmapCaptureThread : public virtual IAfMmapThread {
@@ -615,7 +675,7 @@
const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice* hwDev, AudioStreamIn* input, bool systemReady);
- virtual AudioStreamIn* clearInput() = 0;
+ virtual AudioStreamIn* clearInput() EXCLUDES_ThreadBase_Mutex = 0;
};
} // namespace android
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c6b4983..9a1fe1f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -875,7 +875,7 @@
} break;
case CFG_EVENT_IO: {
IoConfigEventData *data = (IoConfigEventData *)event->mData.get();
- ioConfigChanged(data->mEvent, data->mPid, data->mPortId);
+ ioConfigChanged_l(data->mEvent, data->mPid, data->mPortId);
} break;
case CFG_EVENT_SET_PARAMETER: {
SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get();
@@ -886,22 +886,22 @@
}
} break;
case CFG_EVENT_CREATE_AUDIO_PATCH: {
- const DeviceTypeSet oldDevices = getDeviceTypes();
+ const DeviceTypeSet oldDevices = getDeviceTypes_l();
CreateAudioPatchConfigEventData *data =
(CreateAudioPatchConfigEventData *)event->mData.get();
event->mStatus = createAudioPatch_l(&data->mPatch, &data->mHandle);
- const DeviceTypeSet newDevices = getDeviceTypes();
+ const DeviceTypeSet newDevices = getDeviceTypes_l();
configChanged = oldDevices != newDevices;
mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
dumpDeviceTypes(newDevices).c_str(), toString(newDevices).c_str());
} break;
case CFG_EVENT_RELEASE_AUDIO_PATCH: {
- const DeviceTypeSet oldDevices = getDeviceTypes();
+ const DeviceTypeSet oldDevices = getDeviceTypes_l();
ReleaseAudioPatchConfigEventData *data =
(ReleaseAudioPatchConfigEventData *)event->mData.get();
event->mStatus = releaseAudioPatch_l(data->mHandle);
- const DeviceTypeSet newDevices = getDeviceTypes();
+ const DeviceTypeSet newDevices = getDeviceTypes_l();
configChanged = oldDevices != newDevices;
mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
@@ -1089,9 +1089,9 @@
}
// Note: output device may be used by capture threads for effects such as AEC.
dprintf(fd, " Output devices: %s (%s)\n",
- dumpDeviceTypes(outDeviceTypes()).c_str(), toString(outDeviceTypes()).c_str());
+ dumpDeviceTypes(outDeviceTypes_l()).c_str(), toString(outDeviceTypes_l()).c_str());
dprintf(fd, " Input device: %#x (%s)\n",
- inDeviceType(), toString(inDeviceType()).c_str());
+ inDeviceType_l(), toString(inDeviceType_l()).c_str());
dprintf(fd, " Audio source: %d (%s)\n", mAudioSource, toString(mAudioSource).c_str());
// Dump timestamp statistics for the Thread types that support it.
@@ -1102,7 +1102,8 @@
|| mType == OFFLOAD
|| mType == SPATIALIZER) {
dprintf(fd, " Timestamp stats: %s\n", mTimestampVerifier.toString().c_str());
- dprintf(fd, " Timestamp corrected: %s\n", isTimestampCorrectionEnabled() ? "yes" : "no");
+ dprintf(fd, " Timestamp corrected: %s\n",
+ isTimestampCorrectionEnabled_l() ? "yes" : "no");
}
if (mLastIoBeginNs > 0) { // MMAP may not set this
@@ -1979,7 +1980,7 @@
}
template <typename T>
-void ThreadBase::ActiveTracks<T>::updatePowerState(
+void ThreadBase::ActiveTracks<T>::updatePowerState_l(
const sp<ThreadBase>& thread, bool force) {
// Updates ActiveTracks client uids to the thread wakelock.
if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
@@ -2045,6 +2046,7 @@
// Call only from threadLoop() or when it is idle.
// Do not call from high performance code as this may do binder rpc to the MediaMetrics service.
void ThreadBase::sendStatistics(bool force)
+NO_THREAD_SAFETY_ANALYSIS
{
// Do not log if we have no stats.
// We choose the timestamp verifier because it is the most likely item to be present.
@@ -2076,8 +2078,8 @@
item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
- item->setCString(MM_PREFIX "outDevice", toString(outDeviceTypes()).c_str());
- item->setCString(MM_PREFIX "inDevice", toString(inDeviceType()).c_str());
+ item->setCString(MM_PREFIX "outDevice", toString(outDeviceTypes_l()).c_str());
+ item->setCString(MM_PREFIX "inDevice", toString(inDeviceType_l()).c_str());
// thread statistics
if (mIoJitterMs.getN() > 0) {
@@ -2358,10 +2360,7 @@
dprintf(fd, " Total writes: %d\n", mNumWrites);
dprintf(fd, " Delayed writes: %d\n", mNumDelayedWrites);
dprintf(fd, " Blocked in write: %s\n", mInWrite ? "yes" : "no");
- dprintf(fd, " Suspend count: %d\n", mSuspended);
- dprintf(fd, " Sink buffer : %p\n", mSinkBuffer);
- dprintf(fd, " Mixer buffer: %p\n", mMixerBuffer);
- dprintf(fd, " Effect buffer: %p\n", mEffectBuffer);
+ dprintf(fd, " Suspend count: %d\n", (int32_t)mSuspended);
dprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask);
dprintf(fd, " Standby delay ns=%lld\n", (long long)mStandbyDelayNs);
AudioStreamOut *output = mOutput;
@@ -2434,6 +2433,7 @@
}
if (isBitPerfect) {
+ audio_utils::lock_guard _l(mutex());
sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
if (chain.get() != nullptr) {
// Bit-perfect is required according to the configuration and preferred mixer
@@ -2791,6 +2791,8 @@
return latency_l();
}
uint32_t PlaybackThread::latency_l() const
+NO_THREAD_SAFETY_ANALYSIS
+// Fix later.
{
uint32_t latency;
if (initCheck() == NO_ERROR && mOutput->stream->getLatency(&latency) == OK) {
@@ -2858,7 +2860,6 @@
// addTrack_l() must be called with ThreadBase::mutex() held
status_t PlaybackThread::addTrack_l(const sp<IAfTrack>& track)
-NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mutex()
{
status_t status = ALREADY_EXISTS;
@@ -3026,7 +3027,7 @@
return mOutput->stream->selectPresentation(presentationId, programId);
}
-void PlaybackThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void PlaybackThread::ioConfigChanged_l(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId) {
ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event);
sp<AudioIoDescriptor> desc;
@@ -3048,7 +3049,7 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAfThreadCallback->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged_l(event, desc, pid);
}
void PlaybackThread::onWriteReady()
@@ -3234,8 +3235,8 @@
if (hasMixer()) {
mNormalFrameCount = (mNormalFrameCount + 15) & ~15;
}
- ALOGI("HAL output buffer size %zu frames, normal sink buffer size %zu frames", mFrameCount,
- mNormalFrameCount);
+ ALOGI("HAL output buffer size %zu frames, normal sink buffer size %zu frames",
+ (size_t)mFrameCount, mNormalFrameCount);
// Check if we want to throttle the processing to no more than 2x normal rate
mThreadThrottle = property_get_bool("af.thread.throttle", true /* default_value */);
@@ -3472,7 +3473,7 @@
ALOGD("ro.audio.silent is ignored since no output device is set");
return;
}
- if (isSingleDeviceType(outDeviceTypes(), AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
+ if (isSingleDeviceType(outDeviceTypes_l(), AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
ALOGD("ro.audio.silent will be ignored for threads on AUDIO_DEVICE_OUT_REMOTE_SUBMIX");
return;
}
@@ -3642,7 +3643,7 @@
// make sure standby delay is not too short when connected to an A2DP sink to avoid
// truncating audio when going to standby.
- if (!Intersection(outDeviceTypes(), getAudioDeviceOutAllA2dpSet()).empty()) {
+ if (!Intersection(outDeviceTypes_l(), getAudioDeviceOutAllA2dpSet()).empty()) {
if (mStandbyDelayNs < kDefaultStandbyTimeInNsecs) {
mStandbyDelayNs = kDefaultStandbyTimeInNsecs;
}
@@ -3990,7 +3991,7 @@
// If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
//
// Note: we access outDeviceTypes() outside of mutex().
- if (isMsdDevice() && outDeviceTypes().count(AUDIO_DEVICE_OUT_BUS) != 0) {
+ if (isMsdDevice() && outDeviceTypes_l().count(AUDIO_DEVICE_OUT_BUS) != 0) {
// Here, we try for the AF lock, but do not block on it as the latency
// is more informational.
if (mAfThreadCallback->mutex().try_lock()) {
@@ -4135,7 +4136,7 @@
// mMixerStatusIgnoringFastTracks is also updated internally
mMixerStatus = prepareTracks_l(&tracksToRemove);
- mActiveTracks.updatePowerState(this);
+ mActiveTracks.updatePowerState_l(this);
metadataUpdate = updateMetadata_l();
@@ -4508,9 +4509,10 @@
// notify of throttle end on debug log
// but prevent spamming for bluetooth
ALOGD_IF(!isSingleDeviceType(
- outDeviceTypes(), audio_is_a2dp_out_device) &&
+ outDeviceTypes_l(), audio_is_a2dp_out_device) &&
!isSingleDeviceType(
- outDeviceTypes(), audio_is_hearing_aid_out_device),
+ outDeviceTypes_l(),
+ audio_is_hearing_aid_out_device),
"mixer(%p) throttle end: throttle time(%u)", this, diff);
mThreadThrottleEndMs = mThreadThrottleTimeMs;
}
@@ -4606,7 +4608,7 @@
timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
mSampleRate);
- if (isTimestampCorrectionEnabled()) {
+ if (isTimestampCorrectionEnabled_l()) {
ALOGVV("TS_BEFORE: %d %lld %lld", id(),
(long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
(long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
@@ -4685,7 +4687,7 @@
// and we use systemTime().
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten;
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastIoBeginNs == -1
- ? systemTime() : mLastIoBeginNs;
+ ? systemTime() : (int64_t)mLastIoBeginNs;
}
for (const sp<IAfTrack>& t : mActiveTracks) {
@@ -5326,7 +5328,8 @@
// shared by MIXER and DIRECT, overridden by DUPLICATING
void PlaybackThread::threadLoop_standby()
{
- ALOGV("Audio hardware entering standby, mixer %p, suspend count %d", this, mSuspended);
+ ALOGV("%s: audio hardware entering standby, mixer %p, suspend count %d",
+ __func__, this, (int32_t)mSuspended);
mOutput->standby();
if (mUseAsyncWrite != 0) {
// discard any pending drain or write ack by incrementing sequence
@@ -6367,7 +6370,7 @@
void MixerThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
PlaybackThread::dumpInternals_l(fd, args);
- dprintf(fd, " Thread throttle time (msecs): %u\n", mThreadThrottleTimeMs);
+ dprintf(fd, " Thread throttle time (msecs): %u\n", (uint32_t)mThreadThrottleTimeMs);
dprintf(fd, " AudioMixer tracks: %s\n", mAudioMixer->trackNames().c_str());
dprintf(fd, " Master mono: %s\n", mMasterMono ? "on" : "off");
dprintf(fd, " Master balance: %f (%s)\n", mMasterBalance.load(),
@@ -7218,6 +7221,7 @@
{
if (mFlushPending || mHwPaused) {
// If a flush is pending or track was paused, just discard buffered data
+ audio_utils::lock_guard l(mutex());
flushHw_l();
} else {
mMixerStatus = MIXER_DRAIN_ALL;
@@ -7704,8 +7708,13 @@
mOutputTracks[i]->destroy();
mOutputTracks.removeAt(i);
updateWaitTime_l();
- if (thread->getOutput() == mOutput) {
- mOutput = NULL;
+ // NO_THREAD_SAFETY_ANALYSIS
+ // Lambda workaround: as thread != this
+ // we can safely call the remote thread getOutput.
+ const bool equalOutput =
+ [&](){ return thread->getOutput() == mOutput; }();
+ if (equalOutput) {
+ mOutput = nullptr;
}
return;
}
@@ -7970,10 +7979,11 @@
break;
case FastCapture_Static:
initFastCapture = !mIsMsdDevice // Disable fast capture for MSD BUS devices.
+ && audio_is_linear_pcm(mFormat)
&& (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
- ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d "
- "mIsMsdDevice = %d", this, (long long)mFrameCount, mSampleRate,
- kMinNormalCaptureBufferSizeMs, initFastCapture, mIsMsdDevice);
+ ALOGV("%p kUseFastCapture = Static, format = 0x%x, (%lld * 1000) / %u vs %u, "
+ "initFastCapture = %d, mIsMsdDevice = %d", this, mFormat, (long long)mFrameCount,
+ mSampleRate, kMinNormalCaptureBufferSizeMs, initFastCapture, mIsMsdDevice);
break;
// case FastCapture_Dynamic:
}
@@ -8117,6 +8127,9 @@
// used to request a deferred sleep, to be executed later while mutex is unlocked
uint32_t sleepUs = 0;
+ // timestamp correction enable is determined under lock, used in processing step.
+ bool timestampCorrectionEnabled = false;
+
int64_t lastLoopCountRead = -2; // never matches "previous" loop, when loopCount = 0.
// loop while there is work to do
@@ -8261,7 +8274,7 @@
}
- mActiveTracks.updatePowerState(this);
+ mActiveTracks.updatePowerState_l(this);
updateMetadata_l();
@@ -8281,6 +8294,7 @@
}
sleepUs = 0;
+ timestampCorrectionEnabled = isTimestampCorrectionEnabled_l();
lockEffectChains_l(effectChains);
}
@@ -8437,9 +8451,7 @@
&& time > mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]) {
mTimestampVerifier.add(position, time, mSampleRate);
-
- // Correct timestamps
- if (isTimestampCorrectionEnabled()) {
+ if (timestampCorrectionEnabled) {
ALOGVV("TS_BEFORE: %d %lld %lld",
id(), (long long)time, (long long)position);
auto correctedTimestamp = mTimestampVerifier.getLastCorrectedTimestamp();
@@ -9420,7 +9432,7 @@
{
// disable AEC and NS if the device is a BT SCO headset supporting those
// pre processings
- bool suspend = audio_is_bluetooth_sco_device(inDeviceType()) &&
+ bool suspend = audio_is_bluetooth_sco_device(inDeviceType_l()) &&
mAfThreadCallback->btNrecIsOff();
if (mBtNrecSuspended.exchange(suspend) != suspend) {
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9531,7 +9543,7 @@
return {};
}
-void RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void RecordThread::ioConfigChanged_l(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId) {
sp<AudioIoDescriptor> desc;
switch (event) {
@@ -9549,7 +9561,7 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAfThreadCallback->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged_l(event, desc, pid);
}
void RecordThread::readInputParameters_l()
@@ -10016,25 +10028,27 @@
void MmapThread::disconnect()
{
ActiveTracks<IAfMmapTrack> activeTracks;
+ audio_port_handle_t localPortId;
{
audio_utils::lock_guard _l(mutex());
for (const sp<IAfMmapTrack>& t : mActiveTracks) {
activeTracks.add(t);
}
+ localPortId = mPortId;
}
for (const sp<IAfMmapTrack>& t : activeTracks) {
stop(t->portId());
}
// This will decrement references and may cause the destruction of this thread.
if (isOutput()) {
- AudioSystem::releaseOutput(mPortId);
+ AudioSystem::releaseOutput(localPortId);
} else {
- AudioSystem::releaseInput(mPortId);
+ AudioSystem::releaseInput(localPortId);
}
}
-void MmapThread::configure(const audio_attributes_t* attr,
+void MmapThread::configure_l(const audio_attributes_t* attr,
audio_stream_type_t streamType __unused,
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
@@ -10051,6 +10065,7 @@
status_t MmapThread::createMmapBuffer(int32_t minSizeFrames,
struct audio_mmap_buffer_info *info)
{
+ audio_utils::lock_guard l(mutex());
if (mHalStream == 0) {
return NO_INIT;
}
@@ -10060,6 +10075,7 @@
status_t MmapThread::getMmapPosition(struct audio_mmap_position* position) const
{
+ audio_utils::lock_guard l(mutex());
if (mHalStream == 0) {
return NO_INIT;
}
@@ -10087,6 +10103,7 @@
const audio_attributes_t *attr,
audio_port_handle_t *handle)
{
+ audio_utils::lock_guard l(mutex());
ALOGV("%s clientUid %d mStandby %d mPortId %d *handle %d", __FUNCTION__,
client.attributionSource.uid, mStandby, mPortId, *handle);
if (mHalStream == 0) {
@@ -10097,7 +10114,7 @@
// For the first track, reuse portId and session allocated when the stream was opened.
if (*handle == mPortId) {
- acquireWakeLock();
+ acquireWakeLock_l();
return NO_ERROR;
}
@@ -10107,20 +10124,23 @@
const AttributionSourceState adjAttributionSource = afutils::checkAttributionSourcePackage(
client.attributionSource);
+ const auto localSessionId = mSessionId;
+ auto localAttr = mAttr;
if (isOutput()) {
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = mSampleRate;
config.channel_mask = mChannelMask;
config.format = mFormat;
- audio_stream_type_t stream = streamType();
+ audio_stream_type_t stream = streamType_l();
audio_output_flags_t flags =
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
audio_port_handle_t deviceId = mDeviceId;
std::vector<audio_io_handle_t> secondaryOutputs;
bool isSpatialized;
bool isBitPerfect;
- ret = AudioSystem::getOutputForAttr(&mAttr, &io,
- mSessionId,
+ mutex().unlock();
+ ret = AudioSystem::getOutputForAttr(&localAttr, &io,
+ localSessionId,
&stream,
adjAttributionSource,
&config,
@@ -10130,6 +10150,8 @@
&secondaryOutputs,
&isSpatialized,
&isBitPerfect);
+ mutex().lock();
+ mAttr = localAttr;
ALOGD_IF(!secondaryOutputs.empty(),
"MmapThread::start does not support secondary outputs, ignoring them");
} else {
@@ -10138,14 +10160,17 @@
config.channel_mask = mChannelMask;
config.format = mFormat;
audio_port_handle_t deviceId = mDeviceId;
- ret = AudioSystem::getInputForAttr(&mAttr, &io,
+ mutex().unlock();
+ ret = AudioSystem::getInputForAttr(&localAttr, &io,
RECORD_RIID_INVALID,
- mSessionId,
+ localSessionId,
adjAttributionSource,
&config,
AUDIO_INPUT_FLAG_MMAP_NOIRQ,
&deviceId,
&portId);
+ mutex().lock();
+ // localAttr is const for getInputForAttr.
}
// APM should not chose a different input or output stream for the same set of attributes
// and audo configuration
@@ -10156,18 +10181,20 @@
}
if (isOutput()) {
+ mutex().unlock();
ret = AudioSystem::startOutput(portId);
+ mutex().lock();
} else {
{
// Add the track record before starting input so that the silent status for the
// client can be cached.
- audio_utils::lock_guard _l(mutex());
setClientSilencedState_l(portId, false /*silenced*/);
}
+ mutex().unlock();
ret = AudioSystem::startInput(portId);
+ mutex().lock();
}
- audio_utils::lock_guard _l(mutex());
// abort if start is rejected by audio policy manager
if (ret != NO_ERROR) {
ALOGE("%s: error start rejected by AudioPolicyManager = %d", __FUNCTION__, ret);
@@ -10211,7 +10238,7 @@
mActiveTracks.add(track);
sp<IAfEffectChain> chain = getEffectChain_l(mSessionId);
if (chain != 0) {
- chain->setStrategy(getStrategyForStream(streamType()));
+ chain->setStrategy(getStrategyForStream(streamType_l()));
chain->incTrackCnt();
chain->incActiveTrackCnt();
}
@@ -10233,18 +10260,17 @@
status_t MmapThread::stop(audio_port_handle_t handle)
{
ALOGV("%s handle %d", __FUNCTION__, handle);
+ audio_utils::lock_guard l(mutex());
if (mHalStream == 0) {
return NO_INIT;
}
if (handle == mPortId) {
- releaseWakeLock();
+ releaseWakeLock_l();
return NO_ERROR;
}
- audio_utils::lock_guard _l(mutex());
-
sp<IAfMmapTrack> track;
for (const sp<IAfMmapTrack>& t : mActiveTracks) {
if (handle == t->portId()) {
@@ -10285,8 +10311,10 @@
}
status_t MmapThread::standby()
+NO_THREAD_SAFETY_ANALYSIS // clang bug
{
ALOGV("%s", __FUNCTION__);
+ audio_utils::lock_guard(mutex());
if (mHalStream == 0) {
return NO_INIT;
@@ -10300,7 +10328,7 @@
mThreadSnapshot.onEnd();
mStandby = true;
}
- releaseWakeLock();
+ releaseWakeLock_l();
return NO_ERROR;
}
@@ -10347,7 +10375,10 @@
bool MmapThread::threadLoop()
{
- checkSilentMode_l();
+ {
+ audio_utils::unique_lock _l(mutex());
+ checkSilentMode_l();
+ }
const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
@@ -10387,7 +10418,7 @@
checkInvalidTracks_l();
- mActiveTracks.updatePowerState(this);
+ mActiveTracks.updatePowerState_l(this);
updateMetadata_l();
@@ -10444,7 +10475,7 @@
return {};
}
-void MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void MmapThread::ioConfigChanged_l(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId __unused) {
sp<AudioIoDescriptor> desc;
bool isInput = false;
@@ -10466,7 +10497,7 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAfThreadCallback->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged_l(event, desc, pid);
}
status_t MmapThread::createAudioPatch_l(const struct audio_patch* patch,
@@ -10583,6 +10614,7 @@
}
void MmapThread::toAudioPortConfig(struct audio_port_config* config)
+NO_THREAD_SAFETY_ANALYSIS // mAudioHwDev handle access
{
ThreadBase::toAudioPortConfig(config);
if (isOutput()) {
@@ -10700,7 +10732,6 @@
}
void MmapThread::checkInvalidTracks_l()
-NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mutex()
{
sp<MmapStreamCallback> callback;
for (const sp<IAfMmapTrack>& track : mActiveTracks) {
@@ -10798,7 +10829,8 @@
audio_port_handle_t deviceId,
audio_port_handle_t portId)
{
- MmapThread::configure(attr, streamType, sessionId, callback, deviceId, portId);
+ audio_utils::lock_guard l(mutex());
+ MmapThread::configure_l(attr, streamType, sessionId, callback, deviceId, portId);
mStreamType = streamType;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0ca79f9..7fe6143 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -44,6 +44,13 @@
public:
static const char *threadTypeToString(type_t type);
+ // ThreadBase_ThreadLoop is a virtual mutex (always nullptr) that
+ // guards methods and variables that ONLY run and are accessed
+ // on the single threaded threadLoop().
+ //
+ // As access is by a single thread, the variables are thread safe.
+ static audio_utils::mutex* ThreadBase_ThreadLoop;
+
IAfThreadCallback* afThreadCallback() const final { return mAfThreadCallback.get(); }
ThreadBase(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
@@ -51,7 +58,7 @@
~ThreadBase() override;
status_t readyToRun() final;
- void clearPowerManager() final;
+ void clearPowerManager() final EXCLUDES_ThreadBase_Mutex;
// base for record and playback
enum {
@@ -68,11 +75,9 @@
class ConfigEventData: public RefBase {
public:
- virtual ~ConfigEventData() {}
-
virtual void dump(char *buffer, size_t size) = 0;
protected:
- ConfigEventData() {}
+ ConfigEventData() = default;
};
// Config event sequence by client if status needed (e.g binder thread calling setParameters()):
@@ -103,14 +108,22 @@
}
}
- audio_utils::mutex& mutex() const { return mMutex; }
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::ConfigEvent_Mutex) {
+ return mMutex;
+ }
const int mType; // event type e.g. CFG_EVENT_IO
mutable audio_utils::mutex mMutex; // mutex associated with mCondition
audio_utils::condition_variable mCondition; // condition for status return
+
+ // NO_THREAD_SAFETY_ANALYSIS Can we add GUARDED_BY?
status_t mStatus; // status communicated to sender
- bool mWaitStatus; // true if sender is waiting for status
- bool mRequiresSystemReady; // true if must wait for system ready to enter event queue
- sp<ConfigEventData> mData; // event specific parameter data
+
+ bool mWaitStatus GUARDED_BY(mutex()); // true if sender is waiting for status
+ // true if must wait for system ready to enter event queue
+ bool mRequiresSystemReady GUARDED_BY(mutex());
+
+ // NO_THREAD_SAFETY_ANALYSIS Can we add GUARDED_BY?
+ sp<ConfigEventData> mData; // event specific parameter data
protected:
explicit ConfigEvent(int type, bool requiresSystemReady = false) :
@@ -197,7 +210,7 @@
}
const struct audio_patch mPatch;
- audio_patch_handle_t mHandle;
+ audio_patch_handle_t mHandle; // cannot be const
};
class CreateAudioPatchConfigEvent : public ConfigEvent {
@@ -219,7 +232,7 @@
snprintf(buffer, size, "- Patch handle: %u\n", mHandle);
}
- audio_patch_handle_t mHandle;
+ const audio_patch_handle_t mHandle;
};
class ReleaseAudioPatchConfigEvent : public ConfigEvent {
@@ -240,7 +253,7 @@
snprintf(buffer, size, "- Devices: %s", android::toString(mOutDevices).c_str());
}
- DeviceDescriptorBaseVector mOutDevices;
+ const DeviceDescriptorBaseVector mOutDevices;
};
class UpdateOutDevicesConfigEvent : public ConfigEvent {
@@ -260,7 +273,7 @@
snprintf(buffer, size, "- mMaxSharedAudioHistoryMs: %d", mMaxSharedAudioHistoryMs);
}
- int32_t mMaxSharedAudioHistoryMs;
+ const int32_t mMaxSharedAudioHistoryMs;
};
class ResizeBufferConfigEvent : public ConfigEvent {
@@ -289,15 +302,14 @@
class PMDeathRecipient : public IBinder::DeathRecipient {
public:
explicit PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
- virtual ~PMDeathRecipient() {}
// IBinder::DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
+ void binderDied(const wp<IBinder>& who) final;
private:
DISALLOW_COPY_AND_ASSIGN(PMDeathRecipient);
- wp<ThreadBase> mThread;
+ const wp<ThreadBase> mThread;
};
type_t type() const final { return mType; }
@@ -311,8 +323,9 @@
uint32_t channelCount() const final { return mChannelCount; }
audio_channel_mask_t hapticChannelMask() const override { return AUDIO_CHANNEL_NONE; }
uint32_t hapticChannelCount() const override { return 0; }
- uint32_t latency_l() const override { return 0; }
- void setVolumeForOutput_l(float /* left */, float /* right */) const override {}
+ uint32_t latency_l() const override { return 0; } // NO_THREAD_SAFETY_ANALYSIS
+ void setVolumeForOutput_l(float /* left */, float /* right */) const override
+ REQUIRES(mutex()) {}
// Return's the HAL's frame count i.e. fast mixer buffer size.
size_t frameCountHAL() const final { return mFrameCount; }
@@ -320,44 +333,49 @@
// Should be "virtual status_t requestExitAndWait()" and override same
// method in Thread, but Thread::requestExitAndWait() is not yet virtual.
- void exit() final;
- status_t setParameters(const String8& keyValuePairs) final;
+ void exit() final EXCLUDES_ThreadBase_Mutex;
+ status_t setParameters(const String8& keyValuePairs) final EXCLUDES_ThreadBase_Mutex;
// sendConfigEvent_l() must be called with ThreadBase::mutex() held
// Can temporarily release the lock if waiting for a reply from
// processConfigEvents_l().
- status_t sendConfigEvent_l(sp<ConfigEvent>& event);
+ status_t sendConfigEvent_l(sp<ConfigEvent>& event) REQUIRES(mutex());
void sendIoConfigEvent(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final EXCLUDES_ThreadBase_Mutex;
void sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
- void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) final;
- void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp) final;
- status_t sendSetParameterConfigEvent_l(const String8& keyValuePair) final;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final REQUIRES(mutex());
+ void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) final
+ EXCLUDES_ThreadBase_Mutex;
+ void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp) final
+ REQUIRES(mutex());
+ status_t sendSetParameterConfigEvent_l(const String8& keyValuePair) final REQUIRES(mutex());
status_t sendCreateAudioPatchConfigEvent(const struct audio_patch* patch,
- audio_patch_handle_t* handle) final;
- status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) final;
+ audio_patch_handle_t* handle) final EXCLUDES_ThreadBase_Mutex;
+ status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) final
+ EXCLUDES_ThreadBase_Mutex;
status_t sendUpdateOutDeviceConfigEvent(
- const DeviceDescriptorBaseVector& outDevices) final;
- void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs) final;
- void sendCheckOutputStageEffectsEvent() final;
- void sendCheckOutputStageEffectsEvent_l() final;
- void sendHalLatencyModesChangedEvent_l() final;
+ const DeviceDescriptorBaseVector& outDevices) final EXCLUDES_ThreadBase_Mutex;
+ void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs) final REQUIRES(mutex());
+ void sendCheckOutputStageEffectsEvent() final EXCLUDES_ThreadBase_Mutex;
+ void sendCheckOutputStageEffectsEvent_l() final REQUIRES(mutex());
+ void sendHalLatencyModesChangedEvent_l() final REQUIRES(mutex());
- void processConfigEvents_l() final;
+ void processConfigEvents_l() final REQUIRES(mutex());
void setCheckOutputStageEffects() override {}
void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
void toAudioPortConfig(struct audio_port_config* config) override;
- void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override;
+ void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override REQUIRES(mutex());
// see note at declaration of mStandby, mOutDevice and mInDevice
bool inStandby() const override { return mStandby; }
- const DeviceTypeSet outDeviceTypes() const final {
+ const DeviceTypeSet outDeviceTypes_l() const final REQUIRES(mutex()) {
return getAudioDeviceTypes(mOutDeviceTypeAddrs);
}
- audio_devices_t inDeviceType() const final { return mInDeviceTypeAddr.mType; }
- DeviceTypeSet getDeviceTypes() const final {
- return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
+ audio_devices_t inDeviceType_l() const final REQUIRES(mutex()) {
+ return mInDeviceTypeAddr.mType;
+ }
+ DeviceTypeSet getDeviceTypes_l() const final REQUIRES(mutex()) {
+ return isOutput() ? outDeviceTypes_l() : DeviceTypeSet({inDeviceType_l()});
}
const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const final {
@@ -410,23 +428,26 @@
// get effect chain corresponding to session Id.
sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const final;
// same as getEffectChain() but must be called with ThreadBase mutex locked
- sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const final;
- std::vector<int> getEffectIds_l(audio_session_t sessionId) const final;
+ sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const final REQUIRES(mutex());
+ std::vector<int> getEffectIds_l(audio_session_t sessionId) const final REQUIRES(mutex());
// lock all effect chains Mutexes. Must be called before releasing the
// ThreadBase mutex before processing the mixer and effects. This guarantees the
// integrity of the chains during the process.
// Also sets the parameter 'effectChains' to current value of mEffectChains.
- void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) final;
+ void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) final REQUIRES(mutex());
// unlock effect chains after process
void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) final;
// get a copy of mEffectChains vector
- Vector<sp<IAfEffectChain>> getEffectChains_l() const final { return mEffectChains; };
+ Vector<sp<IAfEffectChain>> getEffectChains_l() const final REQUIRES(mutex()) {
+ return mEffectChains;
+ }
// set audio mode to all effect chains
void setMode(audio_mode_t mode) final;
// get effect module with corresponding ID on specified audio session
sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const final;
- sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const final;
+ sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const final
+ REQUIRES(mutex());
// add and effect module. Also creates the effect chain is none exists for
// the effects audio session. Only called in a context of moving an effect
// from one thread to another
@@ -434,20 +455,22 @@
REQUIRES(audio_utils::AudioFlinger_Mutex, mutex());
// remove and effect module. Also removes the effect chain is this was the last
// effect
- void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) final;
+ void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) final
+ REQUIRES(mutex());
// disconnect an effect handle from module and destroy module if last handle
void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast) final;
// detach all tracks connected to an auxiliary effect
- void detachAuxEffect_l(int /* effectId */) override {}
+ void detachAuxEffect_l(int /* effectId */) override REQUIRES(mutex()) {}
// TODO(b/291317898) - remove hasAudioSession_l below.
- uint32_t hasAudioSession_l(audio_session_t sessionId) const override = 0;
- uint32_t hasAudioSession(audio_session_t sessionId) const final {
- std::lock_guard _l(mutex());
- return hasAudioSession_l(sessionId);
- }
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override REQUIRES(mutex()) = 0;
+ uint32_t hasAudioSession(audio_session_t sessionId) const final EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard _l(mutex());
+ return hasAudioSession_l(sessionId);
+ }
template <typename T>
- uint32_t hasAudioSession_l(audio_session_t sessionId, const T& tracks) const {
+ uint32_t hasAudioSession_l(audio_session_t sessionId, const T& tracks) const
+ REQUIRES(mutex()) {
uint32_t result = 0;
if (getEffectChain_l(sessionId) != 0) {
result = EFFECT_SESSION;
@@ -476,9 +499,9 @@
// the value returned by default implementation is not important as the
// strategy is only meaningful for PlaybackThread which implements this method
product_strategy_t getStrategyForSession_l(
- audio_session_t /* sessionId */) const override {
- return static_cast<product_strategy_t>(0);
- }
+ audio_session_t /* sessionId */) const override REQUIRES(mutex()){
+ return static_cast<product_strategy_t>(0);
+ }
// check if some effects must be suspended/restored when an effect is enabled
// or disabled
@@ -497,38 +520,41 @@
sp<IMemory> pipeMemory() const override { return nullptr; }
- void systemReady() final;
+ void systemReady() final EXCLUDES_ThreadBase_Mutex;
- void broadcast_l() final;
+ void broadcast_l() final REQUIRES(mutex());
- bool isTimestampCorrectionEnabled() const override { return false; }
+ bool isTimestampCorrectionEnabled_l() const override REQUIRES(mutex()) { return false; }
bool isMsdDevice() const final { return mIsMsdDevice; }
void dump(int fd, const Vector<String16>& args) override;
// deliver stats to mediametrics.
- void sendStatistics(bool force) final;
+ void sendStatistics(bool force) final
+ REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
audio_utils::mutex& mutex() const final RETURN_CAPABILITY(audio_utils::ThreadBase_Mutex) {
return mMutex;
}
mutable audio_utils::mutex mMutex;
- void onEffectEnable(const sp<IAfEffectModule>& effect) final;
- void onEffectDisable() final;
+ void onEffectEnable(const sp<IAfEffectModule>& effect) final EXCLUDES_ThreadBase_Mutex;
+ void onEffectDisable() final EXCLUDES_ThreadBase_Mutex;
// invalidateTracksForAudioSession_l must be called with holding mutex().
- void invalidateTracksForAudioSession_l(audio_session_t /* sessionId */) const override {}
+ void invalidateTracksForAudioSession_l(audio_session_t /* sessionId */) const override
+ REQUIRES(mutex()) {}
// Invalidate all the tracks with the given audio session.
- void invalidateTracksForAudioSession(audio_session_t sessionId) const final {
- std::lock_guard _l(mutex());
+ void invalidateTracksForAudioSession(audio_session_t sessionId) const final
+ EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard _l(mutex());
invalidateTracksForAudioSession_l(sessionId);
}
template <typename T>
- void invalidateTracksForAudioSession_l(audio_session_t sessionId,
- const T& tracks) const {
+ void invalidateTracksForAudioSession_l(audio_session_t sessionId,
+ const T& tracks) const REQUIRES(mutex()) {
for (size_t i = 0; i < tracks.size(); ++i) {
const sp<IAfTrackBase>& track = tracks[i];
if (sessionId == track->sessionId()) {
@@ -553,41 +579,44 @@
effect_uuid_t mType; // effect type UUID
};
- void acquireWakeLock();
- virtual void acquireWakeLock_l();
- void releaseWakeLock();
- void releaseWakeLock_l();
- void updateWakeLockUids_l(const SortedVector<uid_t> &uids);
- void getPowerManager_l();
+ void acquireWakeLock() EXCLUDES_ThreadBase_Mutex;
+ virtual void acquireWakeLock_l() REQUIRES(mutex());
+ void releaseWakeLock() EXCLUDES_ThreadBase_Mutex;
+ void releaseWakeLock_l() REQUIRES(mutex());
+ void updateWakeLockUids_l(const SortedVector<uid_t> &uids) REQUIRES(mutex());
+ void getPowerManager_l() REQUIRES(mutex());
// suspend or restore effects of the specified type (or all if type is NULL)
// on a given session. The number of suspend requests is counted and restore
// occurs when all suspend requests are cancelled.
- void setEffectSuspended_l(const effect_uuid_t *type,
+ void setEffectSuspended_l(const effect_uuid_t *type,
bool suspend,
- audio_session_t sessionId) final;
+ audio_session_t sessionId) final REQUIRES(mutex());
// updated mSuspendedSessions when an effect is suspended or restored
- void updateSuspendedSessions_l(const effect_uuid_t *type,
+ void updateSuspendedSessions_l(const effect_uuid_t *type,
bool suspend,
- audio_session_t sessionId);
+ audio_session_t sessionId) REQUIRES(mutex());
// check if some effects must be suspended when an effect chain is added
- void checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain);
+ void checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
// sends the metadata of the active tracks to the HAL
struct MetadataUpdate {
std::vector<playback_track_metadata_v7_t> playbackMetadataUpdate;
std::vector<record_track_metadata_v7_t> recordMetadataUpdate;
};
- virtual MetadataUpdate updateMetadata_l() = 0;
+ // NO_THREAD_SAFETY_ANALYSIS, updateMetadata_l() should include ThreadBase_ThreadLoop
+ // but MmapThread::start() -> exitStandby_l() -> updateMetadata_l() prevents this.
+ virtual MetadataUpdate updateMetadata_l() REQUIRES(mutex()) = 0;
String16 getWakeLockTag();
- virtual void preExit() { }
- virtual void setMasterMono_l(bool mono __unused) { }
+ virtual void preExit() EXCLUDES_ThreadBase_Mutex {}
+ virtual void setMasterMono_l(bool mono __unused) REQUIRES(mutex()) {}
virtual bool requireMonoBlend() { return false; }
// called within the threadLoop to obtain timestamp from the HAL.
- virtual status_t threadloop_getHalTimestamp_l(
- ExtendedTimestamp *timestamp __unused) const {
+ virtual status_t threadloop_getHalTimestamp_l(
+ ExtendedTimestamp *timestamp __unused) const
+ REQUIRES(mutex(), ThreadBase_ThreadLoop) {
return INVALID_OPERATION;
}
public:
@@ -595,11 +624,12 @@
product_strategy_t getStrategyForStream(audio_stream_type_t stream) const;
protected:
- virtual void onHalLatencyModesChanged_l() {}
+ virtual void onHalLatencyModesChanged_l() REQUIRES(mutex()) {}
- virtual void dumpInternals_l(int fd __unused, const Vector<String16>& args __unused)
- { }
- virtual void dumpTracks_l(int fd __unused, const Vector<String16>& args __unused) { }
+ virtual void dumpInternals_l(int fd __unused, const Vector<String16>& args __unused)
+ REQUIRES(mutex()) {}
+ virtual void dumpTracks_l(int fd __unused, const Vector<String16>& args __unused)
+ REQUIRES(mutex()) {}
const type_t mType;
@@ -624,10 +654,14 @@
// HAL format if Fastmixer is used.
audio_format_t mHALFormat;
size_t mBufferSize; // HAL buffer size for read() or write()
- AudioDeviceTypeAddrVector mOutDeviceTypeAddrs; // output device types and addresses
- AudioDeviceTypeAddr mInDeviceTypeAddr; // input device type and address
- Vector< sp<ConfigEvent> > mConfigEvents;
- Vector< sp<ConfigEvent> > mPendingConfigEvents; // events awaiting system ready
+
+ // output device types and addresses
+ AudioDeviceTypeAddrVector mOutDeviceTypeAddrs GUARDED_BY(mutex());
+ AudioDeviceTypeAddr mInDeviceTypeAddr GUARDED_BY(mutex()); // input device type and address
+ Vector<sp<ConfigEvent>> mConfigEvents GUARDED_BY(mutex());
+
+ // events awaiting system ready
+ Vector<sp<ConfigEvent>> mPendingConfigEvents GUARDED_BY(mutex());
// These fields are written and read by thread itself without lock or barrier,
// and read by other threads without lock or barrier via standby(), outDeviceTypes()
@@ -637,17 +671,17 @@
// with possibility that it might be inconsistent with other information.
bool mStandby; // Whether thread is currently in standby.
+ // NO_THREAD_SAFETY_ANALYSIS - mPatch and mAudioSource should be guarded by mutex().
struct audio_patch mPatch;
-
audio_source_t mAudioSource;
const audio_io_handle_t mId;
- Vector<sp<IAfEffectChain>> mEffectChains;
+ Vector<sp<IAfEffectChain>> mEffectChains GUARDED_BY(mutex());
static const int kThreadNameLength = 16; // prctl(PR_SET_NAME) limit
char mThreadName[kThreadNameLength]; // guaranteed NUL-terminated
- sp<os::IPowerManager> mPowerManager;
- sp<IBinder> mWakeLockToken;
+ sp<os::IPowerManager> mPowerManager GUARDED_BY(mutex());
+ sp<IBinder> mWakeLockToken GUARDED_BY(mutex());
const sp<PMDeathRecipient> mDeathRecipient;
// list of suspended effects per session and per type. The first (outer) vector is
// keyed by session ID, the second (inner) by type UUID timeLow field
@@ -658,27 +692,31 @@
static const size_t kLogSize = 4 * 1024;
sp<NBLog::Writer> mNBLogWriter;
bool mSystemReady;
- ExtendedTimestamp mTimestamp;
- TimestampVerifier< // For timestamp statistics.
- int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
+
+ // NO_THREAD_SAFETY_ANALYSIS - mTimestamp and mTimestampVerifier should be
+ // accessed under mutex for the RecordThread.
+ ExtendedTimestamp mTimestamp;
+ TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
// DIRECT and OFFLOAD threads should reset frame count to zero on stop/flush
// TODO: add confirmation checks:
// 1) DIRECT threads and linear PCM format really resets to 0?
// 2) Is frame count really valid if not linear pcm?
// 3) Are all 64 bits of position returned, not just lowest 32 bits?
// Timestamp corrected device should be a single device.
- audio_devices_t mTimestampCorrectedDevice = AUDIO_DEVICE_NONE;
+
+ audio_devices_t mTimestampCorrectedDevice = AUDIO_DEVICE_NONE; // CONST set in ctor
// ThreadLoop statistics per iteration.
- int64_t mLastIoBeginNs = -1;
- int64_t mLastIoEndNs = -1;
+ std::atomic<int64_t> mLastIoBeginNs = -1; // set in threadLoop, read by dump()
+ int64_t mLastIoEndNs GUARDED_BY(ThreadBase_ThreadLoop) = -1;
// ThreadSnapshot is thread-safe (internally locked)
mediautils::ThreadSnapshot mThreadSnapshot;
- // This should be read under ThreadBase lock (if not on the threadLoop thread).
- audio_utils::Statistics<double> mIoJitterMs{0.995 /* alpha */};
- audio_utils::Statistics<double> mProcessTimeMs{0.995 /* alpha */};
+ audio_utils::Statistics<double> mIoJitterMs GUARDED_BY(mutex()) {0.995 /* alpha */};
+ audio_utils::Statistics<double> mProcessTimeMs GUARDED_BY(mutex()) {0.995 /* alpha */};
+
+ // NO_THREAD_SAFETY_ANALYSIS GUARDED_BY(mutex())
audio_utils::Statistics<double> mLatencyMs{0.995 /* alpha */};
audio_utils::Statistics<double> mMonopipePipeDepthStats{0.999 /* alpha */};
@@ -764,7 +802,8 @@
// ThreadBase thread.
void clear();
// periodically called in the threadLoop() to update power state uids.
- void updatePowerState(const sp<ThreadBase>& thread, bool force = false);
+ void updatePowerState_l(const sp<ThreadBase>& thread, bool force = false)
+ REQUIRES(audio_utils::ThreadBase_Mutex);
/** @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.
@@ -799,11 +838,11 @@
bool mHasChanged = false;
};
- SimpleLog mLocalLog;
+ SimpleLog mLocalLog; // locked internally
private:
- void dumpBase_l(int fd, const Vector<String16>& args);
- void dumpEffectChains_l(int fd, const Vector<String16>& args);
+ void dumpBase_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
+ void dumpEffectChains_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
};
// --- PlaybackThread ---
@@ -836,35 +875,38 @@
~PlaybackThread() override;
// Thread virtuals
- bool threadLoop() final;
+ bool threadLoop() final REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
// RefBase
void onFirstRef() override;
status_t checkEffectCompatibility_l(
- const effect_descriptor_t* desc, audio_session_t sessionId) final;
+ const effect_descriptor_t* desc, audio_session_t sessionId) final REQUIRES(mutex());
- void addOutputTrack_l(const sp<IAfTrack>& track) final {
+ void addOutputTrack_l(const sp<IAfTrack>& track) final REQUIRES(mutex()) {
mTracks.add(track);
}
protected:
// Code snippets that were lifted up out of threadLoop()
- virtual void threadLoop_mix() = 0;
- virtual void threadLoop_sleepTime() = 0;
- virtual ssize_t threadLoop_write();
- virtual void threadLoop_drain();
- virtual void threadLoop_standby();
- virtual void threadLoop_exit();
- virtual void threadLoop_removeTracks(const Vector<sp<IAfTrack>>& tracksToRemove);
+ virtual void threadLoop_mix() REQUIRES(ThreadBase_ThreadLoop) = 0;
+ virtual void threadLoop_sleepTime() REQUIRES(ThreadBase_ThreadLoop) = 0;
+ virtual ssize_t threadLoop_write() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_drain() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_standby() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_exit() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_removeTracks(const Vector<sp<IAfTrack>>& tracksToRemove)
+ REQUIRES(ThreadBase_ThreadLoop);
// prepareTracks_l reads and writes mActiveTracks, and returns
// the pending set of tracks to remove via Vector 'tracksToRemove'. The caller
// is responsible for clearing or destroying this Vector later on, when it
// is safe to do so. That will drop the final ref count and destroy the tracks.
- virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) = 0;
- void removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove);
- status_t handleVoipVolume_l(float *volume);
+ virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove)
+ REQUIRES(mutex(), ThreadBase_ThreadLoop) = 0;
+
+ void removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove) REQUIRES(mutex());
+ status_t handleVoipVolume_l(float *volume) REQUIRES(mutex());
// StreamOutHalInterfaceCallback implementation
virtual void onWriteReady();
@@ -877,9 +919,9 @@
protected:
virtual bool waitingAsyncCallback();
- virtual bool waitingAsyncCallback_l();
- virtual bool shouldStandby_l();
- virtual void onAddNewTrack_l();
+ virtual bool waitingAsyncCallback_l() REQUIRES(mutex());
+ virtual bool shouldStandby_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ virtual void onAddNewTrack_l() REQUIRES(mutex());
public: // AsyncCallbackThread
void onAsyncError(); // error reported by AsyncCallbackThread
protected:
@@ -888,20 +930,21 @@
const std::basic_string<uint8_t>& metadataBs) final;
// ThreadBase virtuals
- virtual void preExit();
+ void preExit() final EXCLUDES_ThreadBase_Mutex;
virtual bool keepWakeLock() const { return true; }
- virtual void acquireWakeLock_l() {
+ virtual void acquireWakeLock_l() REQUIRES(mutex()) {
ThreadBase::acquireWakeLock_l();
- mActiveTracks.updatePowerState(this, true /* force */);
+ mActiveTracks.updatePowerState_l(this, true /* force */);
}
- virtual void checkOutputStageEffects() {}
+ virtual void checkOutputStageEffects()
+ REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex {}
virtual void setHalLatencyMode_l() {}
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
- void dumpTracks_l(int fd, const Vector<String16>& args) final;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
+ void dumpTracks_l(int fd, const Vector<String16>& args) final REQUIRES(mutex());
public:
@@ -910,15 +953,15 @@
// return estimated latency in milliseconds, as reported by HAL
uint32_t latency() const final;
// same, but lock must already be held
- uint32_t latency_l() const final;
+ uint32_t latency_l() const final /* REQUIRES(mutex()) */; // NO_THREAD_SAFETY_ANALYSIS
// VolumeInterface
void setMasterVolume(float value) final;
- void setMasterBalance(float balance) override;
+ void setMasterBalance(float balance) override EXCLUDES_ThreadBase_Mutex;
void setMasterMute(bool muted) final;
- void setStreamVolume(audio_stream_type_t stream, float value) final;
- void setStreamMute(audio_stream_type_t stream, bool muted) final;
- float streamVolume(audio_stream_type_t stream) const final;
+ void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
+ void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
+ float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
void setVolumeForOutput_l(float left, float right) const final;
sp<IAfTrack> createTrack_l(
@@ -949,56 +992,72 @@
return mActiveTracks.indexOf(track) >= 0;
}
- AudioStreamOut* getOutput_l() const final { return mOutput; }
- AudioStreamOut* getOutput() const final;
- AudioStreamOut* clearOutput() final;
+ AudioStreamOut* getOutput_l() const final REQUIRES(mutex()) { return mOutput; }
+ AudioStreamOut* getOutput() const final EXCLUDES_ThreadBase_Mutex;
+ AudioStreamOut* clearOutput() final EXCLUDES_ThreadBase_Mutex;
+
+ // NO_THREAD_SAFETY_ANALYSIS -- probably needs a lock.
sp<StreamHalInterface> stream() const final;
- // a very large number of suspend() will eventually wraparound, but unlikely
- void suspend() final { (void) android_atomic_inc(&mSuspended); }
- void restore() final
- {
- // if restore() is done without suspend(), get back into
- // range so that the next suspend() will operate correctly
- if (android_atomic_dec(&mSuspended) <= 0) {
- android_atomic_release_store(0, &mSuspended);
- }
- }
- bool isSuspended() const final
- { return android_atomic_acquire_load(&mSuspended) > 0; }
+ // suspend(), restore(), and isSuspended() are implemented atomically.
+ void suspend() final { ++mSuspended; }
+ void restore() final {
+ // if restore() is done without suspend(), get back into
+ // range so that the next suspend() will operate correctly
+ while (true) {
+ int32_t suspended = mSuspended;
+ if (suspended <= 0) {
+ ALOGW("%s: invalid mSuspended %d <= 0", __func__, suspended);
+ return;
+ }
+ const int32_t desired = suspended - 1;
+ if (mSuspended.compare_exchange_weak(suspended, desired)) return;
+ }
+ }
+ bool isSuspended() const final { return mSuspended > 0; }
- String8 getParameters(const String8& keys);
- void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
+ String8 getParameters(const String8& keys) EXCLUDES_ThreadBase_Mutex;
+
+ // Hold either the AudioFlinger::mutex or the ThreadBase::mutex
+ void ioConfigChanged_l(audio_io_config_event_t event, pid_t pid = 0,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
- status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const final;
+ status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const final
+ EXCLUDES_ThreadBase_Mutex;
// Consider also removing and passing an explicit mMainBuffer initialization
// parameter to AF::IAfTrack::Track().
float* sinkBuffer() const final {
return reinterpret_cast<float *>(mSinkBuffer); };
- void detachAuxEffect_l(int effectId) final;
+ void detachAuxEffect_l(int effectId) final REQUIRES(mutex());
- status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) final;
- status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) final;
+ status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) final
+ EXCLUDES_ThreadBase_Mutex;
+ status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) final REQUIRES(mutex());
- status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final;
- size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final;
- uint32_t hasAudioSession_l(audio_session_t sessionId) const final {
+ status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final REQUIRES(mutex());
+ size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final REQUIRES(mutex());
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const final REQUIRES(mutex()) {
return ThreadBase::hasAudioSession_l(sessionId, mTracks);
}
- product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const final;
+ product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const final
+ REQUIRES(mutex());
- status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final
+ EXCLUDES_ThreadBase_Mutex;
+ // could be static.
bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const final;
- // called with AudioFlinger lock held
- bool invalidateTracks_l(audio_stream_type_t streamType) final;
- bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) final;
+ // Does this require the AudioFlinger mutex as well?
+ bool invalidateTracks_l(audio_stream_type_t streamType) final
+ REQUIRES(mutex());
+ bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) final
+ REQUIRES(mutex());
void invalidateTracks(audio_stream_type_t streamType) override;
// Invalidate tracks by a set of port ids. The port id will be removed from
// the given set if the corresponding track is found and invalidated.
- void invalidateTracks(std::set<audio_port_handle_t>& portIds) override;
+ void invalidateTracks(std::set<audio_port_handle_t>& portIds) override
+ EXCLUDES_ThreadBase_Mutex;
size_t frameCount() const final { return mNormalFrameCount; }
@@ -1006,30 +1065,33 @@
return mMixerChannelMask;
}
- status_t getTimestamp_l(AudioTimestamp& timestamp) final;
+ status_t getTimestamp_l(AudioTimestamp& timestamp) final
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
- void addPatchTrack(const sp<IAfPatchTrack>& track) final;
- void deletePatchTrack(const sp<IAfPatchTrack>& track) final;
+ void addPatchTrack(const sp<IAfPatchTrack>& track) final EXCLUDES_ThreadBase_Mutex;
+ void deletePatchTrack(const sp<IAfPatchTrack>& track) final EXCLUDES_ThreadBase_Mutex;
+ // NO_THREAD_SAFETY_ANALYSIS - fix this to use atomics.
void toAudioPortConfig(struct audio_port_config* config) final;
// Return the asynchronous signal wait time.
- int64_t computeWaitTimeNs_l() const override { return INT64_MAX; }
+ int64_t computeWaitTimeNs_l() const override REQUIRES(mutex()) { return INT64_MAX; }
// returns true if the track is allowed to be added to the thread.
bool isTrackAllowed_l(
audio_channel_mask_t channelMask __unused,
audio_format_t format __unused,
audio_session_t sessionId __unused,
- uid_t uid) const override {
+ uid_t uid) const override REQUIRES(mutex()) {
return trackCountForUid_l(uid) < PlaybackThread::kMaxTracksPerUid
&& mTracks.size() < PlaybackThread::kMaxTracks;
}
- bool isTimestampCorrectionEnabled() const final {
- return audio_is_output_devices(mTimestampCorrectedDevice)
- && outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
+ bool isTimestampCorrectionEnabled_l() const final REQUIRES(mutex()) {
+ return audio_is_output_devices(mTimestampCorrectedDevice)
+ && outDeviceTypes_l().count(mTimestampCorrectedDevice) != 0;
}
+ // NO_THREAD_SAFETY_ANALYSIS - fix this to be atomic.
bool isStreamInitialized() const final {
return !(mOutput == nullptr || mOutput->stream == nullptr);
}
@@ -1046,12 +1108,12 @@
return (mHapticChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE;
}
- void setDownStreamPatch(const struct audio_patch* patch) final {
- std::lock_guard _l(mutex());
+ void setDownStreamPatch(const struct audio_patch* patch) final EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard _l(mutex());
mDownStreamPatch = *patch;
}
- IAfTrack* getTrackById_l(audio_port_handle_t trackId) final;
+ IAfTrack* getTrackById_l(audio_port_handle_t trackId) final REQUIRES(mutex());
bool hasMixer() const final {
return mType == MIXER || mType == DUPLICATING || mType == SPATIALIZER;
@@ -1074,19 +1136,19 @@
void stopMelComputation_l() override
REQUIRES(audio_utils::AudioFlinger_Mutex);
- void setStandby() final {
- std::lock_guard _l(mutex());
+ void setStandby() final EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard _l(mutex());
setStandby_l();
}
- void setStandby_l() final {
+ void setStandby_l() final REQUIRES(mutex()) {
mStandby = true;
mHalStarted = false;
mKernelPositionOnStandby =
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
}
- bool waitForHalStart() final {
+ bool waitForHalStart() final EXCLUDES_ThreadBase_Mutex {
audio_utils::unique_lock _l(mutex());
static const nsecs_t kWaitHalTimeoutNs = seconds(2);
nsecs_t endWaitTimetNs = systemTime() + kWaitHalTimeoutNs;
@@ -1104,10 +1166,17 @@
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
- bool mThreadThrottle; // throttle the thread processing
- uint32_t mThreadThrottleTimeMs; // throttle time for MIXER threads
- uint32_t mThreadThrottleEndMs; // notify once per throttling
- uint32_t mHalfBufferMs; // half the buffer size in milliseconds
+ // throttle the thread processing
+ bool mThreadThrottle GUARDED_BY(ThreadBase_ThreadLoop);
+
+ // throttle time for MIXER threads - atomic as read by dump()
+ std::atomic<uint32_t> mThreadThrottleTimeMs;
+
+ // notify once per throttling
+ uint32_t mThreadThrottleEndMs GUARDED_BY(ThreadBase_ThreadLoop);
+
+ // half the buffer size in milliseconds
+ uint32_t mHalfBufferMs GUARDED_BY(ThreadBase_ThreadLoop);
void* mSinkBuffer; // frame size aligned sink buffer
@@ -1127,21 +1196,21 @@
// buffer before downmixing or data conversion to the sink buffer.
// Set to "true" to enable the Mixer Buffer otherwise mixer output goes to sink buffer.
- bool mMixerBufferEnabled;
+ bool mMixerBufferEnabled GUARDED_BY(ThreadBase_ThreadLoop);
// Storage, 32 byte aligned (may make this alignment a requirement later).
// Due to constraints on mNormalFrameCount, the buffer size is a multiple of 16 frames.
- void* mMixerBuffer;
+ void* mMixerBuffer GUARDED_BY(ThreadBase_ThreadLoop);
// Size of mMixerBuffer in bytes: mNormalFrameCount * #channels * sampsize.
- size_t mMixerBufferSize;
+ size_t mMixerBufferSize GUARDED_BY(ThreadBase_ThreadLoop);
// The audio format of mMixerBuffer. Set to AUDIO_FORMAT_PCM_(FLOAT|16_BIT) only.
- audio_format_t mMixerBufferFormat;
+ audio_format_t mMixerBufferFormat GUARDED_BY(ThreadBase_ThreadLoop);
// An internal flag set to true by MixerThread::prepareTracks_l()
// when mMixerBuffer contains valid data after mixing.
- bool mMixerBufferValid;
+ bool mMixerBufferValid GUARDED_BY(ThreadBase_ThreadLoop);
// Effects Buffer (mEffectsBuffer*)
//
@@ -1150,46 +1219,49 @@
// to the sink buffer.
// Set to "true" to enable the Effects Buffer otherwise effects output goes to sink buffer.
- bool mEffectBufferEnabled;
+ bool mEffectBufferEnabled;
+ // NO_THREAD_SAFETY_ANALYSIS: Spatializer access this in addEffectChain_l()
// Storage, 32 byte aligned (may make this alignment a requirement later).
// Due to constraints on mNormalFrameCount, the buffer size is a multiple of 16 frames.
- void* mEffectBuffer;
+ void* mEffectBuffer;
+ // NO_THREAD_SAFETY_ANALYSIS: Spatializer access this in addEffectChain_l()
// Size of mEffectsBuffer in bytes: mNormalFrameCount * #channels * sampsize.
- size_t mEffectBufferSize;
+ size_t mEffectBufferSize;
+ // NO_THREAD_SAFETY_ANALYSIS: Spatializer access this in addEffectChain_l()
// The audio format of mEffectsBuffer. Set to AUDIO_FORMAT_PCM_16_BIT only.
- audio_format_t mEffectBufferFormat;
+ // NO_THREAD_SAFETY_ANALYSIS: Spatializer access this in addEffectChain_l()
+ audio_format_t mEffectBufferFormat;
// An internal flag set to true by MixerThread::prepareTracks_l()
// when mEffectsBuffer contains valid data after mixing.
//
// When this is set, all mixer data is routed into the effects buffer
// for any processing (including output processing).
- bool mEffectBufferValid;
+ bool mEffectBufferValid GUARDED_BY(ThreadBase_ThreadLoop);
// Set to "true" to enable when data has already copied to sink
- bool mHasDataCopiedToSinkBuffer = false;
+ bool mHasDataCopiedToSinkBuffer GUARDED_BY(ThreadBase_ThreadLoop) = false;
// Frame size aligned buffer used as input and output to all post processing effects
// except the Spatializer in a SPATIALIZER thread. Non spatialized tracks are mixed into
// this buffer so that post processing effects can be applied.
- void* mPostSpatializerBuffer = nullptr;
+ void* mPostSpatializerBuffer GUARDED_BY(mutex()) = nullptr;
// Size of mPostSpatializerBuffer in bytes
- size_t mPostSpatializerBufferSize;
-
+ size_t mPostSpatializerBufferSize GUARDED_BY(mutex());
// suspend count, > 0 means suspended. While suspended, the thread continues to pull from
// tracks and mix, but doesn't write to HAL. A2DP and SCO HAL implementations can't handle
// concurrent use of both of them, so Audio Policy Service suspends one of the threads to
// workaround that restriction.
// 'volatile' means accessed via atomic operations and no lock.
- volatile int32_t mSuspended;
+ std::atomic<int32_t> mSuspended;
int64_t mBytesWritten;
- std::atomic<int64_t> mFramesWritten; // not reset on standby
+ std::atomic<int64_t> mFramesWritten; // not reset on standby
int64_t mLastFramesWritten = -1; // track changes in timestamp
// server frames written.
int64_t mSuspendedFrames; // not reset on standby
@@ -1204,8 +1276,8 @@
// mMasterMute is in both PlaybackThread and in AudioFlinger. When a
// PlaybackThread needs to find out if master-muted, it checks it's local
// copy rather than the one in AudioFlinger. This optimization saves a lock.
- bool mMasterMute;
- void setMasterMute_l(bool muted) { mMasterMute = muted; }
+ bool mMasterMute GUARDED_BY(mutex());
+ void setMasterMute_l(bool muted) REQUIRES(mutex()) { mMasterMute = muted; }
auto discontinuityForStandbyOrFlush() const { // call on threadLoop or with lock.
return ((mType == DIRECT && !audio_is_linear_pcm(mFormat))
@@ -1224,24 +1296,28 @@
// No sleep in standby mode; waits on a condition
// Code snippets that are temporarily lifted up out of threadLoop() until the merge
- virtual void checkSilentMode_l() final; // consider unification with MMapThread
+
+ // consider unification with MMapThread
+ virtual void checkSilentMode_l() final REQUIRES(mutex());
// Non-trivial for DUPLICATING only
- virtual void saveOutputTracks() { }
- virtual void clearOutputTracks() { }
+ virtual void saveOutputTracks() REQUIRES(ThreadBase_ThreadLoop) {}
+ virtual void clearOutputTracks() REQUIRES(ThreadBase_ThreadLoop) {}
// Cache various calculated values, at threadLoop() entry and after a parameter change
- virtual void cacheParameters_l();
+ virtual void cacheParameters_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
void setCheckOutputStageEffects() override {
mCheckOutputStageEffects.store(true);
}
- virtual uint32_t correctLatency_l(uint32_t latency) const;
+ virtual uint32_t correctLatency_l(uint32_t latency) const REQUIRES(mutex());
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
- audio_patch_handle_t *handle);
- virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
+ audio_patch_handle_t *handle) REQUIRES(mutex());
+ virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle)
+ REQUIRES(mutex());
+ // NO_THREAD_SAFETY_ANALYSIS - fix this to use atomics
bool usesHwAvSync() const final { return mType == DIRECT && mOutput != nullptr
&& mHwSupportsPause
&& (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
@@ -1249,22 +1325,23 @@
uint32_t trackCountForUid_l(uid_t uid) const;
void invalidateTracksForAudioSession_l(
- audio_session_t sessionId) const override {
+ audio_session_t sessionId) const override REQUIRES(mutex()) {
ThreadBase::invalidateTracksForAudioSession_l(sessionId, mTracks);
}
DISALLOW_COPY_AND_ASSIGN(PlaybackThread);
- status_t addTrack_l(const sp<IAfTrack>& track) final;
- bool destroyTrack_l(const sp<IAfTrack>& track) final;
+ status_t addTrack_l(const sp<IAfTrack>& track) final REQUIRES(mutex());
+ bool destroyTrack_l(const sp<IAfTrack>& track) final REQUIRES(mutex());
- void removeTrack_l(const sp<IAfTrack>& track);
+ void removeTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex());
- void readOutputParameters_l();
- MetadataUpdate updateMetadata_l() final;
- virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata);
+ void readOutputParameters_l() REQUIRES(mutex());
+ MetadataUpdate updateMetadata_l() final REQUIRES(mutex());
+ virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata)
+ REQUIRES(mutex()) ;
- void collectTimestamps_l();
+ void collectTimestamps_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
// The Tracks class manages tracks added and removed from the Thread.
template <typename T>
@@ -1340,17 +1417,17 @@
uint32_t mSleepTimeUs;
// mixer status returned by prepareTracks_l()
- mixer_state mMixerStatus; // current cycle
+ mixer_state mMixerStatus GUARDED_BY(ThreadBase_ThreadLoop); // current cycle
// previous cycle when in prepareTracks_l()
- mixer_state mMixerStatusIgnoringFastTracks;
+ mixer_state mMixerStatusIgnoringFastTracks GUARDED_BY(ThreadBase_ThreadLoop);
// FIXME or a separate ready state per track
// FIXME move these declarations into the specific sub-class that needs them
// MIXER only
- uint32_t sleepTimeShift;
+ uint32_t sleepTimeShift GUARDED_BY(ThreadBase_ThreadLoop);
// same as AudioFlinger::mStandbyTimeInNsecs except for DIRECT which uses a shorter value
- nsecs_t mStandbyDelayNs;
+ nsecs_t mStandbyDelayNs; // GUARDED_BY(mutex());
// MIXER only
nsecs_t maxPeriod;
@@ -1358,8 +1435,8 @@
// DUPLICATING only
uint32_t writeFrames;
- size_t mBytesRemaining;
- size_t mCurrentWriteLength;
+ size_t mBytesRemaining GUARDED_BY(ThreadBase_ThreadLoop);
+ size_t mCurrentWriteLength GUARDED_BY(ThreadBase_ThreadLoop);
bool mUseAsyncWrite;
// mWriteAckSequence contains current write sequence on bits 31-1. The write sequence is
// incremented each time a write(), a flush() or a standby() occurs.
@@ -1412,7 +1489,7 @@
protected:
// accessed by both binder threads and within threadLoop(), lock on mutex needed
- uint32_t& fastTrackAvailMask_l() final { return mFastTrackAvailMask; }
+ uint32_t& fastTrackAvailMask_l() final REQUIRES(mutex()) { return mFastTrackAvailMask; }
uint32_t mFastTrackAvailMask; // bit i set if fast track [i] is available
bool mHwSupportsPause;
bool mHwPaused;
@@ -1481,18 +1558,20 @@
// Thread virtuals
- bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final;
+ bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final
+ REQUIRES(mutex());
bool isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
- audio_session_t sessionId, uid_t uid) const final;
+ audio_session_t sessionId, uid_t uid) const final REQUIRES(mutex());
protected:
- mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) override;
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) override
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
uint32_t idleSleepTimeUs() const final;
uint32_t suspendSleepTimeUs() const final;
- void cacheParameters_l() override;
+ void cacheParameters_l() override REQUIRES(mutex(), ThreadBase_ThreadLoop);
- void acquireWakeLock_l() final {
+ void acquireWakeLock_l() final REQUIRES(mutex()) {
PlaybackThread::acquireWakeLock_l();
if (hasFastMixer()) {
mFastMixer->setBoottimeOffset(
@@ -1500,18 +1579,19 @@
}
}
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
// threadLoop snippets
- ssize_t threadLoop_write() override;
- void threadLoop_standby() override;
- void threadLoop_mix() override;
- void threadLoop_sleepTime() override;
- uint32_t correctLatency_l(uint32_t latency) const final;
+ ssize_t threadLoop_write() override REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_standby() override REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_mix() override REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_sleepTime() override REQUIRES(ThreadBase_ThreadLoop);
+ uint32_t correctLatency_l(uint32_t latency) const final REQUIRES(mutex());
status_t createAudioPatch_l(
- const struct audio_patch* patch, audio_patch_handle_t* handle) final;
- status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final;
+ const struct audio_patch* patch, audio_patch_handle_t* handle)
+ final REQUIRES(mutex());
+ status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final REQUIRES(mutex());
AudioMixer* mAudioMixer; // normal mixer
@@ -1540,7 +1620,7 @@
// accessible only within the threadLoop(), no locks required
// mFastMixer->sq() // for mutating and pushing state
- int32_t mFastMixerFutex; // for cold idle
+ int32_t mFastMixerFutex GUARDED_BY(ThreadBase_ThreadLoop); // for cold idle
std::atomic_bool mMasterMono;
public:
@@ -1550,8 +1630,9 @@
return mFastMixerDumpState.mTracks[fastIndex].mUnderruns;
}
- status_t threadloop_getHalTimestamp_l(
- ExtendedTimestamp *timestamp) const override {
+ status_t threadloop_getHalTimestamp_l(
+ ExtendedTimestamp *timestamp) const override
+ REQUIRES(mutex(), ThreadBase_ThreadLoop) {
if (mNormalSink.get() != nullptr) {
return mNormalSink->getTimestamp(*timestamp);
}
@@ -1575,16 +1656,16 @@
// and blending without limiter is idempotent but inefficient to do twice.
virtual bool requireMonoBlend() { return mMasterMono.load() && !hasFastMixer(); }
- void setMasterBalance(float balance) override {
+ void setMasterBalance(float balance) override EXCLUDES_ThreadBase_Mutex {
mMasterBalance.store(balance);
if (hasFastMixer()) {
mFastMixer->setMasterBalance(balance);
}
}
- void updateHalSupportedLatencyModes_l();
- void onHalLatencyModesChanged_l() override;
- void setHalLatencyMode_l() override;
+ void updateHalSupportedLatencyModes_l() REQUIRES(mutex());
+ void onHalLatencyModesChanged_l() override REQUIRES(mutex());
+ void setHalLatencyMode_l() override REQUIRES(mutex());
};
class DirectOutputThread : public PlaybackThread, public virtual IAfDirectOutputThread {
@@ -1599,35 +1680,36 @@
const audio_offload_info_t& offloadInfo)
: DirectOutputThread(afThreadCallback, output, id, DIRECT, systemReady, offloadInfo) { }
- virtual ~DirectOutputThread();
+ ~DirectOutputThread() override;
status_t selectPresentation(int presentationId, int programId) final;
// Thread virtuals
virtual bool checkForNewParameter_l(const String8& keyValuePair,
- status_t& status);
+ status_t& status) REQUIRES(mutex());
- void flushHw_l() override;
+ void flushHw_l() override REQUIRES(mutex(), ThreadBase_ThreadLoop);
- void setMasterBalance(float balance) override;
+ void setMasterBalance(float balance) override EXCLUDES_ThreadBase_Mutex;
protected:
virtual uint32_t activeSleepTimeUs() const;
virtual uint32_t idleSleepTimeUs() const;
virtual uint32_t suspendSleepTimeUs() const;
- virtual void cacheParameters_l();
+ virtual void cacheParameters_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
// threadLoop snippets
- virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
- virtual void threadLoop_mix();
- virtual void threadLoop_sleepTime();
- virtual void threadLoop_exit();
- virtual bool shouldStandby_l();
+ virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove)
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ virtual void threadLoop_mix() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_sleepTime() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_exit() REQUIRES(ThreadBase_ThreadLoop);
+ virtual bool shouldStandby_l() REQUIRES(mutex());
- virtual void onAddNewTrack_l();
+ virtual void onAddNewTrack_l() REQUIRES(mutex());
const audio_offload_info_t mOffloadInfo;
@@ -1637,7 +1719,7 @@
DirectOutputThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
const audio_offload_info_t& offloadInfo);
- void processVolume_l(IAfTrack *track, bool lastTrack);
+ void processVolume_l(IAfTrack *track, bool lastTrack) REQUIRES(mutex());
bool isTunerStream() const { return (mOffloadInfo.content_id > 0); }
// prepareTracks_l() tells threadLoop_mix() the name of the single active track
@@ -1652,7 +1734,7 @@
public:
virtual bool hasFastMixer() const { return false; }
- virtual int64_t computeWaitTimeNs_l() const override;
+ virtual int64_t computeWaitTimeNs_l() const override REQUIRES(mutex());
status_t threadloop_getHalTimestamp_l(ExtendedTimestamp *timestamp) const override {
// For DIRECT and OFFLOAD threads, query the output sink directly.
@@ -1679,19 +1761,20 @@
audio_io_handle_t id, bool systemReady,
const audio_offload_info_t& offloadInfo);
virtual ~OffloadThread() {};
- void flushHw_l() override;
+ void flushHw_l() final REQUIRES(mutex(), ThreadBase_ThreadLoop);
protected:
// threadLoop snippets
- virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
- virtual void threadLoop_exit();
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) final
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ void threadLoop_exit() final REQUIRES(ThreadBase_ThreadLoop);
- virtual bool waitingAsyncCallback();
- virtual bool waitingAsyncCallback_l();
- virtual void invalidateTracks(audio_stream_type_t streamType);
- void invalidateTracks(std::set<audio_port_handle_t>& portIds) override;
+ bool waitingAsyncCallback() final;
+ bool waitingAsyncCallback_l() final REQUIRES(mutex());
+ void invalidateTracks(audio_stream_type_t streamType) final EXCLUDES_ThreadBase_Mutex;
+ void invalidateTracks(std::set<audio_port_handle_t>& portIds) final EXCLUDES_ThreadBase_Mutex;
- virtual bool keepWakeLock() const { return (mKeepWakeLock || (mDrainSequence & 1)); }
+ bool keepWakeLock() const final { return (mKeepWakeLock || (mDrainSequence & 1)); }
private:
size_t mPausedWriteLength; // length in bytes of write interrupted by pause
@@ -1704,10 +1787,10 @@
explicit AsyncCallbackThread(const wp<PlaybackThread>& playbackThread);
// Thread virtuals
- virtual bool threadLoop();
+ bool threadLoop() final;
// RefBase
- virtual void onFirstRef();
+ void onFirstRef() final;
void exit();
void setWriteBlocked(uint32_t sequence);
@@ -1730,7 +1813,9 @@
mutable audio_utils::mutex mMutex;
bool mAsyncError;
- audio_utils::mutex& mutex() const { return mMutex; }
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::AsyncCallbackThread_Mutex) {
+ return mMutex;
+ }
};
class DuplicatingThread : public MixerThread, public IAfDuplicatingThread {
@@ -1745,41 +1830,42 @@
}
// Thread virtuals
- void addOutputTrack(IAfPlaybackThread* thread) final;
- void removeOutputTrack(IAfPlaybackThread* thread) final;
+ void addOutputTrack(IAfPlaybackThread* thread) final EXCLUDES_ThreadBase_Mutex;
+ void removeOutputTrack(IAfPlaybackThread* thread) final EXCLUDES_ThreadBase_Mutex;
uint32_t waitTimeMs() const final { return mWaitTimeMs; }
void sendMetadataToBackend_l(
- const StreamOutHalInterface::SourceMetadata& metadata) override;
+ const StreamOutHalInterface::SourceMetadata& metadata) final REQUIRES(mutex());
protected:
virtual uint32_t activeSleepTimeUs() const;
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) final REQUIRES(mutex());
private:
- bool outputsReady();
+ bool outputsReady() REQUIRES(ThreadBase_ThreadLoop);
protected:
// threadLoop snippets
- virtual void threadLoop_mix();
- virtual void threadLoop_sleepTime();
- virtual ssize_t threadLoop_write();
- virtual void threadLoop_standby();
- virtual void cacheParameters_l();
+ void threadLoop_mix() final REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_sleepTime() final REQUIRES(ThreadBase_ThreadLoop);
+ ssize_t threadLoop_write() final REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_standby() final REQUIRES(ThreadBase_ThreadLoop);
+ void cacheParameters_l() final REQUIRES(mutex(), ThreadBase_ThreadLoop);
private:
// called from threadLoop, addOutputTrack, removeOutputTrack
- virtual void updateWaitTime_l();
+ void updateWaitTime_l() REQUIRES(mutex());
protected:
- virtual void saveOutputTracks();
- virtual void clearOutputTracks();
+ void saveOutputTracks() final REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ void clearOutputTracks() final REQUIRES(mutex(), ThreadBase_ThreadLoop);
private:
uint32_t mWaitTimeMs;
- SortedVector <sp<IAfOutputTrack>> outputTracks;
- SortedVector <sp<IAfOutputTrack>> mOutputTracks;
+ // NO_THREAD_SAFETY_ANALYSIS GUARDED_BY(ThreadBase_ThreadLoop)
+ SortedVector <sp<IAfOutputTrack>> outputTracks;
+ SortedVector <sp<IAfOutputTrack>> mOutputTracks GUARDED_BY(mutex());
public:
virtual bool hasFastMixer() const { return false; }
status_t threadloop_getHalTimestamp_l(
- ExtendedTimestamp *timestamp) const override {
+ ExtendedTimestamp *timestamp) const override REQUIRES(mutex()) {
if (mOutputTracks.size() > 0) {
// forward the first OutputTrack's kernel information for timestamp.
const ExtendedTimestamp trackTimestamp =
@@ -1806,11 +1892,12 @@
bool hasFastMixer() const final { return false; }
- status_t setRequestedLatencyMode(audio_latency_mode_t mode) final;
+ status_t setRequestedLatencyMode(audio_latency_mode_t mode) final EXCLUDES_ThreadBase_Mutex;
protected:
- void checkOutputStageEffects() final;
- void setHalLatencyMode_l() final;
+ void checkOutputStageEffects() final
+ REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
+ void setHalLatencyMode_l() final REQUIRES(mutex());
private:
// Do not request a specific mode by default
@@ -1836,15 +1923,15 @@
~RecordThread() override;
// no addTrack_l ?
- void destroyTrack_l(const sp<IAfRecordTrack>& track) final;
- void removeTrack_l(const sp<IAfRecordTrack>& track) final;
+ void destroyTrack_l(const sp<IAfRecordTrack>& track) final REQUIRES(mutex());
+ void removeTrack_l(const sp<IAfRecordTrack>& track) final REQUIRES(mutex());
// Thread virtuals
- bool threadLoop() final;
- void preExit() final;
+ bool threadLoop() final REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
+ void preExit() final EXCLUDES_ThreadBase_Mutex;
// RefBase
- void onFirstRef() final;
+ void onFirstRef() final EXCLUDES_ThreadBase_Mutex;
status_t initCheck() const final { return mInput == nullptr ? NO_INIT : NO_ERROR; }
@@ -1868,15 +1955,15 @@
status_t *status /*non-NULL*/,
audio_port_handle_t portId,
int32_t maxSharedAudioHistoryMs) final
- REQUIRES(audio_utils::AudioFlinger_Mutex);
+ REQUIRES(audio_utils::AudioFlinger_Mutex) EXCLUDES_ThreadBase_Mutex;
status_t start(IAfRecordTrack* recordTrack,
AudioSystem::sync_event_t event,
- audio_session_t triggerSession) final;
+ audio_session_t triggerSession) final EXCLUDES_ThreadBase_Mutex;
// ask the thread to stop the specified track, and
// return true if the caller should then do it's part of the stopping process
- bool stop(IAfRecordTrack* recordTrack) final;
+ bool stop(IAfRecordTrack* recordTrack) final EXCLUDES_ThreadBase_Mutex;
AudioStreamIn* getInput() const final { return mInput; }
AudioStreamIn* clearInput() final;
@@ -1884,27 +1971,30 @@
virtual sp<StreamHalInterface> stream() const;
- virtual bool checkForNewParameter_l(const String8& keyValuePair,
- status_t& status);
- virtual void cacheParameters_l() {}
- virtual String8 getParameters(const String8& keys);
- void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
+ virtual bool checkForNewParameter_l(const String8& keyValuePair,
+ status_t& status) REQUIRES(mutex());
+ virtual void cacheParameters_l() REQUIRES(mutex(), ThreadBase_ThreadLoop) {}
+ virtual String8 getParameters(const String8& keys) EXCLUDES_ThreadBase_Mutex;
+
+ // Hold either the AudioFlinger::mutex or the ThreadBase::mutex
+ void ioConfigChanged_l(audio_io_config_event_t event, pid_t pid = 0,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
- audio_patch_handle_t *handle);
- virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
- void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
- void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override;
+ audio_patch_handle_t *handle) REQUIRES(mutex());
+ virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle) REQUIRES(mutex());
+ void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override
+ EXCLUDES_ThreadBase_Mutex;
+ void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override REQUIRES(mutex());
- void addPatchTrack(const sp<IAfPatchRecord>& record) final;
- void deletePatchTrack(const sp<IAfPatchRecord>& record) final;
+ void addPatchTrack(const sp<IAfPatchRecord>& record) final EXCLUDES_ThreadBase_Mutex;
+ void deletePatchTrack(const sp<IAfPatchRecord>& record) final EXCLUDES_ThreadBase_Mutex;
- void readInputParameters_l();
- uint32_t getInputFramesLost() const final;
+ void readInputParameters_l() REQUIRES(mutex());
+ uint32_t getInputFramesLost() const final EXCLUDES_ThreadBase_Mutex;
- virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain);
- virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain);
- uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
+ virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override REQUIRES(mutex()) {
return ThreadBase::hasAudioSession_l(sessionId, mTracks);
}
@@ -1913,7 +2003,8 @@
// FIXME replace by Set [and implement Bag/Multiset for other uses].
KeyedVector<audio_session_t, bool> sessionIds() const;
- status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override
+ EXCLUDES_ThreadBase_Mutex;
bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
static void syncStartEventCallback(const wp<audioflinger::SyncEvent>& event);
@@ -1922,52 +2013,55 @@
bool hasFastCapture() const final { return mFastCapture != 0; }
virtual void toAudioPortConfig(struct audio_port_config *config);
- virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
- audio_session_t sessionId);
+ virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
+ audio_session_t sessionId) REQUIRES(mutex());
- virtual void acquireWakeLock_l() {
+ virtual void acquireWakeLock_l() REQUIRES(mutex()) {
ThreadBase::acquireWakeLock_l();
- mActiveTracks.updatePowerState(this, true /* force */);
+ mActiveTracks.updatePowerState_l(this, true /* force */);
}
- void checkBtNrec() final;
+ void checkBtNrec() final EXCLUDES_ThreadBase_Mutex;
// Sets the UID records silence
- void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final
+ EXCLUDES_ThreadBase_Mutex;
status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones) const final;
- status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) final;
- status_t setPreferredMicrophoneFieldDimension(float zoom) final;
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) const final
+ EXCLUDES_ThreadBase_Mutex;
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) final
+ EXCLUDES_ThreadBase_Mutex;
+ status_t setPreferredMicrophoneFieldDimension(float zoom) final EXCLUDES_ThreadBase_Mutex;
- MetadataUpdate updateMetadata_l() override;
+ MetadataUpdate updateMetadata_l() override REQUIRES(mutex());
bool fastTrackAvailable() const final { return mFastTrackAvail; }
void setFastTrackAvailable(bool available) final { mFastTrackAvail = available; }
- bool isTimestampCorrectionEnabled() const override {
+ bool isTimestampCorrectionEnabled_l() const override REQUIRES(mutex()) {
// checks popcount for exactly one device.
// Is currently disabled. Before enabling,
// verify compressed record timestamps.
return audio_is_input_device(mTimestampCorrectedDevice)
- && inDeviceType() == mTimestampCorrectedDevice;
+ && inDeviceType_l() == mTimestampCorrectedDevice;
}
status_t shareAudioHistory(const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
- int64_t sharedAudioStartMs = -1) final;
+ int64_t sharedAudioStartMs = -1) final EXCLUDES_ThreadBase_Mutex;
status_t shareAudioHistory_l(const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
- int64_t sharedAudioStartMs = -1);
- void resetAudioHistory_l() final;
+ int64_t sharedAudioStartMs = -1) REQUIRES(mutex());
+ void resetAudioHistory_l() final REQUIRES(mutex());
bool isStreamInitialized() const final {
return !(mInput == nullptr || mInput->stream == nullptr);
}
protected:
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
- void dumpTracks_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
+ void dumpTracks_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
private:
// Enter standby if not already in standby, and set mStandby flag
@@ -1976,10 +2070,10 @@
// Call the HAL standby method unconditionally, and don't change mStandby flag
void inputStandBy();
- void checkBtNrec_l();
+ void checkBtNrec_l() REQUIRES(mutex());
- int32_t getOldestFront_l();
- void updateFronts_l(int32_t offset);
+ int32_t getOldestFront_l() REQUIRES(mutex());
+ void updateFronts_l(int32_t offset) REQUIRES(mutex());
AudioStreamIn *mInput;
Source *mSource;
@@ -2065,88 +2159,112 @@
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
audio_port_handle_t deviceId,
- audio_port_handle_t portId) override;
+ audio_port_handle_t portId) override EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard l(mutex());
+ configure_l(attr, streamType, sessionId, callback, deviceId, portId);
+ }
- void disconnect() final;
+ void configure_l(const audio_attributes_t* attr,
+ audio_stream_type_t streamType,
+ audio_session_t sessionId,
+ const sp<MmapStreamCallback>& callback,
+ audio_port_handle_t deviceId,
+ audio_port_handle_t portId) REQUIRES(mutex());
+
+ void disconnect() final EXCLUDES_ThreadBase_Mutex;
// MmapStreamInterface for adapter.
- status_t createMmapBuffer(int32_t minSizeFrames, struct audio_mmap_buffer_info* info) final;
- status_t getMmapPosition(struct audio_mmap_position* position) const override;
+ status_t createMmapBuffer(int32_t minSizeFrames, struct audio_mmap_buffer_info* info) final
+ EXCLUDES_ThreadBase_Mutex;
+ status_t getMmapPosition(struct audio_mmap_position* position) const override
+ EXCLUDES_ThreadBase_Mutex;
status_t start(const AudioClient& client,
const audio_attributes_t *attr,
- audio_port_handle_t* handle) final;
- status_t stop(audio_port_handle_t handle) final;
- status_t standby() final;
- status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const = 0;
- status_t reportData(const void* buffer, size_t frameCount) override;
+ audio_port_handle_t* handle) final EXCLUDES_ThreadBase_Mutex;
+ status_t stop(audio_port_handle_t handle) final EXCLUDES_ThreadBase_Mutex;
+ status_t standby() final EXCLUDES_ThreadBase_Mutex;
+ status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const
+ EXCLUDES_ThreadBase_Mutex = 0;
+ status_t reportData(const void* buffer, size_t frameCount) override EXCLUDES_ThreadBase_Mutex;
// RefBase
void onFirstRef() final;
// Thread virtuals
- bool threadLoop() final;
+ bool threadLoop() final REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
// Not in ThreadBase
- virtual void threadLoop_exit() final;
- virtual void threadLoop_standby() final;
- virtual bool shouldStandby_l() final { return false; }
+ virtual void threadLoop_exit() final REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_standby() final REQUIRES(ThreadBase_ThreadLoop);
+ virtual bool shouldStandby_l() final REQUIRES(mutex()){ return false; }
virtual status_t exitStandby_l() REQUIRES(mutex());
status_t initCheck() const final { return mHalStream == nullptr ? NO_INIT : NO_ERROR; }
size_t frameCount() const final { return mFrameCount; }
- bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final;
- String8 getParameters(const String8& keys) final;
- void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
- void readHalParameters_l();
- void cacheParameters_l() final {}
+ bool checkForNewParameter_l(const String8& keyValuePair, status_t& status)
+ final REQUIRES(mutex());
+ String8 getParameters(const String8& keys) final EXCLUDES_ThreadBase_Mutex;
+ void ioConfigChanged_l(audio_io_config_event_t event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final
+ /* holds either AF::mutex or TB::mutex */;
+ void readHalParameters_l() REQUIRES(mutex());
+ void cacheParameters_l() final REQUIRES(mutex(), ThreadBase_ThreadLoop) {}
status_t createAudioPatch_l(
- const struct audio_patch* patch, audio_patch_handle_t* handle) final;
- status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final;
+ const struct audio_patch* patch, audio_patch_handle_t* handle) final
+ REQUIRES(mutex());
+ status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final
+ REQUIRES(mutex());
+ // NO_THREAD_SAFETY_ANALYSIS
void toAudioPortConfig(struct audio_port_config* config) override;
sp<StreamHalInterface> stream() const final { return mHalStream; }
- status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final;
- size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final;
+ status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final REQUIRES(mutex());
+ size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final REQUIRES(mutex());
status_t checkEffectCompatibility_l(
- const effect_descriptor_t *desc, audio_session_t sessionId) final;
+ const effect_descriptor_t *desc, audio_session_t sessionId) final REQUIRES(mutex());
- uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override REQUIRES(mutex()) {
// Note: using mActiveTracks as no mTracks here.
return ThreadBase::hasAudioSession_l(sessionId, mActiveTracks);
}
status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const final;
- virtual void checkSilentMode_l() {} // cannot be const (RecordThread)
- virtual void processVolume_l() {}
- void checkInvalidTracks_l();
+ virtual void checkSilentMode_l() REQUIRES(mutex()) {} // cannot be const (RecordThread)
+ virtual void processVolume_l() REQUIRES(mutex()) {}
+ void checkInvalidTracks_l() REQUIRES(mutex());
// Not in ThreadBase
- virtual audio_stream_type_t streamType() const { return AUDIO_STREAM_DEFAULT; }
- virtual void invalidateTracks(audio_stream_type_t /* streamType */) {}
- void invalidateTracks(std::set<audio_port_handle_t>& /* portIds */) override {}
+ virtual audio_stream_type_t streamType_l() const REQUIRES(mutex()) {
+ return AUDIO_STREAM_DEFAULT;
+ }
+ virtual void invalidateTracks(audio_stream_type_t /* streamType */)
+ EXCLUDES_ThreadBase_Mutex {}
+ void invalidateTracks(std::set<audio_port_handle_t>& /* portIds */) override
+ EXCLUDES_ThreadBase_Mutex {}
// Sets the UID records silence
void setRecordSilenced(
- audio_port_handle_t /* portId */, bool /* silenced */) override {}
+ audio_port_handle_t /* portId */, bool /* silenced */) override
+ EXCLUDES_ThreadBase_Mutex {}
bool isStreamInitialized() const override { return false; }
- void setClientSilencedState_l(audio_port_handle_t portId, bool silenced) {
+ void setClientSilencedState_l(audio_port_handle_t portId, bool silenced) REQUIRES(mutex()) {
mClientSilencedStates[portId] = silenced;
}
- size_t eraseClientSilencedState_l(audio_port_handle_t portId) {
+ size_t eraseClientSilencedState_l(audio_port_handle_t portId) REQUIRES(mutex()) {
return mClientSilencedStates.erase(portId);
}
- bool isClientSilenced_l(audio_port_handle_t portId) const {
+ bool isClientSilenced_l(audio_port_handle_t portId) const REQUIRES(mutex()) {
const auto it = mClientSilencedStates.find(portId);
return it != mClientSilencedStates.end() ? it->second : false;
}
- void setClientSilencedIfExists_l(audio_port_handle_t portId, bool silenced) {
+ void setClientSilencedIfExists_l(audio_port_handle_t portId, bool silenced)
+ REQUIRES(mutex()) {
const auto it = mClientSilencedStates.find(portId);
if (it != mClientSilencedStates.end()) {
it->second = silenced;
@@ -2154,28 +2272,28 @@
}
protected:
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
- void dumpTracks_l(int fd, const Vector<String16>& args) final;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
+ void dumpTracks_l(int fd, const Vector<String16>& args) final REQUIRES(mutex());
/**
* @brief mDeviceId current device port unique identifier
*/
- audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t mDeviceId GUARDED_BY(mutex()) = AUDIO_PORT_HANDLE_NONE;
- audio_attributes_t mAttr;
- audio_session_t mSessionId;
- audio_port_handle_t mPortId;
+ audio_attributes_t mAttr GUARDED_BY(mutex());
+ audio_session_t mSessionId GUARDED_BY(mutex());
+ audio_port_handle_t mPortId GUARDED_BY(mutex());
- wp<MmapStreamCallback> mCallback;
- sp<StreamHalInterface> mHalStream;
- sp<DeviceHalInterface> mHalDevice;
- AudioHwDevice* const mAudioHwDev;
- ActiveTracks<IAfMmapTrack> mActiveTracks;
- float mHalVolFloat;
- std::map<audio_port_handle_t, bool> mClientSilencedStates;
+ wp<MmapStreamCallback> mCallback GUARDED_BY(mutex());
+ sp<StreamHalInterface> mHalStream; // NO_THREAD_SAFETY_ANALYSIS
+ sp<DeviceHalInterface> mHalDevice GUARDED_BY(mutex());
+ AudioHwDevice* const mAudioHwDev GUARDED_BY(mutex());
+ ActiveTracks<IAfMmapTrack> mActiveTracks GUARDED_BY(mutex());
+ float mHalVolFloat GUARDED_BY(mutex());
+ std::map<audio_port_handle_t, bool> mClientSilencedStates GUARDED_BY(mutex());
- int32_t mNoCallbackWarningCount;
- static constexpr int32_t kMaxNoCallbackWarnings = 5;
+ int32_t mNoCallbackWarningCount GUARDED_BY(mutex());
+ static constexpr int32_t kMaxNoCallbackWarnings = 5;
};
class MmapPlaybackThread : public MmapThread, public IAfMmapPlaybackThread,
@@ -2193,28 +2311,31 @@
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
audio_port_handle_t deviceId,
- audio_port_handle_t portId) final;
+ audio_port_handle_t portId) final EXCLUDES_ThreadBase_Mutex;
- AudioStreamOut* clearOutput() final;
+ AudioStreamOut* clearOutput() final EXCLUDES_ThreadBase_Mutex;
// VolumeInterface
void setMasterVolume(float value) final;
- void setMasterBalance(float /* value */) final {} // Needs implementation?
- void setMasterMute(bool muted) final;
- void setStreamVolume(audio_stream_type_t stream, float value) final;
- void setStreamMute(audio_stream_type_t stream, bool muted) final;
- float streamVolume(audio_stream_type_t stream) const final;
+ // Needs implementation?
+ void setMasterBalance(float /* value */) final EXCLUDES_ThreadBase_Mutex {}
+ void setMasterMute(bool muted) final EXCLUDES_ThreadBase_Mutex;
+ void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
+ void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
+ float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
- void setMasterMute_l(bool muted) { mMasterMute = muted; }
+ void setMasterMute_l(bool muted) REQUIRES(mutex()) { mMasterMute = muted; }
- void invalidateTracks(audio_stream_type_t streamType) final;
- void invalidateTracks(std::set<audio_port_handle_t>& portIds) final;
+ void invalidateTracks(audio_stream_type_t streamType) final EXCLUDES_ThreadBase_Mutex;
+ void invalidateTracks(std::set<audio_port_handle_t>& portIds) final EXCLUDES_ThreadBase_Mutex;
- audio_stream_type_t streamType() const final { return mStreamType; }
- void checkSilentMode_l() final;
- void processVolume_l() final;
+ audio_stream_type_t streamType_l() const final REQUIRES(mutex()) {
+ return mStreamType;
+ }
+ void checkSilentMode_l() final REQUIRES(mutex());
+ void processVolume_l() final REQUIRES(mutex());
- MetadataUpdate updateMetadata_l() final;
+ MetadataUpdate updateMetadata_l() final REQUIRES(mutex());
void toAudioPortConfig(struct audio_port_config* config) final;
@@ -2232,21 +2353,21 @@
REQUIRES(audio_utils::AudioFlinger_Mutex);
protected:
- void dumpInternals_l(int fd, const Vector<String16>& args) final;
- float streamVolume_l() const {
+ void dumpInternals_l(int fd, const Vector<String16>& args) final REQUIRES(mutex());
+ float streamVolume_l() const REQUIRES(mutex()) {
return mStreamTypes[mStreamType].volume;
}
- bool streamMuted_l() const {
+ bool streamMuted_l() const REQUIRES(mutex()) {
return mStreamTypes[mStreamType].mute;
}
- stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
- audio_stream_type_t mStreamType;
- float mMasterVolume;
- bool mMasterMute;
- AudioStreamOut* mOutput;
+ stream_type_t mStreamTypes[AUDIO_STREAM_CNT] GUARDED_BY(mutex());
+ audio_stream_type_t mStreamType GUARDED_BY(mutex());
+ float mMasterVolume GUARDED_BY(mutex());
+ bool mMasterMute GUARDED_BY(mutex());
+ AudioStreamOut* mOutput; // NO_THREAD_SAFETY_ANALYSIS
- mediautils::atomic_sp<audio_utils::MelProcessor> mMelProcessor;
+ mediautils::atomic_sp<audio_utils::MelProcessor> mMelProcessor; // locked internally
};
class MmapCaptureThread : public MmapThread, public IAfMmapCaptureThread
@@ -2259,13 +2380,14 @@
return sp<IAfMmapCaptureThread>::fromExisting(this);
}
- AudioStreamIn* clearInput() final;
+ AudioStreamIn* clearInput() final EXCLUDES_ThreadBase_Mutex;
status_t exitStandby_l() REQUIRES(mutex()) final;
- MetadataUpdate updateMetadata_l() final;
- void processVolume_l() final;
- void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
+ MetadataUpdate updateMetadata_l() final REQUIRES(mutex());
+ void processVolume_l() final REQUIRES(mutex());
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final
+ EXCLUDES_ThreadBase_Mutex;
void toAudioPortConfig(struct audio_port_config* config) final;
@@ -2277,7 +2399,7 @@
protected:
- AudioStreamIn* mInput;
+ AudioStreamIn* mInput; // NO_THREAD_SAFETY_ANALYSIS
};
class BitPerfectThread : public MixerThread {
@@ -2286,13 +2408,15 @@
audio_io_handle_t id, bool systemReady);
protected:
- mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) final;
- void threadLoop_mix() final;
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) final
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ void threadLoop_mix() final REQUIRES(ThreadBase_ThreadLoop);
private:
- bool mIsBitPerfect;
- float mVolumeLeft = 0.f;
- float mVolumeRight = 0.f;
+ // These variables are only accessed on the threadLoop; hence need no mutex.
+ bool mIsBitPerfect GUARDED_BY(ThreadBase_ThreadLoop) = false;
+ float mVolumeLeft GUARDED_BY(ThreadBase_ThreadLoop) = 0.f;
+ float mVolumeRight GUARDED_BY(ThreadBase_ThreadLoop) = 0.f;
};
} // namespace android
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 75d885d..4811586 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -450,6 +450,10 @@
if (*_aidl_return != OK) {
return Status::ok();
}
+
+ // restrict position modulo INT_MAX to avoid integer sanitization abort
+ legacy.mPosition &= INT_MAX;
+
*timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
return Status::ok();
}
@@ -1169,9 +1173,11 @@
if (thread != 0) {
if (isOffloaded()) {
audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
+ const bool nonOffloadableGlobalEffectEnabled =
+ thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
audio_utils::lock_guard _lth(thread->mutex());
sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
- if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
+ if (nonOffloadableGlobalEffectEnabled ||
(ec != 0 && ec->isNonOffloadableEnabled())) {
invalidate();
return PERMISSION_DENIED;
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 80e098b..6c130fd 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -89,6 +89,8 @@
void importAudioPortAndPickAudioProfile(const sp<PolicyAudioPort>& policyPort,
bool force = false);
+ status_t readFromParcelable(const media::AudioPortFw& parcelable) override;
+
void setEncapsulationInfoFromHal(AudioPolicyClientInterface *clientInterface);
void dump(String8 *dst, int spaces, bool verbose = true) const;
@@ -104,7 +106,7 @@
std::string mTagName; // Unique human readable identifier for a device port found in conf file.
audio_format_t mCurrentEncodedFormat;
bool mIsDynamic = false;
- const std::string mDeclaredAddress; // Original device address
+ std::string mDeclaredAddress; // Original device address
};
class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 8c7a7de..4edd11f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -29,6 +29,8 @@
namespace android {
+using media::audio::common::AudioDeviceAddress;
+using media::audio::common::AudioDeviceType;
using media::audio::common::AudioIoFlags;
using media::audio::common::AudioPortDeviceExt;
using media::audio::common::AudioPortExt;
@@ -113,12 +115,17 @@
ports.emplace(aidlPort.id, devicePort);
if (const auto& deviceExt = aidlPort.ext.get<AudioPortExt::device>();
- deviceExt.device.type.connection.empty()) { // Attached device
+ deviceExt.device.type.connection.empty() ||
+ // DeviceHalAidl connects remote submix input with an address.
+ (deviceExt.device.type.type == AudioDeviceType::IN_SUBMIX &&
+ deviceExt.device.address != AudioDeviceAddress())) {
+ // Attached device.
if (isInput) {
attachedInputDevices->add(devicePort);
} else {
attachedOutputDevices->add(devicePort);
- if ((deviceExt.flags & defaultDeviceFlag) != 0) {
+ if (*defaultOutputDevice == nullptr &&
+ (deviceExt.flags & defaultDeviceFlag) != 0) {
*defaultOutputDevice = devicePort;
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 514601c..fe25693 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -154,6 +154,12 @@
policyPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
}
+status_t DeviceDescriptor::readFromParcelable(const media::AudioPortFw& parcelable) {
+ RETURN_STATUS_IF_ERROR(DeviceDescriptorBase::readFromParcelable(parcelable));
+ mDeclaredAddress = DeviceDescriptorBase::address();
+ return OK;
+}
+
void DeviceDescriptor::setEncapsulationInfoFromHal(
AudioPolicyClientInterface *clientInterface) {
AudioParameter param(String8(mDeviceTypeAddr.getAddress()));
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.cpp b/services/camera/libcameraservice/aidl/AidlUtils.cpp
index 7291c5f..2225cfe 100644
--- a/services/camera/libcameraservice/aidl/AidlUtils.cpp
+++ b/services/camera/libcameraservice/aidl/AidlUtils.cpp
@@ -78,7 +78,13 @@
for (auto &handle : windowHandles) {
native_handle_t* nh = makeFromAidl(handle);
- iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(nh)));
+ auto igbp = AImageReader_getHGBPFromHandle(nh);
+ if (igbp == nullptr) {
+ ALOGE("%s: Could not get HGBP from NativeHandle: %s. Skipping.",
+ __FUNCTION__, handle.toString().c_str());
+ continue;
+ }
+ iGBPs.push_back(new H2BGraphicBufferProducer(igbp));
native_handle_delete(nh);
}
UOutputConfiguration outputConfiguration(
diff --git a/services/camera/libcameraservice/hidl/Utils.cpp b/services/camera/libcameraservice/hidl/Utils.cpp
index b5dddf7..d0302d0 100644
--- a/services/camera/libcameraservice/hidl/Utils.cpp
+++ b/services/camera/libcameraservice/hidl/Utils.cpp
@@ -88,7 +88,13 @@
auto &windowHandles = hOutputConfiguration.windowHandles;
iGBPs.reserve(windowHandles.size());
for (auto &handle : windowHandles) {
- iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(handle)));
+ auto igbp = AImageReader_getHGBPFromHandle(handle);
+ if (igbp == nullptr) {
+ ALOGE("%s: Could not get HGBP from native_handle: %p. Skipping.",
+ __FUNCTION__, handle.getNativeHandle());
+ continue;
+ }
+ iGBPs.push_back(new H2BGraphicBufferProducer(igbp));
}
hardware::camera2::params::OutputConfiguration outputConfiguration(
iGBPs, convertFromHidl(hOutputConfiguration.rotation),
diff --git a/services/mediacodec/main_swcodecservice.cpp b/services/mediacodec/main_swcodecservice.cpp
index d91b788..9aa5d3d 100644
--- a/services/mediacodec/main_swcodecservice.cpp
+++ b/services/mediacodec/main_swcodecservice.cpp
@@ -40,9 +40,5 @@
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
strcpy(argv[0], "media.swcodec");
- ::android::hardware::configureRpcThreadpool(64, false);
-
RegisterCodecServices();
-
- ::android::hardware::joinRpcThreadpool();
}