Merge "Add Dolby Vision branding info into MPEG-4 ftyp box" into main
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index 1e3bfe0..c7a1bfd 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -184,7 +184,7 @@
// attempting to call audio flinger on a null pointer could make the process crash
// and attract attentions.
std::vector<AudioMMapPolicyInfo> policyInfos;
- status_t status = af->getMmapPolicyInfos(
+ status_t status = sp<IAudioFlinger>::cast(af)->getMmapPolicyInfos(
AudioMMapPolicyType::DEFAULT, &policyInfos);
// Initialize aaudio service when querying mmap policy succeeds and
// any of the policy supports MMAP.
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 7caaaaf..4bd12b8 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -646,7 +646,7 @@
return result.value_or(0);
}
-uint32_t AudioFlingerClientAdapter::getPrimaryOutputSamplingRate() {
+uint32_t AudioFlingerClientAdapter::getPrimaryOutputSamplingRate() const {
auto result = [&]() -> ConversionResult<uint32_t> {
int32_t aidlRet;
RETURN_IF_ERROR(statusTFromBinderStatus(
@@ -657,7 +657,7 @@
return result.value_or(0);
}
-size_t AudioFlingerClientAdapter::getPrimaryOutputFrameCount() {
+size_t AudioFlingerClientAdapter::getPrimaryOutputFrameCount() const {
auto result = [&]() -> ConversionResult<size_t> {
int64_t aidlRet;
RETURN_IF_ERROR(statusTFromBinderStatus(
@@ -672,7 +672,7 @@
return statusTFromBinderStatus(mDelegate->setLowRamDevice(isLowRamDevice, totalMemory));
}
-status_t AudioFlingerClientAdapter::getAudioPort(struct audio_port_v7* port) {
+status_t AudioFlingerClientAdapter::getAudioPort(struct audio_port_v7* port) const {
media::AudioPortFw portAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_v7_AudioPortFw(*port));
media::AudioPortFw aidlRet;
@@ -705,7 +705,7 @@
}
status_t AudioFlingerClientAdapter::listAudioPatches(unsigned int* num_patches,
- struct audio_patch* patches) {
+ struct audio_patch* patches) const {
std::vector<media::AudioPatchFw> aidlRet;
int32_t maxPatches = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*num_patches));
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -753,7 +753,8 @@
}
status_t
-AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) {
+AudioFlingerClientAdapter::getMicrophones(
+ std::vector<media::MicrophoneInfoFw>* microphones) const {
std::vector<media::MicrophoneInfoFw> aidlRet;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mDelegate->getMicrophones(&aidlRet)));
if (microphones != nullptr) {
@@ -788,7 +789,7 @@
return statusTFromBinderStatus(mDelegate->getMmapPolicyInfos(policyType, policyInfos));
}
-int32_t AudioFlingerClientAdapter::getAAudioMixerBurstCount() {
+int32_t AudioFlingerClientAdapter::getAAudioMixerBurstCount() const {
auto result = [&]() -> ConversionResult<int32_t> {
int32_t aidlRet;
RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->getAAudioMixerBurstCount(&aidlRet)));
@@ -798,7 +799,7 @@
return result.value_or(0);
}
-int32_t AudioFlingerClientAdapter::getAAudioHardwareBurstMinUsec() {
+int32_t AudioFlingerClientAdapter::getAAudioHardwareBurstMinUsec() const {
auto result = [&]() -> ConversionResult<int32_t> {
int32_t aidlRet;
RETURN_IF_ERROR(statusTFromBinderStatus(
@@ -829,7 +830,7 @@
}
status_t AudioFlingerClientAdapter::getSupportedLatencyModes(
- audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) {
+ audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) const {
if (modes == nullptr) {
return BAD_VALUE;
}
@@ -851,7 +852,7 @@
return statusTFromBinderStatus(mDelegate->setBluetoothVariableLatencyEnabled(enabled));
}
-status_t AudioFlingerClientAdapter::isBluetoothVariableLatencyEnabled(bool* enabled) {
+status_t AudioFlingerClientAdapter::isBluetoothVariableLatencyEnabled(bool* enabled) const {
if (enabled == nullptr) {
return BAD_VALUE;
}
@@ -862,7 +863,7 @@
return NO_ERROR;
}
-status_t AudioFlingerClientAdapter::supportsBluetoothVariableLatency(bool* support) {
+status_t AudioFlingerClientAdapter::supportsBluetoothVariableLatency(bool* support) const {
if (support == nullptr) {
return BAD_VALUE;
}
@@ -875,7 +876,7 @@
status_t AudioFlingerClientAdapter::getSoundDoseInterface(
const sp<media::ISoundDoseCallback> &callback,
- sp<media::ISoundDose>* soundDose) {
+ sp<media::ISoundDose>* soundDose) const {
return statusTFromBinderStatus(mDelegate->getSoundDoseInterface(callback, soundDose));
}
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 2e2ef65..3c96862 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -303,8 +303,8 @@
// helpers for android.media.AudioManager.getProperty(), see description there for meaning
// FIXME move these APIs to AudioPolicy to permit a more accurate implementation
// that looks on primary device for a stream with fast flag, primary flag, or first one.
- virtual uint32_t getPrimaryOutputSamplingRate() = 0;
- virtual size_t getPrimaryOutputFrameCount() = 0;
+ virtual uint32_t getPrimaryOutputSamplingRate() const = 0;
+ virtual size_t getPrimaryOutputFrameCount() const = 0;
// Intended for AudioService to inform AudioFlinger of device's low RAM attribute,
// and should be called at most once. For a definition of what "low RAM" means, see
@@ -313,7 +313,7 @@
virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) = 0;
/* Get attributes for a given audio port */
- virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
+ virtual status_t getAudioPort(struct audio_port_v7* port) const = 0;
/* Create an audio patch between several source and sink ports */
virtual status_t createAudioPatch(const struct audio_patch *patch,
@@ -324,7 +324,7 @@
/* List existing audio patches */
virtual status_t listAudioPatches(unsigned int *num_patches,
- struct audio_patch *patches) = 0;
+ struct audio_patch* patches) const = 0;
/* Set audio port configuration */
virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
@@ -341,7 +341,7 @@
virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
/* List available microphones and their characteristics */
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) = 0;
+ virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const = 0;
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
@@ -357,9 +357,9 @@
media::audio::common::AudioMMapPolicyType policyType,
std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
- virtual int32_t getAAudioMixerBurstCount() = 0;
+ virtual int32_t getAAudioMixerBurstCount() const = 0;
- virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
+ virtual int32_t getAAudioHardwareBurstMinUsec() const = 0;
virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
media::DeviceConnectedState state) = 0;
@@ -370,18 +370,18 @@
audio_io_handle_t output, audio_latency_mode_t mode) = 0;
virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
- std::vector<audio_latency_mode_t>* modes) = 0;
+ std::vector<audio_latency_mode_t>* modes) const = 0;
virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
- sp<media::ISoundDose>* soundDose) = 0;
+ sp<media::ISoundDose>* soundDose) const = 0;
virtual status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) = 0;
virtual status_t setBluetoothVariableLatencyEnabled(bool enabled) = 0;
- virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) = 0;
+ virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) const = 0;
- virtual status_t supportsBluetoothVariableLatency(bool* support) = 0;
+ virtual status_t supportsBluetoothVariableLatency(bool* support) const = 0;
virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) = 0;
};
@@ -459,22 +459,22 @@
audio_session_t sessionId,
bool suspended) override;
audio_module_handle_t loadHwModule(const char* name) override;
- uint32_t getPrimaryOutputSamplingRate() override;
- size_t getPrimaryOutputFrameCount() override;
+ uint32_t getPrimaryOutputSamplingRate() const override;
+ size_t getPrimaryOutputFrameCount() const override;
status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
- status_t getAudioPort(struct audio_port_v7* port) override;
+ status_t getAudioPort(struct audio_port_v7* port) const override;
status_t createAudioPatch(const struct audio_patch* patch,
audio_patch_handle_t* handle) override;
status_t releaseAudioPatch(audio_patch_handle_t handle) override;
status_t listAudioPatches(unsigned int* num_patches,
- struct audio_patch* patches) override;
+ struct audio_patch* patches) const override;
status_t setAudioPortConfig(const struct audio_port_config* config) override;
audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) override;
status_t systemReady() override;
status_t audioPolicyReady() override;
size_t frameCountHAL(audio_io_handle_t ioHandle) const override;
- status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) override;
+ status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const override;
status_t setAudioHalPids(const std::vector<pid_t>& pids) override;
status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
status_t updateSecondaryOutputs(
@@ -482,20 +482,20 @@
status_t getMmapPolicyInfos(
media::audio::common::AudioMMapPolicyType policyType,
std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) override;
- int32_t getAAudioMixerBurstCount() override;
- int32_t getAAudioHardwareBurstMinUsec() override;
+ int32_t getAAudioMixerBurstCount() const override;
+ int32_t getAAudioHardwareBurstMinUsec() const override;
status_t setDeviceConnectedState(const struct audio_port_v7 *port,
media::DeviceConnectedState state) override;
status_t setSimulateDeviceConnections(bool enabled) override;
status_t setRequestedLatencyMode(audio_io_handle_t output,
audio_latency_mode_t mode) override;
status_t getSupportedLatencyModes(
- audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) override;
+ audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) const override;
status_t setBluetoothVariableLatencyEnabled(bool enabled) override;
- status_t isBluetoothVariableLatencyEnabled(bool* enabled) override;
- status_t supportsBluetoothVariableLatency(bool* support) override;
+ status_t isBluetoothVariableLatencyEnabled(bool* enabled) const override;
+ status_t supportsBluetoothVariableLatency(bool* support) const override;
status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
- sp<media::ISoundDose>* soundDose) override;
+ sp<media::ISoundDose>* soundDose) const override;
status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) override;
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml b/media/module/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
index c3d746d..94029c5 100644
--- a/media/module/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
+++ b/media/module/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
@@ -18,11 +18,17 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="false" />
<option name="push-file" key="{MODULE}" value="/data/local/tmp/{MODULE}" />
- <option name="push-file"
- key="https://dl.google.com/android-unittest/media/frameworks/av/media/module/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true"
- value="/data/local/tmp/TranscodingBenchmark/" />
</target_preparer>
-
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="{MODULE}" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="TranscodingBenchmark-1.2" />
+ <option name="dynamic-config-module" value="{MODULE}" />
+ </target_preparer>
<test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
<option name="native-benchmark-device-path" value="/data/local/tmp" />
<option name="benchmark-module-name" value="{MODULE}" />
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/BenchmarkCommon.h b/media/module/libmediatranscoding/transcoder/benchmark/BenchmarkCommon.h
new file mode 100644
index 0000000..4753bc1
--- /dev/null
+++ b/media/module/libmediatranscoding/transcoder/benchmark/BenchmarkCommon.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BENCHMARK_COMMON_H__
+#define __BENCHMARK_COMMON_H__
+
+
+#include <string>
+
+namespace android {
+
+static const std::string kAssetDirectory = "/sdcard/test/TranscodingBenchmark-1.2/";
+
+} // namespace android
+#endif // __BENCHMARK_COMMON_H__
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/DynamicConfig.xml b/media/module/libmediatranscoding/transcoder/benchmark/DynamicConfig.xml
new file mode 100644
index 0000000..ad574ef
--- /dev/null
+++ b/media/module/libmediatranscoding/transcoder/benchmark/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
index f0b9304..a44c229 100644
--- a/media/module/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
@@ -39,18 +39,16 @@
#include <thread>
+#include "BenchmarkCommon.h"
using namespace android;
static void ReadMediaSamples(benchmark::State& state, const std::string& srcFileName,
bool readAudio, bool sequentialAccess = false) {
- // Asset directory.
- static const std::string kAssetDirectory = "/data/local/tmp/TranscodingBenchmark/";
-
int srcFd = 0;
std::string srcPath = kAssetDirectory + srcFileName;
if ((srcFd = open(srcPath.c_str(), O_RDONLY)) < 0) {
- state.SkipWithError("Unable to open source file");
+ state.SkipWithError("Unable to open source file: " + srcPath);
return;
}
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
index d6ed2c6..b3f53e3 100644
--- a/media/module/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
@@ -44,6 +44,8 @@
#include <media/PassthroughTrackTranscoder.h>
#include <media/VideoTrackTranscoder.h>
+#include "BenchmarkCommon.h"
+
using namespace android;
typedef enum {
@@ -249,9 +251,6 @@
/** Gets a MediaSampleReader for the source file */
static std::shared_ptr<MediaSampleReader> GetSampleReader(const std::string& srcFileName,
bool mock) {
- // Asset directory
- static const std::string kAssetDirectory = "/data/local/tmp/TranscodingBenchmark/";
-
int srcFd = 0;
std::string srcPath = kAssetDirectory + srcFileName;
@@ -362,7 +361,7 @@
std::shared_ptr<MediaSampleReader> sampleReader = GetSampleReader(srcFileName, mockReader);
if (sampleReader == nullptr) {
- state.SkipWithError("Unable to create sample reader");
+ state.SkipWithError("Unable to create sample reader: " + srcFileName);
return;
}
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
index 86979f4..7e9b993 100644
--- a/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
@@ -37,6 +37,8 @@
#include <iostream>
+#include "BenchmarkCommon.h"
+
using namespace android;
const std::string PARAM_VIDEO_FRAME_RATE = "VideoFrameRate";
@@ -110,8 +112,6 @@
static constexpr int kDstOpenFlags = O_WRONLY | O_CREAT;
// User R+W permission.
static constexpr int kDstFileMode = S_IRUSR | S_IWUSR;
- // Asset directory
- static const std::string kAssetDirectory = "/data/local/tmp/TranscodingBenchmark/";
// Transcoding configuration params to be logged
int64_t trackDurationUs = 0;
@@ -132,11 +132,11 @@
media_status_t status = AMEDIA_OK;
if ((srcFd = open(srcPath.c_str(), O_RDONLY)) < 0) {
- state.SkipWithError("Unable to open source file");
+ state.SkipWithError("Unable to open source file: " + srcPath);
goto exit;
}
if ((dstFd = open(dstPath.c_str(), kDstOpenFlags, kDstFileMode)) < 0) {
- state.SkipWithError("Unable to open destination file");
+ state.SkipWithError("Unable to open destination file: " + dstPath);
goto exit;
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
index 772a29b..28c2654 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
@@ -20,12 +20,13 @@
package="com.android.media.benchmark">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- <application
+ <application android:requestLegacyExternalStorage="true"
tools:ignore="AllowBackup,GoogleAppIndexingWarning,MissingApplicationIcon"
tools:remove="android:appComponentFactory">
</application>
-
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="31"/>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.media.benchmark"
android:label="Benchmark Media Test"/>
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 17e6d15..0cd6243 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -149,6 +149,7 @@
srcs: [
"AudioFlinger.cpp",
+ "Client.cpp",
"DeviceEffectManager.cpp",
"Effects.cpp",
"MelReporter.cpp",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 18ab3a7..0d539c0 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -15,7 +15,6 @@
** limitations under the License.
*/
-
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
@@ -23,71 +22,43 @@
#define AUDIO_ARRAYS_STATIC_CHECK 1
#include "Configuration.h"
-#include <dirent.h>
-#include <math.h>
-#include <signal.h>
-#include <string>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <thread>
+#include "AudioFlinger.h"
+//#define BUFLOG_NDEBUG 0
+#include <afutils/BufLog.h>
+#include <afutils/DumpTryLock.h>
+#include <afutils/Permission.h>
+#include <afutils/PropertyUtils.h>
+#include <afutils/TypedLogger.h>
#include <android-base/stringprintf.h>
#include <android/media/IAudioPolicyService.h>
-#include <android/os/IExternalVibratorService.h>
+#include <audiomanager/IAudioManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
#include <binder/Parcel.h>
-#include <media/audiohal/AudioHalVersionInfo.h>
-#include <media/audiohal/DeviceHalInterface.h>
-#include <media/audiohal/DevicesFactoryHalInterface.h>
-#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <cutils/properties.h>
+#include <media/AidlConversion.h>
#include <media/AudioParameter.h>
+#include <media/AudioValidator.h>
+#include <media/IMediaLogService.h>
#include <media/MediaMetricsItem.h>
#include <media/TypeConverter.h>
-#include <mediautils/TimeCheck.h>
-#include <memunreachable/memunreachable.h>
-#include <utils/String16.h>
-#include <utils/threads.h>
-
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-
-#include <system/audio.h>
-#include <audiomanager/IAudioManager.h>
-
-#include "AudioFlinger.h"
-#include "EffectConfiguration.h"
-#include <afutils/PropertyUtils.h>
-
-#include <media/AudioResamplerPublic.h>
-
-#include <system/audio_effects/effect_visualizer.h>
-#include <system/audio_effects/effect_ns.h>
-#include <system/audio_effects/effect_aec.h>
-#include <system/audio_effects/effect_hapticgenerator.h>
-#include <system/audio_effects/effect_spatializer.h>
-
-#include <audio_utils/primitives.h>
-
-#include <powermanager/PowerManager.h>
-
-#include <media/IMediaLogService.h>
-#include <media/AidlConversion.h>
-#include <media/AudioValidator.h>
-#include <media/nbaio/Pipe.h>
-#include <media/nbaio/PipeReader.h>
#include <mediautils/BatteryNotifier.h>
#include <mediautils/MemoryLeakTrackUtil.h>
#include <mediautils/MethodStatistics.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/TimeCheck.h>
-#include <private/android_filesystem_config.h>
+#include <memunreachable/memunreachable.h>
+// required for effect matching
+#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_ns.h>
+#include <system/audio_effects/effect_spatializer.h>
+#include <system/audio_effects/effect_visualizer.h>
+#include <utils/Log.h>
-//#define BUFLOG_NDEBUG 0
-#include <afutils/BufLog.h>
-#include <afutils/TypedLogger.h>
+// not needed with the includes above, added to prevent transitive include dependency.
+#include <chrono>
+#include <thread>
// ----------------------------------------------------------------------------
@@ -124,10 +95,6 @@
static constexpr char kAudioServiceName[] = "audio";
-nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
-
-uint32_t AudioFlinger::mScreenState;
-
// In order to avoid invalidating offloaded tracks each time a Visualizer is turned on and off
// we define a minimum time during which a global effect is considered enabled.
static const nsecs_t kMinGlobalEffectEnabletimeNs = seconds(7200);
@@ -148,21 +115,6 @@
}
}
-// Keep a strong reference to external vibrator service
-static sp<os::IExternalVibratorService> sExternalVibratorService;
-
-static sp<os::IExternalVibratorService> getExternalVibratorService() {
- if (sExternalVibratorService == 0) {
- sp<IBinder> binder = defaultServiceManager()->getService(
- String16("external_vibrator_service"));
- if (binder != 0) {
- sExternalVibratorService =
- interface_cast<os::IExternalVibratorService>(binder);
- }
- }
- return sExternalVibratorService;
-}
-
// Creates association between Binder code to name for IAudioFlinger.
#define IAUDIOFLINGER_BINDER_METHOD_MACRO_LIST \
BINDER_METHOD_ENTRY(createTrack) \
@@ -269,41 +221,6 @@
}
};
-// TODO b/182392769: use attribution source util
-/* static */
-AttributionSourceState AudioFlinger::checkAttributionSourcePackage(
- const AttributionSourceState& attributionSource) {
- Vector<String16> packages;
- PermissionController{}.getPackagesForUid(attributionSource.uid, packages);
-
- AttributionSourceState checkedAttributionSource = attributionSource;
- if (!attributionSource.packageName.has_value()
- || attributionSource.packageName.value().size() == 0) {
- if (!packages.isEmpty()) {
- checkedAttributionSource.packageName =
- std::move(legacy2aidl_String16_string(packages[0]).value());
- }
- } else {
- String16 opPackageLegacy = VALUE_OR_FATAL(
- aidl2legacy_string_view_String16(attributionSource.packageName.value_or("")));
- if (std::find_if(packages.begin(), packages.end(),
- [&opPackageLegacy](const auto& package) {
- return opPackageLegacy == package; }) == packages.end()) {
- ALOGW("The package name(%s) provided does not correspond to the uid %d",
- attributionSource.packageName.value_or("").c_str(), attributionSource.uid);
- }
- }
- return checkedAttributionSource;
-}
-
-// ----------------------------------------------------------------------------
-
-std::string formatToString(audio_format_t format) {
- std::string result;
- FormatConverter::toString(format, result);
- return result;
-}
-
// ----------------------------------------------------------------------------
void AudioFlinger::instantiate() {
@@ -314,26 +231,6 @@
}
AudioFlinger::AudioFlinger()
- : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
- mPrimaryHardwareDev(NULL),
- mAudioHwDevs(NULL),
- mHardwareStatus(AUDIO_HW_IDLE),
- mMasterVolume(1.0f),
- mMasterMute(false),
- // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
- mMode(AUDIO_MODE_INVALID),
- mBtNrecIsOff(false),
- mIsLowRamDevice(true),
- mIsDeviceTypeKnown(false),
- mTotalMemory(0),
- mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
- mGlobalEffectEnableTime(0),
- mPatchPanel(this),
- mPatchCommandThread(sp<PatchCommandThread>::make()),
- mDeviceEffectManager(sp<DeviceEffectManager>::make(*this)),
- mMelReporter(sp<MelReporter>::make(*this)),
- mSystemReady(false),
- mBluetoothLatencyModesEnabled(true)
{
// Move the audio session unique ID generator start base as time passes to limit risk of
// generating the same ID again after an audioserver restart.
@@ -370,9 +267,6 @@
// in bad state, reset the state upon service start.
BatteryNotifier::getInstance().noteResetAudio();
- mDevicesFactoryHal = DevicesFactoryHalInterface::create();
- mEffectsFactoryHal = audioflinger::EffectConfiguration::getEffectsFactoryHal();
-
mMediaLogNotifier->run("MediaLogNotifier");
std::vector<pid_t> halPids;
mDevicesFactoryHal->getHalPids(&halPids);
@@ -386,26 +280,13 @@
void AudioFlinger::onFirstRef()
{
- Mutex::Autolock _l(mLock);
-
- /* TODO: move all this work into an Init() function */
- char val_str[PROPERTY_VALUE_MAX] = { 0 };
- if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
- uint32_t int_val;
- if (1 == sscanf(val_str, "%u", &int_val)) {
- mStandbyTimeInNsecs = milliseconds(int_val);
- ALOGI("Using %u mSec as standby time.", int_val);
- } else {
- mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
- ALOGI("Using default %u mSec as standby time.",
- (uint32_t)(mStandbyTimeInNsecs / 1000000));
- }
- }
+ audio_utils::lock_guard _l(mutex());
mMode = AUDIO_MODE_NORMAL;
gAudioFlinger = this; // we are already refcounted, store into atomic pointer.
-
+ mDeviceEffectManager = sp<DeviceEffectManager>::make(
+ sp<IAfDeviceEffectManagerCallback>::fromExisting(this)),
mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
@@ -413,6 +294,9 @@
mAAudioBurstsPerBuffer = getAAudioMixerBurstCountFromSystemProperty();
mAAudioHwBurstMinMicros = getAAudioHardwareBurstMinUsecFromSystemProperty();
}
+
+ mPatchPanel = IAfPatchPanel::create(sp<IAfPatchPanelCallback>::fromExisting(this));
+ mMelReporter = sp<MelReporter>::make(sp<IAfMelReporterCallback>::fromExisting(this));
}
status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) {
@@ -422,20 +306,20 @@
status_t AudioFlinger::setVibratorInfos(
const std::vector<media::AudioVibratorInfo>& vibratorInfos) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mAudioVibratorInfos = vibratorInfos;
return NO_ERROR;
}
status_t AudioFlinger::updateSecondaryOutputs(
const TrackSecondaryOutputsMap& trackSecondaryOutputs) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (const auto& [trackId, secondaryOutputs] : trackSecondaryOutputs) {
size_t i = 0;
for (; i < mPlaybackThreads.size(); ++i) {
- PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
- Mutex::Autolock _tl(thread->mLock);
- sp<PlaybackThread::Track> track = thread->getTrackById_l(trackId);
+ IAfPlaybackThread* thread = mPlaybackThreads.valueAt(i).get();
+ audio_utils::lock_guard _tl(thread->mutex());
+ sp<IAfTrack> track = thread->getTrackById_l(trackId);
if (track != nullptr) {
ALOGD("%s trackId: %u", __func__, trackId);
updateSecondaryOutputsForTrack_l(track.get(), thread, secondaryOutputs);
@@ -450,13 +334,13 @@
status_t AudioFlinger::getMmapPolicyInfos(
AudioMMapPolicyType policyType, std::vector<AudioMMapPolicyInfo> *policyInfos) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (const auto it = mPolicyInfos.find(policyType); it != mPolicyInfos.end()) {
*policyInfos = it->second;
return NO_ERROR;
}
if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
for (size_t i = 0; i < mAudioHwDevs.size(); ++i) {
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
std::vector<AudioMMapPolicyInfo> infos;
@@ -476,21 +360,21 @@
return NO_ERROR;
}
-int32_t AudioFlinger::getAAudioMixerBurstCount() {
- Mutex::Autolock _l(mLock);
+int32_t AudioFlinger::getAAudioMixerBurstCount() const {
+ audio_utils::lock_guard _l(mutex());
return mAAudioBurstsPerBuffer;
}
-int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() {
- Mutex::Autolock _l(mLock);
+int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() const {
+ audio_utils::lock_guard _l(mutex());
return mAAudioHwBurstMinMicros;
}
status_t AudioFlinger::setDeviceConnectedState(const struct audio_port_v7 *port,
media::DeviceConnectedState state) {
status_t final_result = NO_INIT;
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
mHardwareStatus = AUDIO_HW_SET_CONNECTED_STATE;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -510,8 +394,8 @@
status_t AudioFlinger::setSimulateDeviceConnections(bool enabled) {
bool at_least_one_succeeded = false;
status_t last_error = INVALID_OPERATION;
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
mHardwareStatus = AUDIO_HW_SET_SIMULATE_CONNECTIONS;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -527,7 +411,7 @@
}
// getDefaultVibratorInfo_l must be called with AudioFlinger lock held.
-std::optional<media::AudioVibratorInfo> AudioFlinger::getDefaultVibratorInfo_l() {
+std::optional<media::AudioVibratorInfo> AudioFlinger::getDefaultVibratorInfo_l() const {
if (mAudioVibratorInfos.empty()) {
return {};
}
@@ -554,7 +438,7 @@
}
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- // no mHardwareLock needed, as there are no other references to this
+ // no hardwareMutex() needed, as there are no other references to this
delete mAudioHwDevs.valueAt(i);
}
@@ -580,7 +464,7 @@
sp<MmapStreamInterface>& interface,
audio_port_handle_t *handle)
{
- // TODO: Use ServiceManager to get IAudioFlinger instead of by atomic pointer.
+ // TODO(b/292281786): Use ServiceManager to get IAudioFlinger instead of by atomic pointer.
// This allows moving oboeservice (AAudio) to a separate process in the future.
sp<AudioFlinger> af = AudioFlinger::gAudioFlinger.load(); // either nullptr or singleton AF.
status_t ret = NO_INIT;
@@ -638,7 +522,7 @@
__func__, callingUid, callingPid, clientPid);
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
}
- adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ adjAttributionSource = afutils::checkAttributionSourcePackage(
adjAttributionSource);
if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
@@ -676,11 +560,14 @@
return ret;
}
+ // use unique_lock as we may selectively unlock.
+ audio_utils::unique_lock l(mutex());
+
// at this stage, a MmapThread was created when openOutput() or openInput() was called by
// audio policy manager and we can retrieve it
- sp<MmapThread> thread = mMmapThreads.valueFor(io);
+ const sp<IAfMmapThread> thread = mMmapThreads.valueFor(io);
if (thread != 0) {
- interface = new MmapThreadHandle(thread);
+ interface = IAfMmapThread::createMmapStreamInterfaceAdapter(thread);
thread->configure(&localAttr, streamType, actualSessionId, callback, *deviceId, portId);
*handle = portId;
*sessionId = actualSessionId;
@@ -688,12 +575,14 @@
config->channel_mask = thread->channelMask();
config->format = thread->format();
} else {
+ l.unlock();
if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
AudioSystem::releaseOutput(portId);
} else {
AudioSystem::releaseInput(portId);
}
ret = NO_INIT;
+ // we don't reacquire the lock here as nothing left to do.
}
ALOGV("%s done status %d portId %d", __FUNCTION__, ret, portId);
@@ -701,37 +590,9 @@
return ret;
}
-/* static */
-os::HapticScale AudioFlinger::onExternalVibrationStart(
- const sp<os::ExternalVibration>& externalVibration) {
- sp<os::IExternalVibratorService> evs = getExternalVibratorService();
- if (evs != nullptr) {
- int32_t ret;
- binder::Status status = evs->onExternalVibrationStart(*externalVibration, &ret);
- if (status.isOk()) {
- ALOGD("%s, start external vibration with intensity as %d", __func__, ret);
- return os::ExternalVibration::externalVibrationScaleToHapticScale(ret);
- }
- }
- ALOGD("%s, start external vibration with intensity as MUTE due to %s",
- __func__,
- evs == nullptr ? "external vibration service not found"
- : "error when querying intensity");
- return os::HapticScale::MUTE;
-}
-
-/* static */
-void AudioFlinger::onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration) {
- sp<os::IExternalVibratorService> evs = getExternalVibratorService();
- if (evs != 0) {
- ALOGD("%s, stopping external vibration", __func__);
- evs->onExternalVibrationStop(*externalVibration);
- }
-}
-
status_t AudioFlinger::addEffectToHal(
const struct audio_port_config *device, const sp<EffectHalInterface>& effect) {
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(device->ext.device.hw_module);
if (audioHwDevice == nullptr) {
return NO_INIT;
@@ -741,7 +602,7 @@
status_t AudioFlinger::removeEffectFromHal(
const struct audio_port_config *device, const sp<EffectHalInterface>& effect) {
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(device->ext.device.hw_module);
if (audioHwDevice == nullptr) {
return NO_INIT;
@@ -761,11 +622,11 @@
{
// if module is 0, the request comes from an old policy manager and we should load
// well known modules
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (module == 0) {
ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
for (size_t i = 0; i < arraysize(audio_interfaces); i++) {
- loadHwModule_l(audio_interfaces[i]);
+ loadHwModule_ll(audio_interfaces[i]);
}
// then try to find a module supporting the requested device.
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -788,7 +649,7 @@
return NULL;
}
-void AudioFlinger::dumpClients(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::dumpClients_ll(int fd, const Vector<String16>& args __unused)
{
String8 result;
@@ -822,17 +683,14 @@
}
-void AudioFlinger::dumpInternals(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::dumpInternals_l(int fd, const Vector<String16>& args __unused)
{
const size_t SIZE = 256;
char buffer[SIZE];
String8 result;
hardware_call_state hardwareStatus = mHardwareStatus;
- snprintf(buffer, SIZE, "Hardware status: %d\n"
- "Standby Time mSec: %u\n",
- hardwareStatus,
- (uint32_t)(mStandbyTimeInNsecs / 1000000));
+ snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
result.append(buffer);
write(fd, result.c_str(), result.size());
@@ -857,12 +715,6 @@
write(fd, result.c_str(), result.size());
}
-bool AudioFlinger::dumpTryLock(Mutex& mutex)
-{
- status_t err = mutex.timedLock(kDumpLockTimeoutNs);
- return err == NO_ERROR;
-}
-
status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
@@ -870,15 +722,15 @@
dumpPermissionDenial(fd, args);
} else {
// get state of hardware lock
- bool hardwareLocked = dumpTryLock(mHardwareLock);
+ const bool hardwareLocked = afutils::dumpTryLock(hardwareMutex());
if (!hardwareLocked) {
String8 result(kHardwareLockedString);
write(fd, result.c_str(), result.size());
} else {
- mHardwareLock.unlock();
+ hardwareMutex().unlock();
}
- const bool locked = dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
@@ -886,7 +738,7 @@
write(fd, result.c_str(), result.size());
}
- bool clientLocked = dumpTryLock(mClientLock);
+ const bool clientLocked = afutils::dumpTryLock(clientMutex());
if (!clientLocked) {
String8 result(kClientLockedString);
write(fd, result.c_str(), result.size());
@@ -899,12 +751,12 @@
write(fd, result.c_str(), result.size());
}
- dumpClients(fd, args);
+ dumpClients_ll(fd, args);
if (clientLocked) {
- mClientLock.unlock();
+ clientMutex().unlock();
}
- dumpInternals(fd, args);
+ dumpInternals_l(fd, args);
// dump playback threads
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -934,7 +786,7 @@
dev->dump(fd, args);
}
- mPatchPanel.dump(fd);
+ mPatchPanel->dump(fd);
mDeviceEffectManager->dump(fd);
@@ -959,7 +811,7 @@
BUFLOG_RESET;
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
#ifdef TEE_SINK
@@ -1029,14 +881,14 @@
return NO_ERROR;
}
-sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)
+sp<Client> AudioFlinger::registerPid(pid_t pid)
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
// If pid is already in the mClients wp<> map, then use that entry
// (for which promote() is always != 0), otherwise create a new entry and Client.
sp<Client> client = mClients.valueFor(pid).promote();
if (client == 0) {
- client = new Client(this, pid);
+ client = sp<Client>::make(sp<IAfClientCallback>::fromExisting(this), pid);
mClients.add(pid, client);
}
@@ -1054,7 +906,7 @@
// If allocation fails, consult the vector of previously unregistered writers
// and garbage-collect one or more them until an allocation succeeds
if (shared == 0) {
- Mutex::Autolock _l(mUnregisteredWritersLock);
+ audio_utils::lock_guard _l(unregisteredWritersMutex());
for (size_t count = mUnregisteredWriters.size(); count > 0; count--) {
{
// Pick the oldest stale writer to garbage-collect
@@ -1094,7 +946,7 @@
}
// Rather than removing the writer immediately, append it to a queue of old writers to
// be garbage-collected later. This allows us to continue to view old logs for a while.
- Mutex::Autolock _l(mUnregisteredWritersLock);
+ audio_utils::lock_guard _l(unregisteredWritersMutex());
mUnregisteredWriters.push(writer);
}
@@ -1107,8 +959,7 @@
CreateTrackInput input = VALUE_OR_RETURN_STATUS(CreateTrackInput::fromAidl(_input));
CreateTrackOutput output;
- sp<PlaybackThread::Track> track;
- sp<TrackHandle> trackHandle;
+ sp<IAfTrack> track;
sp<Client> client;
status_t lStatus;
audio_stream_type_t streamType;
@@ -1145,7 +996,7 @@
clientPid = callingPid;
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
}
- adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ adjAttributionSource = afutils::checkAttributionSourcePackage(
adjAttributionSource);
audio_session_t sessionId = input.sessionId;
@@ -1191,8 +1042,8 @@
}
{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output.outputId);
+ audio_utils::lock_guard _l(mutex());
+ IAfPlaybackThread* thread = checkPlaybackThread_l(output.outputId);
if (thread == NULL) {
ALOGE("no playback thread found for output handle %d", output.outputId);
lStatus = BAD_VALUE;
@@ -1201,14 +1052,14 @@
client = registerPid(clientPid);
- PlaybackThread *effectThread = NULL;
+ IAfPlaybackThread* effectThread = nullptr;
// check if an effect chain with the same session ID is present on another
// output thread and move it here.
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+ sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
if (mPlaybackThreads.keyAt(i) != output.outputId) {
uint32_t sessions = t->hasAudioSession(sessionId);
- if (sessions & ThreadBase::EFFECT_SESSION) {
+ if (sessions & IAfThreadBase::EFFECT_SESSION) {
effectThread = t.get();
break;
}
@@ -1242,8 +1093,8 @@
output.portId = portId;
if (lStatus == NO_ERROR) {
- // no risk of deadlock because AudioFlinger::mLock is held
- Mutex::Autolock _dl(thread->mLock);
+ // no risk of deadlock because AudioFlinger::mutex() is held
+ audio_utils::lock_guard _dl(thread->mutex());
// Connect secondary outputs. Failure on a secondary output must not imped the primary
// Any secondary output setup failure will lead to a desync between the AP and AF until
// the track is destroyed.
@@ -1251,8 +1102,9 @@
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
if (effectThread != nullptr) {
- Mutex::Autolock _sl(effectThread->mLock);
- if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
+ // No thread safety analysis: double lock on a thread capability.
+ audio_utils::lock_guard_no_thread_safety_analysis _sl(effectThread->mutex());
+ if (moveEffectChain_ll(sessionId, effectThread, thread) == NO_ERROR) {
effectThreadId = thread->id();
effectIds = thread->getEffectIds_l(sessionId);
}
@@ -1281,11 +1133,11 @@
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the Track so that the
- // Client destructor is called by the TrackBase destructor with mClientLock held
- // Don't hold mClientLock when releasing the reference on the track as the
+ // Client destructor is called by the TrackBase destructor with clientMutex() held
+ // Don't hold clientMutex() when releasing the reference on the track as the
// destructor will acquire it.
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
client.clear();
}
track.clear();
@@ -1298,7 +1150,7 @@
AudioSystem::moveEffectsToIo(effectIds, effectThreadId);
}
- output.audioTrack = new TrackHandle(track);
+ output.audioTrack = IAfTrack::createIAudioTrackAdapter(track);
_output = VALUE_OR_FATAL(output.toAidl());
Exit:
@@ -1310,8 +1162,8 @@
uint32_t AudioFlinger::sampleRate(audio_io_handle_t ioHandle) const
{
- Mutex::Autolock _l(mLock);
- ThreadBase *thread = checkThread_l(ioHandle);
+ audio_utils::lock_guard _l(mutex());
+ IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("sampleRate() unknown thread %d", ioHandle);
return 0;
@@ -1321,8 +1173,8 @@
audio_format_t AudioFlinger::format(audio_io_handle_t output) const
{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ audio_utils::lock_guard _l(mutex());
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("format() unknown thread %d", output);
return AUDIO_FORMAT_INVALID;
@@ -1332,8 +1184,8 @@
size_t AudioFlinger::frameCount(audio_io_handle_t ioHandle) const
{
- Mutex::Autolock _l(mLock);
- ThreadBase *thread = checkThread_l(ioHandle);
+ audio_utils::lock_guard _l(mutex());
+ IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("frameCount() unknown thread %d", ioHandle);
return 0;
@@ -1345,8 +1197,8 @@
size_t AudioFlinger::frameCountHAL(audio_io_handle_t ioHandle) const
{
- Mutex::Autolock _l(mLock);
- ThreadBase *thread = checkThread_l(ioHandle);
+ audio_utils::lock_guard _l(mutex());
+ IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("frameCountHAL() unknown thread %d", ioHandle);
return 0;
@@ -1356,8 +1208,8 @@
uint32_t AudioFlinger::latency(audio_io_handle_t output) const
{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ audio_utils::lock_guard _l(mutex());
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("latency(): no playback thread found for output handle %d", output);
return 0;
@@ -1377,12 +1229,12 @@
return PERMISSION_DENIED;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mMasterVolume = value;
// Set master volume in the HALs which support it.
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
@@ -1424,7 +1276,7 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// short cut.
if (mMasterBalance == balance) return NO_ERROR;
@@ -1458,18 +1310,18 @@
}
{ // scope for the lock
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
mHardwareStatus = AUDIO_HW_SET_MODE;
ret = dev->setMode(mode);
mHardwareStatus = AUDIO_HW_IDLE;
}
if (NO_ERROR == ret) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mMode = mode;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->setMode(mode);
@@ -1495,11 +1347,11 @@
return PERMISSION_DENIED;
}
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
- sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev.load()->hwDevice();
if (primaryDev == nullptr) {
ALOGW("%s: no primary HAL device", __func__);
return INVALID_OPERATION;
@@ -1523,11 +1375,11 @@
if (ret != NO_ERROR) {
return false;
}
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return false;
}
- sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev.load()->hwDevice();
if (primaryDev == nullptr) {
ALOGW("%s: no primary HAL device", __func__);
return false;
@@ -1544,7 +1396,7 @@
{
ALOGV("AudioFlinger::setRecordSilenced(portId:%d, silenced:%d)", portId, silenced);
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
for (size_t i = 0; i < mRecordThreads.size(); i++) {
mRecordThreads[i]->setRecordSilenced(portId, silenced);
}
@@ -1565,12 +1417,12 @@
return PERMISSION_DENIED;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mMasterMute = muted;
// Set master mute in the HALs which support it.
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
@@ -1586,7 +1438,7 @@
// assigned to HALs which do not have master mute support will apply master mute
// during the mix operation. Threads with HALs which do support master mute
// will simply ignore the setting.
- Vector<VolumeInterface *> volumeInterfaces = getAllVolumeInterfaces_l();
+ std::vector<sp<VolumeInterface>> volumeInterfaces = getAllVolumeInterfaces_l();
for (size_t i = 0; i < volumeInterfaces.size(); i++) {
volumeInterfaces[i]->setMasterMute(muted);
}
@@ -1596,20 +1448,20 @@
float AudioFlinger::masterVolume() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return masterVolume_l();
}
status_t AudioFlinger::getMasterBalance(float *balance) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
*balance = getMasterBalance_l();
return NO_ERROR; // if called through binder, may return a transactional error
}
bool AudioFlinger::masterMute() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return masterMute_l();
}
@@ -1628,7 +1480,8 @@
return mMasterMute;
}
-status_t AudioFlinger::checkStreamType(audio_stream_type_t stream) const
+/* static */
+status_t AudioFlinger::checkStreamType(audio_stream_type_t stream)
{
if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
ALOGW("checkStreamType() invalid stream %d", stream);
@@ -1661,8 +1514,8 @@
LOG_ALWAYS_FATAL_IF(stream == AUDIO_STREAM_PATCH && value != 1.0f,
"AUDIO_STREAM_PATCH must have full scale volume");
- AutoMutex lock(mLock);
- VolumeInterface *volumeInterface = getVolumeInterface_l(output);
+ audio_utils::lock_guard lock(mutex());
+ sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
if (volumeInterface == NULL) {
return BAD_VALUE;
}
@@ -1676,8 +1529,8 @@
if (output == AUDIO_IO_HANDLE_NONE) {
return BAD_VALUE;
}
- AutoMutex lock(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ audio_utils::lock_guard lock(mutex());
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == nullptr) {
return BAD_VALUE;
}
@@ -1685,12 +1538,12 @@
}
status_t AudioFlinger::getSupportedLatencyModes(audio_io_handle_t output,
- std::vector<audio_latency_mode_t>* modes) {
+ std::vector<audio_latency_mode_t>* modes) const {
if (output == AUDIO_IO_HANDLE_NONE) {
return BAD_VALUE;
}
- AutoMutex lock(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ audio_utils::lock_guard lock(mutex());
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == nullptr) {
return BAD_VALUE;
}
@@ -1698,7 +1551,7 @@
}
status_t AudioFlinger::setBluetoothVariableLatencyEnabled(bool enabled) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
status_t status = INVALID_OPERATION;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
// Success if at least one PlaybackThread supports Bluetooth latency modes
@@ -1712,7 +1565,7 @@
return status;
}
-status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool *enabled) {
+status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool* enabled) const {
if (enabled == nullptr) {
return BAD_VALUE;
}
@@ -1720,11 +1573,11 @@
return NO_ERROR;
}
-status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) {
+status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) const {
if (support == nullptr) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(hardwareMutex());
*support = false;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
if (mAudioHwDevs.valueAt(i)->supportsBluetoothVariableLatency()) {
@@ -1736,7 +1589,7 @@
}
status_t AudioFlinger::getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
- sp<media::ISoundDose>* soundDose) {
+ sp<media::ISoundDose>* soundDose) const {
if (soundDose == nullptr) {
return BAD_VALUE;
}
@@ -1763,9 +1616,9 @@
return BAD_VALUE;
}
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
mStreamTypes[stream].mute = muted;
- Vector<VolumeInterface *> volumeInterfaces = getAllVolumeInterfaces_l();
+ std::vector<sp<VolumeInterface>> volumeInterfaces = getAllVolumeInterfaces_l();
for (size_t i = 0; i < volumeInterfaces.size(); i++) {
volumeInterfaces[i]->setStreamMute(stream, muted);
}
@@ -1783,8 +1636,8 @@
return 0.0f;
}
- AutoMutex lock(mLock);
- VolumeInterface *volumeInterface = getVolumeInterface_l(output);
+ audio_utils::lock_guard lock(mutex());
+ sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
if (volumeInterface == NULL) {
return 0.0f;
}
@@ -1799,7 +1652,7 @@
return true;
}
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
return streamMute_l(stream);
}
@@ -1818,17 +1671,18 @@
}
}
-// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
+// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mutex() held
void AudioFlinger::forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
- const std::function<bool(const sp<PlaybackThread>&)>& useThread)
+ const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread)
{
- std::vector<PatchPanel::SoftwarePatch> swPatches;
- if (mPatchPanel.getDownstreamSoftwarePatches(upStream, &swPatches) != OK) return;
+ std::vector<SoftwarePatch> swPatches;
+ if (mPatchPanel->getDownstreamSoftwarePatches(upStream, &swPatches) != OK) return;
ALOGV_IF(!swPatches.empty(), "%s found %zu downstream patches for stream ID %d",
__func__, swPatches.size(), upStream);
for (const auto& swPatch : swPatches) {
- sp<PlaybackThread> downStream = checkPlaybackThread_l(swPatch.getPlaybackThreadHandle());
+ const sp<IAfPlaybackThread> downStream =
+ checkPlaybackThread_l(swPatch.getPlaybackThreadHandle());
if (downStream != NULL && (useThread == nullptr || useThread(downStream))) {
downStream->setParameters(keyValuePairs);
}
@@ -1840,7 +1694,7 @@
const std::set<audio_io_handle_t>& streams)
{
for (const audio_io_handle_t stream : streams) {
- PlaybackThread *playbackThread = checkPlaybackThread_l(stream);
+ IAfPlaybackThread* const playbackThread = checkPlaybackThread_l(stream);
if (playbackThread == nullptr || !playbackThread->isMsdDevice()) {
continue;
}
@@ -1922,11 +1776,11 @@
// AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// result will remain NO_INIT if no audio device is present
status_t final_result = NO_INIT;
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
mHardwareStatus = AUDIO_HW_SET_PARAMETER;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -1954,8 +1808,8 @@
String8 screenState;
if (param.get(String8(AudioParameter::keyScreenState), screenState) == NO_ERROR) {
bool isOff = (screenState == AudioParameter::valueOff);
- if (isOff != (AudioFlinger::mScreenState & 1)) {
- AudioFlinger::mScreenState = ((AudioFlinger::mScreenState & ~1) + 2) | isOff;
+ if (isOff != (mScreenState & 1)) {
+ mScreenState = ((mScreenState & ~1) + 2) | isOff;
}
}
return final_result;
@@ -1963,9 +1817,9 @@
// hold a strong ref on thread in case closeOutput() or closeInput() is called
// and the thread is exited once the lock is released
- sp<ThreadBase> thread;
+ sp<IAfThreadBase> thread;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
thread = checkPlaybackThread_l(ioHandle);
if (thread == 0) {
thread = checkRecordThread_l(ioHandle);
@@ -1984,6 +1838,7 @@
}
if (thread != 0) {
status_t result = thread->setParameters(filteredKeyValuePairs);
+ audio_utils::lock_guard _l(mutex());
forwardParametersToDownstreamPatches_l(thread->id(), filteredKeyValuePairs);
return result;
}
@@ -1995,12 +1850,12 @@
ALOGVV("getParameters() io %d, keys %s, calling pid %d",
ioHandle, keys.c_str(), IPCThreadState::self()->getCallingPid());
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
String8 out_s8;
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
String8 s;
mHardwareStatus = AUDIO_HW_GET_PARAMETER;
@@ -2012,11 +1867,11 @@
return out_s8;
}
- ThreadBase *thread = (ThreadBase *)checkPlaybackThread_l(ioHandle);
+ IAfThreadBase* thread = checkPlaybackThread_l(ioHandle);
if (thread == NULL) {
- thread = (ThreadBase *)checkRecordThread_l(ioHandle);
+ thread = checkRecordThread_l(ioHandle);
if (thread == NULL) {
- thread = (ThreadBase *)checkMmapThread_l(ioHandle);
+ thread = checkMmapThread_l(ioHandle);
if (thread == NULL) {
return String8("");
}
@@ -2038,13 +1893,13 @@
return 0;
}
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return 0;
}
mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
std::vector<audio_channel_mask_t> channelMasks = {channelMask};
if (channelMask != AUDIO_CHANNEL_IN_MONO) {
@@ -2110,9 +1965,9 @@
uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
- RecordThread *recordThread = checkRecordThread_l(ioHandle);
+ IAfRecordThread* const recordThread = checkRecordThread_l(ioHandle);
if (recordThread != NULL) {
return recordThread->getInputFramesLost();
}
@@ -2131,11 +1986,11 @@
return PERMISSION_DENIED;
}
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
ret = dev->setVoiceVolume(value);
mHardwareStatus = AUDIO_HW_IDLE;
@@ -2150,9 +2005,9 @@
status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
audio_io_handle_t output) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
- PlaybackThread *playbackThread = checkPlaybackThread_l(output);
+ IAfPlaybackThread* const playbackThread = checkPlaybackThread_l(output);
if (playbackThread != NULL) {
return playbackThread->getRenderPosition(halFrames, dspFrames);
}
@@ -2162,14 +2017,14 @@
void AudioFlinger::registerClient(const sp<media::IAudioFlingerClient>& client)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (client == 0) {
return;
}
pid_t pid = IPCThreadState::self()->getCallingPid();
const uid_t uid = IPCThreadState::self()->getCallingUid();
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
if (mNotificationClients.indexOfKey(pid) < 0) {
sp<NotificationClient> notificationClient = new NotificationClient(this,
client,
@@ -2185,9 +2040,10 @@
}
}
- // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the
- // ThreadBase mutex and the locking order is ThreadBase::mLock then AudioFlinger::mClientLock.
- // the config change is always sent from playback or record threads to avoid deadlock
+ // clientMutex() should not be held here because ThreadBase::sendIoConfigEvent()
+ // will lock the ThreadBase::mutex() and the locking order is
+ // ThreadBase::mutex() then AudioFlinger::clientMutex().
+ // The config change is always sent from playback or record threads to avoid deadlock
// with AudioSystem::gLock
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_REGISTERED, pid);
@@ -2200,11 +2056,11 @@
void AudioFlinger::removeNotificationClient(pid_t pid)
{
- std::vector< sp<AudioFlinger::EffectModule> > removedEffects;
+ std::vector<sp<IAfEffectModule>> removedEffects;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
mNotificationClients.removeItem(pid);
}
@@ -2241,7 +2097,7 @@
media::AudioIoDescriptor descAidl = VALUE_OR_FATAL(
legacy2aidl_AudioIoDescriptor_AudioIoDescriptor(ioDesc));
- Mutex::Autolock _l(mClientLock);
+ audio_utils::lock_guard _l(clientMutex());
size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
if ((pid == 0) || (mNotificationClients.keyAt(i) == pid)) {
@@ -2258,7 +2114,7 @@
convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
- Mutex::Autolock _l(mClientLock);
+ audio_utils::lock_guard _l(clientMutex());
size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
mNotificationClients.valueAt(i)->audioFlingerClient()
@@ -2266,7 +2122,7 @@
}
}
-// removeClient_l() must be called with AudioFlinger::mClientLock held
+// removeClient_l() must be called with AudioFlinger::clientMutex() held
void AudioFlinger::removeClient_l(pid_t pid)
{
ALOGV("removeClient_l() pid %d, calling pid %d", pid,
@@ -2274,11 +2130,11 @@
mClients.removeItem(pid);
}
-// getEffectThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::ThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
+// getEffectThread_l() must be called with AudioFlinger::mutex() held
+sp<IAfThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
int effectId)
{
- sp<ThreadBase> thread;
+ sp<IAfThreadBase> thread;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
@@ -2307,27 +2163,6 @@
return thread;
}
-
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
- : RefBase(),
- mAudioFlinger(audioFlinger),
- mPid(pid),
- mClientAllocator(AllocatorFactory::getClientAllocator()) {}
-
-// Client destructor must be called with AudioFlinger::mClientLock held
-AudioFlinger::Client::~Client()
-{
- mAudioFlinger->removeClient_l(mPid);
-}
-
-AllocatorFactory::ClientAllocator& AudioFlinger::Client::allocator()
-{
- return mClientAllocator;
-}
-
// ----------------------------------------------------------------------------
AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
@@ -2354,9 +2189,9 @@
void AudioFlinger::MediaLogNotifier::requestMerge() {
- AutoMutex _l(mMutex);
+ audio_utils::lock_guard _l(mMutex);
mPendingRequests = true;
- mCond.signal();
+ mCondition.notify_one();
}
bool AudioFlinger::MediaLogNotifier::threadLoop() {
@@ -2366,10 +2201,10 @@
}
// Wait until there are pending requests
{
- AutoMutex _l(mMutex);
+ audio_utils::unique_lock _l(mMutex);
mPendingRequests = false; // to ignore past requests
while (!mPendingRequests) {
- mCond.wait(mMutex);
+ mCondition.wait(_l);
// TODO may also need an exitPending check
}
mPendingRequests = false;
@@ -2392,8 +2227,7 @@
CreateRecordInput input = VALUE_OR_RETURN_STATUS(CreateRecordInput::fromAidl(_input));
CreateRecordOutput output;
- sp<RecordThread::RecordTrack> recordTrack;
- sp<RecordHandle> recordHandle;
+ sp<IAfRecordTrack> recordTrack;
sp<Client> client;
status_t lStatus;
audio_session_t sessionId = input.sessionId;
@@ -2425,7 +2259,7 @@
__func__, callingUid, callingPid, currentPid);
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
}
- adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ 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)) {
@@ -2481,8 +2315,8 @@
}
{
- Mutex::Autolock _l(mLock);
- RecordThread *thread = checkRecordThread_l(output.inputId);
+ audio_utils::lock_guard _l(mutex());
+ IAfRecordThread* const thread = checkRecordThread_l(output.inputId);
if (thread == NULL) {
ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
lStatus = FAILED_TRANSACTION;
@@ -2536,9 +2370,9 @@
// Check if one effect chain was awaiting for an AudioRecord to be created on this
// session and move it to this thread.
- sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l2(thread->mLock);
+ audio_utils::lock_guard _l2(thread->mutex());
thread->addEffectChain_l(chain);
}
break;
@@ -2551,17 +2385,17 @@
output.buffers = recordTrack->getBuffers();
output.portId = portId;
- output.audioRecord = new RecordHandle(recordTrack);
+ output.audioRecord = IAfRecordTrack::createIAudioRecordAdapter(recordTrack);
_output = VALUE_OR_FATAL(output.toAidl());
Exit:
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the RecordTrack so that the
- // Client destructor is called by the TrackBase destructor with mClientLock held
- // Don't hold mClientLock when releasing the reference on the track as the
+ // Client destructor is called by the TrackBase destructor with clientMutex() held
+ // Don't hold clientMutex() when releasing the reference on the track as the
// destructor will acquire it.
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
client.clear();
}
recordTrack.clear();
@@ -2582,8 +2416,8 @@
if (config == nullptr) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
RETURN_STATUS_IF_ERROR(
mDevicesFactoryHal->getSurroundSoundConfig(&config->surroundSoundConfig));
RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getEngineConfig(&config->engineConfig));
@@ -2591,7 +2425,7 @@
RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getDeviceNames(&hwModuleNames));
std::set<AudioMode> allSupportedModes;
for (const auto& name : hwModuleNames) {
- AudioHwDevice* module = loadHwModule_l(name.c_str());
+ AudioHwDevice* module = loadHwModule_ll(name.c_str());
if (module == nullptr) continue;
media::AudioHwModule aidlModule;
if (module->hwDevice()->getAudioPorts(&aidlModule.ports) == OK &&
@@ -2626,14 +2460,15 @@
if (!settingsAllowed()) {
return AUDIO_MODULE_HANDLE_NONE;
}
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
- AudioHwDevice* module = loadHwModule_l(name);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
+ AudioHwDevice* module = loadHwModule_ll(name);
return module != nullptr ? module->handle() : AUDIO_MODULE_HANDLE_NONE;
}
-// loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
-AudioHwDevice* AudioFlinger::loadHwModule_l(const char *name)
+// loadHwModule_l() must be called with AudioFlinger::mutex()
+// and AudioFlinger::hardwareMutex() held
+AudioHwDevice* AudioFlinger::loadHwModule_ll(const char *name)
{
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
@@ -2712,7 +2547,7 @@
if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
mPrimaryHardwareDev = audioDevice;
mHardwareStatus = AUDIO_HW_SET_MODE;
- mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+ mPrimaryHardwareDev.load()->hwDevice()->setMode(mMode);
mHardwareStatus = AUDIO_HW_IDLE;
}
@@ -2737,17 +2572,17 @@
// ----------------------------------------------------------------------------
-uint32_t AudioFlinger::getPrimaryOutputSamplingRate()
+uint32_t AudioFlinger::getPrimaryOutputSamplingRate() const
{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = fastPlaybackThread_l();
+ audio_utils::lock_guard _l(mutex());
+ IAfPlaybackThread* const thread = fastPlaybackThread_l();
return thread != NULL ? thread->sampleRate() : 0;
}
-size_t AudioFlinger::getPrimaryOutputFrameCount()
+size_t AudioFlinger::getPrimaryOutputFrameCount() const
{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = fastPlaybackThread_l();
+ audio_utils::lock_guard _l(mutex());
+ IAfPlaybackThread* const thread = fastPlaybackThread_l();
return thread != NULL ? thread->frameCountHAL() : 0;
}
@@ -2759,7 +2594,7 @@
if (!isAudioServerOrSystemServerUid(uid)) {
return PERMISSION_DENIED;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mIsDeviceTypeKnown) {
return INVALID_OPERATION;
}
@@ -2817,8 +2652,8 @@
module = config->ext.mix.hw_module;
}
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
ssize_t index = mAudioHwDevs.indexOfKey(module);
if (index < 0) {
ALOGW("%s() bad hw module %d", __func__, module);
@@ -2831,7 +2666,7 @@
audio_hw_sync_t AudioFlinger::getAudioHwSyncForSession(audio_session_t sessionId)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
if (index >= 0) {
@@ -2842,11 +2677,11 @@
sp<DeviceHalInterface> dev;
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return AUDIO_HW_SYNC_INVALID;
}
- dev = mPrimaryHardwareDev->hwDevice();
+ dev = mPrimaryHardwareDev.load()->hwDevice();
}
if (dev == nullptr) {
return AUDIO_HW_SYNC_INVALID;
@@ -2872,15 +2707,15 @@
mHwAvSyncIds.add(sessionId, value);
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- sp<PlaybackThread> thread = mPlaybackThreads.valueAt(i);
+ const sp<IAfPlaybackThread> thread = mPlaybackThreads.valueAt(i);
uint32_t sessions = thread->hasAudioSession(sessionId);
- if (sessions & ThreadBase::TRACK_SESSION) {
+ if (sessions & IAfThreadBase::TRACK_SESSION) {
AudioParameter param = AudioParameter();
param.addInt(String8(AudioParameter::keyStreamHwAvSync), value);
String8 keyValuePairs = param.toString();
thread->setParameters(keyValuePairs);
forwardParametersToDownstreamPatches_l(thread->id(), keyValuePairs,
- [](const sp<PlaybackThread>& thread) { return thread->usesHwAvSync(); });
+ [](const sp<IAfPlaybackThread>& thread) { return thread->usesHwAvSync(); });
break;
}
}
@@ -2891,7 +2726,7 @@
status_t AudioFlinger::systemReady()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGI("%s", __FUNCTION__);
if (mSystemReady) {
ALOGW("%s called twice", __FUNCTION__);
@@ -2899,15 +2734,15 @@
}
mSystemReady = true;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- ThreadBase *thread = (ThreadBase *)mPlaybackThreads.valueAt(i).get();
+ IAfThreadBase* const thread = mPlaybackThreads.valueAt(i).get();
thread->systemReady();
}
for (size_t i = 0; i < mRecordThreads.size(); i++) {
- ThreadBase *thread = (ThreadBase *)mRecordThreads.valueAt(i).get();
+ IAfThreadBase* const thread = mRecordThreads.valueAt(i).get();
thread->systemReady();
}
for (size_t i = 0; i < mMmapThreads.size(); i++) {
- ThreadBase *thread = (ThreadBase *)mMmapThreads.valueAt(i).get();
+ IAfThreadBase* const thread = mMmapThreads.valueAt(i).get();
thread->systemReady();
}
@@ -2932,9 +2767,9 @@
return mAudioManager.load();
}
-status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones)
+status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
status_t status = INVALID_OPERATION;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -2958,8 +2793,9 @@
return status;
}
-// setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId)
+// setAudioHwSyncForSession_l() must be called with AudioFlinger::mutex() held
+void AudioFlinger::setAudioHwSyncForSession_l(
+ IAfPlaybackThread* const thread, audio_session_t sessionId)
{
ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
if (index >= 0) {
@@ -2970,7 +2806,7 @@
String8 keyValuePairs = param.toString();
thread->setParameters(keyValuePairs);
forwardParametersToDownstreamPatches_l(thread->id(), keyValuePairs,
- [](const sp<PlaybackThread>& thread) { return thread->usesHwAvSync(); });
+ [](const sp<IAfPlaybackThread>& thread) { return thread->usesHwAvSync(); });
}
}
@@ -2978,7 +2814,7 @@
// ----------------------------------------------------------------------------
-sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
+sp<IAfThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *halConfig,
audio_config_base_t *mixerConfig,
@@ -3001,28 +2837,6 @@
}
mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
-
- // FOR TESTING ONLY:
- // This if statement allows overriding the audio policy settings
- // and forcing a specific format or channel mask to the HAL/Sink device for testing.
- if (!(flags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT))) {
- // Check only for Normal Mixing mode
- if (kEnableExtendedPrecision) {
- // Specify format (uncomment one below to choose)
- //halConfig->format = AUDIO_FORMAT_PCM_FLOAT;
- //halConfig->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
- //halConfig->format = AUDIO_FORMAT_PCM_32_BIT;
- //halConfig->format = AUDIO_FORMAT_PCM_8_24_BIT;
- // ALOGV("openOutput_l() upgrading format to %#08x", halConfig->format);
- }
- if (kEnableExtendedChannels) {
- // Specify channel mask (uncomment one below to choose)
- //halConfig->channel_mask = audio_channel_out_mask_from_count(4); // for USB 4ch
- //halConfig->channel_mask = audio_channel_mask_from_representation_and_bits(
- // AUDIO_CHANNEL_REPRESENTATION_INDEX, (1 << 4) - 1); // another 4ch example
- }
- }
-
AudioStreamOut *outputStream = NULL;
status_t status = outHwDev->openOutputStream(
&outputStream,
@@ -3036,43 +2850,45 @@
if (status == NO_ERROR) {
if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
- sp<MmapPlaybackThread> thread =
- new MmapPlaybackThread(this, *output, outHwDev, outputStream, mSystemReady);
+ const sp<IAfMmapPlaybackThread> thread = IAfMmapPlaybackThread::create(
+ this, *output, outHwDev, outputStream, mSystemReady);
mMmapThreads.add(*output, thread);
ALOGV("openOutput_l() created mmap playback thread: ID %d thread %p",
*output, thread.get());
return thread;
} else {
- sp<PlaybackThread> thread;
+ sp<IAfPlaybackThread> thread;
if (flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
- thread = sp<BitPerfectThread>::make(this, outputStream, *output, mSystemReady);
+ thread = IAfPlaybackThread::createBitPerfectThread(
+ this, outputStream, *output, mSystemReady);
ALOGV("%s() created bit-perfect output: ID %d thread %p",
__func__, *output, thread.get());
} else if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
- thread = new SpatializerThread(this, outputStream, *output,
+ thread = IAfPlaybackThread::createSpatializerThread(this, outputStream, *output,
mSystemReady, mixerConfig);
ALOGV("openOutput_l() created spatializer output: ID %d thread %p",
*output, thread.get());
} else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
- thread = new OffloadThread(this, outputStream, *output,
+ thread = IAfPlaybackThread::createOffloadThread(this, outputStream, *output,
mSystemReady, halConfig->offload_info);
ALOGV("openOutput_l() created offload output: ID %d thread %p",
*output, thread.get());
} else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
- || !isValidPcmSinkFormat(halConfig->format)
- || !isValidPcmSinkChannelMask(halConfig->channel_mask)) {
- thread = new DirectOutputThread(this, outputStream, *output,
+ || !IAfThreadBase::isValidPcmSinkFormat(halConfig->format)
+ || !IAfThreadBase::isValidPcmSinkChannelMask(halConfig->channel_mask)) {
+ thread = IAfPlaybackThread::createDirectOutputThread(this, outputStream, *output,
mSystemReady, halConfig->offload_info);
ALOGV("openOutput_l() created direct output: ID %d thread %p",
*output, thread.get());
} else {
- thread = new MixerThread(this, outputStream, *output, mSystemReady);
+ thread = IAfPlaybackThread::createMixerThread(
+ this, outputStream, *output, mSystemReady);
ALOGV("openOutput_l() created mixer output: ID %d thread %p",
*output, thread.get());
}
mPlaybackThreads.add(*output, thread);
struct audio_patch patch;
- mPatchPanel.notifyStreamOpened(outHwDev, *output, &patch);
+ mPatchPanel->notifyStreamOpened(outHwDev, *output, &patch);
if (thread->isMsdDevice()) {
thread->setDownStreamPatch(&patch);
}
@@ -3116,14 +2932,14 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
- sp<ThreadBase> thread = openOutput_l(module, &output, &halConfig,
+ const sp<IAfThreadBase> thread = openOutput_l(module, &output, &halConfig,
&mixerConfig, deviceType, address, flags);
if (thread != 0) {
uint32_t latencyMs = 0;
if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ const auto playbackThread = thread->asIAfPlaybackThread();
latencyMs = playbackThread->latency();
// notify client processes of the new output creation
@@ -3131,18 +2947,17 @@
// the first primary output opened designates the primary hw device if no HW module
// named "primary" was already loaded.
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if ((mPrimaryHardwareDev == nullptr) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
ALOGI("Using module %d as the primary audio interface", module);
mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
mHardwareStatus = AUDIO_HW_SET_MODE;
- mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+ mPrimaryHardwareDev.load()->hwDevice()->setMode(mMode);
mHardwareStatus = AUDIO_HW_IDLE;
}
} else {
- MmapThread *mmapThread = (MmapThread *)thread.get();
- mmapThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
+ thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
}
response->output = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
response->config = VALUE_OR_RETURN_STATUS(
@@ -3159,9 +2974,9 @@
audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
audio_io_handle_t output2)
{
- Mutex::Autolock _l(mLock);
- MixerThread *thread1 = checkMixerThread_l(output1);
- MixerThread *thread2 = checkMixerThread_l(output2);
+ audio_utils::lock_guard _l(mutex());
+ IAfPlaybackThread* const thread1 = checkMixerThread_l(output1);
+ IAfPlaybackThread* const thread2 = checkMixerThread_l(output2);
if (thread1 == NULL || thread2 == NULL) {
ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1,
@@ -3170,7 +2985,8 @@
}
audio_io_handle_t id = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
- DuplicatingThread *thread = new DuplicatingThread(this, thread1, id, mSystemReady);
+ const sp<IAfDuplicatingThread> thread = IAfDuplicatingThread::create(
+ this, thread1, id, mSystemReady);
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
// notify client processes of the new output creation
@@ -3187,22 +3003,22 @@
{
// keep strong reference on the playback thread so that
// it is not destroyed while exit() is executed
- sp<PlaybackThread> playbackThread;
- sp<MmapPlaybackThread> mmapThread;
+ sp<IAfPlaybackThread> playbackThread;
+ sp<IAfMmapPlaybackThread> mmapThread;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
playbackThread = checkPlaybackThread_l(output);
if (playbackThread != NULL) {
ALOGV("closeOutput() %d", output);
dumpToThreadLog_l(playbackThread);
- if (playbackThread->type() == ThreadBase::MIXER) {
+ if (playbackThread->type() == IAfThreadBase::MIXER) {
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
- DuplicatingThread *dupThread =
- (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
- dupThread->removeOutputTrack((MixerThread *)playbackThread.get());
+ IAfDuplicatingThread* const dupThread =
+ mPlaybackThreads.valueAt(i)->asIAfDuplicatingThread().get();
+ dupThread->removeOutputTrack(playbackThread.get());
}
}
}
@@ -3211,20 +3027,22 @@
mPlaybackThreads.removeItem(output);
// save all effects to the default thread
if (mPlaybackThreads.size()) {
- PlaybackThread *dstThread = checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
+ IAfPlaybackThread* const dstThread =
+ checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
if (dstThread != NULL) {
// audioflinger lock is held so order of thread lock acquisition doesn't matter
- Mutex::Autolock _dl(dstThread->mLock);
- Mutex::Autolock _sl(playbackThread->mLock);
- Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
+ // Use scoped_lock to avoid deadlock order issues with duplicating threads.
+ audio_utils::scoped_lock sl(dstThread->mutex(), playbackThread->mutex());
+ Vector<sp<IAfEffectChain>> effectChains = playbackThread->getEffectChains_l();
for (size_t i = 0; i < effectChains.size(); i ++) {
- moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
+ moveEffectChain_ll(effectChains[i]->sessionId(), playbackThread.get(),
dstThread);
}
}
}
} else {
- mmapThread = (MmapPlaybackThread *)checkMmapThread_l(output);
+ const sp<IAfMmapThread> mt = checkMmapThread_l(output);
+ mmapThread = mt ? mt->asIAfMmapPlaybackThread().get() : nullptr;
if (mmapThread == 0) {
return BAD_VALUE;
}
@@ -3233,10 +3051,10 @@
ALOGD("closing mmapThread %p", mmapThread.get());
}
ioConfigChanged(AUDIO_OUTPUT_CLOSED, sp<AudioIoDescriptor>::make(output));
- mPatchPanel.notifyStreamClosed(output);
+ mPatchPanel->notifyStreamClosed(output);
}
// The thread entity (active unit of execution) is no longer running here,
- // but the ThreadBase container still exists.
+ // but the IAfThreadBase container still exists.
if (playbackThread != 0) {
playbackThread->exit();
@@ -3254,7 +3072,8 @@
return NO_ERROR;
}
-void AudioFlinger::closeOutputFinish(const sp<PlaybackThread>& thread)
+/* static */
+void AudioFlinger::closeOutputFinish(const sp<IAfPlaybackThread>& thread)
{
AudioStreamOut *out = thread->clearOutput();
ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
@@ -3262,17 +3081,17 @@
delete out;
}
-void AudioFlinger::closeThreadInternal_l(const sp<PlaybackThread>& thread)
+void AudioFlinger::closeThreadInternal_l(const sp<IAfPlaybackThread>& thread)
{
- mPlaybackThreads.removeItem(thread->mId);
+ mPlaybackThreads.removeItem(thread->id());
thread->exit();
closeOutputFinish(thread);
}
status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ audio_utils::lock_guard _l(mutex());
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
return BAD_VALUE;
@@ -3286,8 +3105,8 @@
status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ audio_utils::lock_guard _l(mutex());
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
return BAD_VALUE;
@@ -3303,7 +3122,7 @@
status_t AudioFlinger::openInput(const media::OpenInputRequest& request,
media::OpenInputResponse* response)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioDeviceTypeAddr device = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioDeviceTypeAddress(request.device));
@@ -3316,7 +3135,7 @@
audio_config_t config = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioConfig_audio_config_t(request.config, true /*isInput*/));
- sp<ThreadBase> thread = openInput_l(
+ const sp<IAfThreadBase> thread = openInput_l(
VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_module_handle_t(request.module)),
&input,
&config,
@@ -3340,7 +3159,7 @@
return NO_INIT;
}
-sp<AudioFlinger::ThreadBase> AudioFlinger::openInput_l(audio_module_handle_t module,
+sp<IAfThreadBase> AudioFlinger::openInput_l(audio_module_handle_t module,
audio_io_handle_t *input,
audio_config_t *config,
audio_devices_t devices,
@@ -3406,17 +3225,18 @@
if (status == NO_ERROR && inStream != 0) {
AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
- sp<MmapCaptureThread> thread =
- new MmapCaptureThread(this, *input, inHwDev, inputStream, mSystemReady);
+ const sp<IAfMmapCaptureThread> thread =
+ IAfMmapCaptureThread::create(this, *input, inHwDev, inputStream, mSystemReady);
mMmapThreads.add(*input, thread);
ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
thread.get());
return thread;
} else {
// Start record thread
- // RecordThread requires both input and output device indication to forward to audio
- // pre processing modules
- sp<RecordThread> thread = new RecordThread(this, inputStream, *input, mSystemReady);
+ // IAfRecordThread requires both input and output device indication
+ // to forward to audio pre processing modules
+ const sp<IAfRecordThread> thread =
+ IAfRecordThread::create(this, inputStream, *input, mSystemReady);
mRecordThreads.add(*input, thread);
ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());
return thread;
@@ -3436,10 +3256,10 @@
{
// keep strong reference on the record thread so that
// it is not destroyed while exit() is executed
- sp<RecordThread> recordThread;
- sp<MmapCaptureThread> mmapThread;
+ sp<IAfRecordThread> recordThread;
+ sp<IAfMmapCaptureThread> mmapThread;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
recordThread = checkRecordThread_l(input);
if (recordThread != 0) {
ALOGV("closeInput() %d", input);
@@ -3450,10 +3270,10 @@
// on at least one effect. We must either move the chain to an existing thread with the
// same session ID or put it aside in case a new record thread is opened for a
// new capture on the same session
- sp<EffectChain> chain;
+ sp<IAfEffectChain> chain;
{
- Mutex::Autolock _sl(recordThread->mLock);
- Vector< sp<EffectChain> > effectChains = recordThread->getEffectChains_l();
+ audio_utils::lock_guard _sl(recordThread->mutex());
+ const Vector<sp<IAfEffectChain>> effectChains = recordThread->getEffectChains_l();
// Note: maximum one chain per record thread
if (effectChains.size() != 0) {
chain = effectChains[0];
@@ -3465,12 +3285,12 @@
// creation of its replacement
size_t i;
for (i = 0; i < mRecordThreads.size(); i++) {
- sp<RecordThread> t = mRecordThreads.valueAt(i);
+ const sp<IAfRecordThread> t = mRecordThreads.valueAt(i);
if (t == recordThread) {
continue;
}
if (t->hasAudioSession(chain->sessionId()) != 0) {
- Mutex::Autolock _l2(t->mLock);
+ audio_utils::lock_guard _l2(t->mutex());
ALOGV("closeInput() found thread %d for effect session %d",
t->id(), chain->sessionId());
t->addEffectChain_l(chain);
@@ -3484,7 +3304,8 @@
}
mRecordThreads.removeItem(input);
} else {
- mmapThread = (MmapCaptureThread *)checkMmapThread_l(input);
+ const sp<IAfMmapThread> mt = checkMmapThread_l(input);
+ mmapThread = mt ? mt->asIAfMmapCaptureThread().get() : nullptr;
if (mmapThread == 0) {
return BAD_VALUE;
}
@@ -3493,7 +3314,7 @@
}
ioConfigChanged(AUDIO_INPUT_CLOSED, sp<AudioIoDescriptor>::make(input));
}
- // FIXME: calling thread->exit() without mLock held should not be needed anymore now that
+ // FIXME: calling thread->exit() without mutex() held should not be needed anymore now that
// we have a different lock for notification client
if (recordThread != 0) {
closeInputFinish(recordThread);
@@ -3507,7 +3328,7 @@
return NO_ERROR;
}
-void AudioFlinger::closeInputFinish(const sp<RecordThread>& thread)
+void AudioFlinger::closeInputFinish(const sp<IAfRecordThread>& thread)
{
thread->exit();
AudioStreamIn *in = thread->clearInput();
@@ -3516,19 +3337,19 @@
delete in;
}
-void AudioFlinger::closeThreadInternal_l(const sp<RecordThread>& thread)
+void AudioFlinger::closeThreadInternal_l(const sp<IAfRecordThread>& thread)
{
- mRecordThreads.removeItem(thread->mId);
+ mRecordThreads.removeItem(thread->id());
closeInputFinish(thread);
}
status_t AudioFlinger::invalidateTracks(const std::vector<audio_port_handle_t> &portIds) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGV("%s", __func__);
std::set<audio_port_handle_t> portIdSet(portIds.begin(), portIds.end());
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ IAfPlaybackThread* const thread = mPlaybackThreads.valueAt(i).get();
thread->invalidateTracks(portIdSet);
if (portIdSet.empty()) {
return NO_ERROR;
@@ -3558,7 +3379,7 @@
void AudioFlinger::acquireAudioSessionId(
audio_session_t audioSession, pid_t pid, uid_t uid)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
pid_t caller = IPCThreadState::self()->getCallingPid();
ALOGV("acquiring %d from %d, for %d", audioSession, caller, pid);
const uid_t callerUid = IPCThreadState::self()->getCallingUid();
@@ -3570,7 +3391,7 @@
}
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
// Ignore requests received from processes not known as notification client. The request
// is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
// called from a different pid leaving a stale session reference. Also we don't know how
@@ -3596,9 +3417,9 @@
void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
{
- std::vector< sp<EffectModule> > removedEffects;
+ std::vector<sp<IAfEffectModule>> removedEffects;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
pid_t caller = IPCThreadState::self()->getCallingPid();
ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
const uid_t callerUid = IPCThreadState::self()->getCallingUid();
@@ -3614,7 +3435,7 @@
if (ref->mCnt == 0) {
mAudioSessionRefs.removeAt(i);
delete ref;
- std::vector< sp<EffectModule> > effects = purgeStaleEffects_l();
+ std::vector<sp<IAfEffectModule>> effects = purgeStaleEffects_l();
removedEffects.insert(removedEffects.end(), effects.begin(), effects.end());
}
goto Exit;
@@ -3644,18 +3465,19 @@
return false;
}
-std::vector<sp<AudioFlinger::EffectModule>> AudioFlinger::purgeStaleEffects_l() {
+std::vector<sp<IAfEffectModule>> AudioFlinger::purgeStaleEffects_l() {
ALOGV("purging stale effects");
- Vector< sp<EffectChain> > chains;
- std::vector< sp<EffectModule> > removedEffects;
+ Vector<sp<IAfEffectChain>> chains;
+ std::vector< sp<IAfEffectModule> > removedEffects;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
- Mutex::Autolock _l(t->mLock);
- for (size_t j = 0; j < t->mEffectChains.size(); j++) {
- sp<EffectChain> ec = t->mEffectChains[j];
+ sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
+ audio_utils::lock_guard _l(t->mutex());
+ const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
+ for (size_t j = 0; j < threadChains.size(); j++) {
+ sp<IAfEffectChain> ec = threadChains[j];
if (!audio_is_global_session(ec->sessionId())) {
chains.push(ec);
}
@@ -3663,28 +3485,30 @@
}
for (size_t i = 0; i < mRecordThreads.size(); i++) {
- sp<RecordThread> t = mRecordThreads.valueAt(i);
- Mutex::Autolock _l(t->mLock);
- for (size_t j = 0; j < t->mEffectChains.size(); j++) {
- sp<EffectChain> ec = t->mEffectChains[j];
+ sp<IAfRecordThread> t = mRecordThreads.valueAt(i);
+ audio_utils::lock_guard _l(t->mutex());
+ const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
+ for (size_t j = 0; j < threadChains.size(); j++) {
+ sp<IAfEffectChain> ec = threadChains[j];
chains.push(ec);
}
}
for (size_t i = 0; i < mMmapThreads.size(); i++) {
- sp<MmapThread> t = mMmapThreads.valueAt(i);
- Mutex::Autolock _l(t->mLock);
- for (size_t j = 0; j < t->mEffectChains.size(); j++) {
- sp<EffectChain> ec = t->mEffectChains[j];
+ const sp<IAfMmapThread> t = mMmapThreads.valueAt(i);
+ audio_utils::lock_guard _l(t->mutex());
+ const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
+ for (size_t j = 0; j < threadChains.size(); j++) {
+ sp<IAfEffectChain> ec = threadChains[j];
chains.push(ec);
}
}
for (size_t i = 0; i < chains.size(); i++) {
// clang-tidy suggests const ref
- sp<EffectChain> ec = chains[i]; // NOLINT(performance-unnecessary-copy-initialization)
+ sp<IAfEffectChain> ec = chains[i]; // NOLINT(performance-unnecessary-copy-initialization)
int sessionid = ec->sessionId();
- sp<ThreadBase> t = ec->thread().promote();
+ const auto t = ec->thread().promote();
if (t == 0) {
continue;
}
@@ -3700,10 +3524,10 @@
}
}
if (!found) {
- Mutex::Autolock _l(t->mLock);
+ audio_utils::lock_guard _l(t->mutex());
// remove all effects from the chain
- while (ec->mEffects.size()) {
- sp<EffectModule> effect = ec->mEffects[0];
+ while (ec->numberOfEffects()) {
+ sp<IAfEffectModule> effect = ec->getEffectModule(0);
effect->unPin();
t->removeEffect_l(effect, /*release*/ true);
if (effect->purgeHandles()) {
@@ -3716,8 +3540,8 @@
return removedEffects;
}
-// dumpToThreadLog_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::dumpToThreadLog_l(const sp<ThreadBase> &thread)
+// dumpToThreadLog_l() must be called with AudioFlinger::mutex() held
+void AudioFlinger::dumpToThreadLog_l(const sp<IAfThreadBase> &thread)
{
constexpr int THREAD_DUMP_TIMEOUT_MS = 2;
audio_utils::FdToString fdToString("- ", THREAD_DUMP_TIMEOUT_MS);
@@ -3728,10 +3552,10 @@
}
}
-// checkThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::ThreadBase *AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
+// checkThread_l() must be called with AudioFlinger::mutex() held
+IAfThreadBase* AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
{
- ThreadBase *thread = checkMmapThread_l(ioHandle);
+ IAfThreadBase* thread = checkMmapThread_l(ioHandle);
if (thread == 0) {
switch (audio_unique_id_get_use(ioHandle)) {
case AUDIO_UNIQUE_ID_USE_OUTPUT:
@@ -3747,56 +3571,56 @@
return thread;
}
-// checkOutputThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::ThreadBase> AudioFlinger::checkOutputThread_l(audio_io_handle_t ioHandle) const
+// checkOutputThread_l() must be called with AudioFlinger::mutex() held
+sp<IAfThreadBase> AudioFlinger::checkOutputThread_l(audio_io_handle_t ioHandle) const
{
if (audio_unique_id_get_use(ioHandle) != AUDIO_UNIQUE_ID_USE_OUTPUT) {
return nullptr;
}
- sp<AudioFlinger::ThreadBase> thread = mPlaybackThreads.valueFor(ioHandle);
+ sp<IAfThreadBase> thread = mPlaybackThreads.valueFor(ioHandle);
if (thread == nullptr) {
thread = mMmapThreads.valueFor(ioHandle);
}
return thread;
}
-// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
+// checkPlaybackThread_l() must be called with AudioFlinger::mutex() held
+IAfPlaybackThread* AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
{
return mPlaybackThreads.valueFor(output).get();
}
-// checkMixerThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
+// checkMixerThread_l() must be called with AudioFlinger::mutex() held
+IAfPlaybackThread* AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
{
- PlaybackThread *thread = checkPlaybackThread_l(output);
- return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
+ IAfPlaybackThread * const thread = checkPlaybackThread_l(output);
+ return thread != nullptr && thread->type() != IAfThreadBase::DIRECT ? thread : nullptr;
}
-// checkRecordThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
+// checkRecordThread_l() must be called with AudioFlinger::mutex() held
+IAfRecordThread* AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
{
return mRecordThreads.valueFor(input).get();
}
-// checkMmapThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::MmapThread *AudioFlinger::checkMmapThread_l(audio_io_handle_t io) const
+// checkMmapThread_l() must be called with AudioFlinger::mutex() held
+IAfMmapThread* AudioFlinger::checkMmapThread_l(audio_io_handle_t io) const
{
return mMmapThreads.valueFor(io).get();
}
-// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::VolumeInterface *AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
+// checkPlaybackThread_l() must be called with AudioFlinger::mutex() held
+sp<VolumeInterface> AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
{
- VolumeInterface *volumeInterface = mPlaybackThreads.valueFor(output).get();
+ sp<VolumeInterface> volumeInterface = mPlaybackThreads.valueFor(output).get();
if (volumeInterface == nullptr) {
- MmapThread *mmapThread = mMmapThreads.valueFor(output).get();
+ IAfMmapThread* const mmapThread = mMmapThreads.valueFor(output).get();
if (mmapThread != nullptr) {
if (mmapThread->isOutput()) {
- MmapPlaybackThread *mmapPlaybackThread =
- static_cast<MmapPlaybackThread *>(mmapThread);
+ IAfMmapPlaybackThread* const mmapPlaybackThread =
+ mmapThread->asIAfMmapPlaybackThread().get();
volumeInterface = mmapPlaybackThread;
}
}
@@ -3804,17 +3628,17 @@
return volumeInterface;
}
-Vector <AudioFlinger::VolumeInterface *> AudioFlinger::getAllVolumeInterfaces_l() const
+std::vector<sp<VolumeInterface>> AudioFlinger::getAllVolumeInterfaces_l() const
{
- Vector <VolumeInterface *> volumeInterfaces;
+ std::vector<sp<VolumeInterface>> volumeInterfaces;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- volumeInterfaces.add(mPlaybackThreads.valueAt(i).get());
+ volumeInterfaces.push_back(mPlaybackThreads.valueAt(i).get());
}
for (size_t i = 0; i < mMmapThreads.size(); i++) {
if (mMmapThreads.valueAt(i)->isOutput()) {
- MmapPlaybackThread *mmapPlaybackThread =
- static_cast<MmapPlaybackThread *>(mMmapThreads.valueAt(i).get());
- volumeInterfaces.add(mmapPlaybackThread);
+ IAfMmapPlaybackThread* const mmapPlaybackThread =
+ mMmapThreads.valueAt(i)->asIAfMmapPlaybackThread().get();
+ volumeInterfaces.push_back(mmapPlaybackThread);
}
}
return volumeInterfaces;
@@ -3841,14 +3665,14 @@
// TODO Use a floor after wraparound. This may need a mutex.
}
-AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
+IAfPlaybackThread* AudioFlinger::primaryPlaybackThread_l() const
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return nullptr;
}
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ IAfPlaybackThread* const thread = mPlaybackThreads.valueAt(i).get();
if(thread->isDuplicating()) {
continue;
}
@@ -3862,7 +3686,7 @@
DeviceTypeSet AudioFlinger::primaryOutputDevice_l() const
{
- PlaybackThread *thread = primaryPlaybackThread_l();
+ IAfPlaybackThread* const thread = primaryPlaybackThread_l();
if (thread == NULL) {
return {};
@@ -3871,12 +3695,12 @@
return thread->outDeviceTypes();
}
-AudioFlinger::PlaybackThread *AudioFlinger::fastPlaybackThread_l() const
+IAfPlaybackThread* AudioFlinger::fastPlaybackThread_l() const
{
size_t minFrameCount = 0;
- PlaybackThread *minThread = NULL;
+ IAfPlaybackThread* minThread = nullptr;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ IAfPlaybackThread* const thread = mPlaybackThreads.valueAt(i).get();
if (!thread->isDuplicating()) {
size_t frameCount = thread->frameCountHAL();
if (frameCount != 0 && (minFrameCount == 0 || frameCount < minFrameCount ||
@@ -3890,9 +3714,9 @@
return minThread;
}
-AudioFlinger::ThreadBase *AudioFlinger::hapticPlaybackThread_l() const {
+IAfThreadBase* AudioFlinger::hapticPlaybackThread_l() const {
for (size_t i = 0; i < mPlaybackThreads.size(); ++i) {
- PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ IAfPlaybackThread* const thread = mPlaybackThreads.valueAt(i).get();
if (thread->hapticChannelMask() != AUDIO_CHANNEL_NONE) {
return thread;
}
@@ -3901,12 +3725,12 @@
}
void AudioFlinger::updateSecondaryOutputsForTrack_l(
- PlaybackThread::Track* track,
- PlaybackThread* thread,
+ IAfTrack* track,
+ IAfPlaybackThread* thread,
const std::vector<audio_io_handle_t> &secondaryOutputs) const {
TeePatches teePatches;
for (audio_io_handle_t secondaryOutput : secondaryOutputs) {
- PlaybackThread *secondaryThread = checkPlaybackThread_l(secondaryOutput);
+ IAfPlaybackThread* const secondaryThread = checkPlaybackThread_l(secondaryOutput);
if (secondaryThread == nullptr) {
ALOGE("no playback thread found for secondary output %d", thread->id());
continue;
@@ -3932,10 +3756,10 @@
// The frameCount should also not be smaller than the secondary thread min frame
// count
size_t minFrameCount = AudioSystem::calculateMinFrameCount(
- [&] { Mutex::Autolock _l(secondaryThread->mLock);
+ [&] { audio_utils::lock_guard _l(secondaryThread->mutex());
return secondaryThread->latency_l(); }(),
- secondaryThread->mNormalFrameCount,
- secondaryThread->mSampleRate,
+ secondaryThread->frameCount(), // normal frame count
+ secondaryThread->sampleRate(),
track->sampleRate(),
track->getSpeed());
frameCount = std::max(frameCount, minFrameCount);
@@ -3948,7 +3772,7 @@
// use an index mask here to create the PatchRecord.
inChannelMask = audio_channel_mask_out_to_in_index_mask(track->channelMask());
}
- sp patchRecord = new RecordThread::PatchRecord(nullptr /* thread */,
+ sp<IAfPatchRecord> patchRecord = IAfPatchRecord::create(nullptr /* thread */,
track->sampleRate(),
inChannelMask,
track->format(),
@@ -3968,7 +3792,7 @@
// for now, we exclude fast tracks by removing the Fast flag.
const audio_output_flags_t outputFlags =
(audio_output_flags_t)(track->getOutputFlags() & ~AUDIO_OUTPUT_FLAG_FAST);
- sp patchTrack = new PlaybackThread::PatchTrack(secondaryThread,
+ sp<IAfPatchTrack> patchTrack = IAfPatchTrack::create(secondaryThread,
track->streamType(),
track->sampleRate(),
track->channelMask(),
@@ -3998,9 +3822,9 @@
audio_session_t triggerSession,
audio_session_t listenerSession,
const audioflinger::SyncEventCallback& callBack,
- const wp<RefBase>& cookie)
+ const wp<IAfTrackBase>& cookie)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
auto event = sp<audioflinger::SyncEvent>::make(
type, triggerSession, listenerSession, callBack, cookie);
@@ -4037,7 +3861,7 @@
status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mEffectsFactoryHal.get()) {
return mEffectsFactoryHal->queryNumberEffects(numEffects);
} else {
@@ -4047,7 +3871,7 @@
status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mEffectsFactoryHal.get()) {
return mEffectsFactoryHal->getDescriptor(index, descriptor);
} else {
@@ -4064,7 +3888,7 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!mEffectsFactoryHal.get()) {
return -ENODEV;
@@ -4140,7 +3964,7 @@
aidl2legacy_EffectDescriptor_effect_descriptor_t(request.desc));
const bool probe = request.probe;
- sp<EffectHandle> handle;
+ sp<IAfEffectHandle> handle;
effect_descriptor_t descOut;
int enabledOut = 0;
int idOut = -1;
@@ -4159,7 +3983,7 @@
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
currentPid = callingPid;
}
- adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(adjAttributionSource);
+ adjAttributionSource = afutils::checkAttributionSourcePackage(adjAttributionSource);
ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
adjAttributionSource.pid, effectClient.get(), priority, sessionId, io,
@@ -4184,7 +4008,11 @@
lStatus = BAD_VALUE;
goto Exit;
}
- PlaybackThread *thread = checkPlaybackThread_l(io);
+ IAfPlaybackThread* thread;
+ {
+ audio_utils::lock_guard l(mutex());
+ thread = checkPlaybackThread_l(io);
+ }
if (thread == nullptr) {
ALOGE("%s: invalid output %d specified for AUDIO_SESSION_OUTPUT_STAGE", __func__, io);
lStatus = BAD_VALUE;
@@ -4248,7 +4076,7 @@
goto Exit;
}
- const bool hapticPlaybackRequired = EffectModule::isHapticGenerator(&descOut.type);
+ const bool hapticPlaybackRequired = IAfEffectModule::isHapticGenerator(&descOut.type);
if (hapticPlaybackRequired
&& (sessionId == AUDIO_SESSION_DEVICE
|| sessionId == AUDIO_SESSION_OUTPUT_MIX
@@ -4275,17 +4103,17 @@
ALOGV("createEffect got output %d", io);
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (sessionId == AUDIO_SESSION_DEVICE) {
sp<Client> client = registerPid(currentPid);
ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress());
handle = mDeviceEffectManager->createEffect_l(
- &descOut, device, client, effectClient, mPatchPanel.patches_l(),
+ &descOut, device, client, effectClient, mPatchPanel->patches_l(),
&enabledOut, &lStatus, probe, request.notifyFramesProcessed);
if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- // remove local strong reference to Client with mClientLock held
- Mutex::Autolock _cl(mClientLock);
+ // remove local strong reference to Client with clientMutex() held
+ audio_utils::lock_guard _cl(clientMutex());
client.clear();
} else {
// handle must be valid here, but check again to be safe.
@@ -4353,7 +4181,7 @@
}
const uint32_t sessionType =
mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId);
- if ((sessionType & ThreadBase::EFFECT_SESSION) != 0) {
+ if ((sessionType & IAfThreadBase::EFFECT_SESSION) != 0) {
ALOGE("%s: effect %s io %d denied because session %d effect exists on io %d",
__func__, descOut.name, (int) io, (int) sessionId, (int) checkIo);
android_errorWriteLog(0x534e4554, "123237974");
@@ -4362,7 +4190,7 @@
}
}
}
- ThreadBase *thread = checkRecordThread_l(io);
+ IAfThreadBase* thread = checkRecordThread_l(io);
if (thread == NULL) {
thread = checkPlaybackThread_l(io);
if (thread == NULL) {
@@ -4376,9 +4204,9 @@
} else {
// Check if one effect chain was awaiting for an effect to be created on this
// session and used it instead of creating a new one.
- sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l2(thread->mLock);
+ audio_utils::lock_guard _l2(thread->mutex());
thread->addEffectChain_l(chain);
}
}
@@ -4387,9 +4215,9 @@
// create effect on selected output thread
bool pinned = !audio_is_global_session(sessionId) && isSessionAcquired_l(sessionId);
- ThreadBase *oriThread = nullptr;
+ IAfThreadBase* oriThread = nullptr;
if (hapticPlaybackRequired && thread->hapticChannelMask() == AUDIO_CHANNEL_NONE) {
- ThreadBase *hapticThread = hapticPlaybackThread_l();
+ IAfThreadBase* const hapticThread = hapticPlaybackThread_l();
if (hapticThread == nullptr) {
ALOGE("%s haptic thread not found while it is required", __func__);
lStatus = INVALID_OPERATION;
@@ -4405,8 +4233,8 @@
&descOut, &enabledOut, &lStatus, pinned, probe,
request.notifyFramesProcessed);
if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- // remove local strong reference to Client with mClientLock held
- Mutex::Autolock _cl(mClientLock);
+ // remove local strong reference to Client with clientMutex() held
+ audio_utils::lock_guard _cl(clientMutex());
client.clear();
} else {
// handle must be valid here, but check again to be safe.
@@ -4428,7 +4256,7 @@
response->alreadyExists = false;
}
// Check CPU and memory usage
- sp<EffectBase> effect = handle->effect().promote();
+ sp<IAfEffectBase> effect = handle->effect().promote();
if (effect != nullptr) {
status_t rStatus = effect->updatePolicyState();
if (rStatus != NO_ERROR) {
@@ -4441,7 +4269,7 @@
response->id = idOut;
response->enabled = enabledOut != 0;
- response->effect = handle;
+ response->effect = handle->asIEffect();
response->desc = VALUE_OR_RETURN_STATUS(
legacy2aidl_effect_descriptor_t_EffectDescriptor(descOut));
@@ -4452,27 +4280,26 @@
status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput)
{
- ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
- sessionId, srcOutput, dstOutput);
- Mutex::Autolock _l(mLock);
+ ALOGV("%s() session %d, srcOutput %d, dstOutput %d",
+ __func__, sessionId, srcOutput, dstOutput);
+ audio_utils::lock_guard _l(mutex());
if (srcOutput == dstOutput) {
- ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
+ ALOGW("%s() same dst and src outputs %d", __func__, dstOutput);
return NO_ERROR;
}
- PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
- if (srcThread == NULL) {
- ALOGW("moveEffects() bad srcOutput %d", srcOutput);
+ IAfPlaybackThread* const srcThread = checkPlaybackThread_l(srcOutput);
+ if (srcThread == nullptr) {
+ ALOGW("%s() bad srcOutput %d", __func__, srcOutput);
return BAD_VALUE;
}
- PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
- if (dstThread == NULL) {
- ALOGW("moveEffects() bad dstOutput %d", dstOutput);
+ IAfPlaybackThread* const dstThread = checkPlaybackThread_l(dstOutput);
+ if (dstThread == nullptr) {
+ ALOGW("%s() bad dstOutput %d", __func__, dstOutput);
return BAD_VALUE;
}
- Mutex::Autolock _dl(dstThread->mLock);
- Mutex::Autolock _sl(srcThread->mLock);
- return moveEffectChain_l(sessionId, srcThread, dstThread);
+ audio_utils::scoped_lock _ll(dstThread->mutex(), srcThread->mutex());
+ return moveEffectChain_ll(sessionId, srcThread, dstThread);
}
@@ -4480,39 +4307,38 @@
audio_session_t sessionId,
bool suspended)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
- sp<ThreadBase> thread = getEffectThread_l(sessionId, effectId);
+ sp<IAfThreadBase> thread = getEffectThread_l(sessionId, effectId);
if (thread == nullptr) {
return;
}
- Mutex::Autolock _sl(thread->mLock);
- sp<EffectModule> effect = thread->getEffect_l(sessionId, effectId);
+ audio_utils::lock_guard _sl(thread->mutex());
+ sp<IAfEffectModule> effect = thread->getEffect_l(sessionId, effectId);
thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
}
-// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
-status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
- AudioFlinger::PlaybackThread *srcThread,
- AudioFlinger::PlaybackThread *dstThread)
-NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
+// moveEffectChain_ll must be called with the AudioFlinger::mutex()
+// and both srcThread and dstThread mutex()s held
+status_t AudioFlinger::moveEffectChain_ll(audio_session_t sessionId,
+ IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
{
- ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
- sessionId, srcThread, dstThread);
+ ALOGV("%s: session %d from thread %p to thread %p",
+ __func__, sessionId, srcThread, dstThread);
- sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = srcThread->getEffectChain_l(sessionId);
if (chain == 0) {
- ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
- sessionId, srcThread);
+ ALOGW("%s: effect chain for session %d not on source thread %p",
+ __func__, sessionId, srcThread);
return INVALID_OPERATION;
}
// Check whether the destination thread and all effects in the chain are compatible
if (!chain->isCompatibleWithThread_l(dstThread)) {
- ALOGW("moveEffectChain_l() effect chain failed because"
+ ALOGW("%s: effect chain failed because"
" destination thread %p is not compatible with effects in the chain",
- dstThread);
+ __func__, dstThread);
return INVALID_OPERATION;
}
@@ -4525,16 +4351,16 @@
// transfer all effects one by one so that new effect chain is created on new thread with
// correct buffer sizes and audio parameters and effect engines reconfigured accordingly
- sp<EffectChain> dstChain;
- Vector< sp<EffectModule> > removed;
+ sp<IAfEffectChain> dstChain;
+ Vector<sp<IAfEffectModule>> removed;
status_t status = NO_ERROR;
std::string errorString;
// process effects one by one.
- for (sp<EffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
+ for (sp<IAfEffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
effect = chain->getEffectFromId_l(0)) {
srcThread->removeEffect_l(effect);
removed.add(effect);
- status = dstThread->addEffect_l(effect);
+ status = dstThread->addEffect_ll(effect);
if (status != NO_ERROR) {
errorString = StringPrintf(
"cannot add effect %p to destination thread", effect.get());
@@ -4560,7 +4386,7 @@
for (const auto& effect : removed) {
dstThread->removeEffect_l(effect); // Note: Depending on error location, the last
// effect may not have been placed on dstThread.
- if (srcThread->addEffect_l(effect) == NO_ERROR) {
+ if (srcThread->addEffect_ll(effect) == NO_ERROR) {
++restored;
if (dstChain == nullptr) {
dstChain = effect->getCallback()->chain().promote();
@@ -4576,15 +4402,15 @@
// If we do not take the dstChain lock, it is possible that processing is ongoing
// while we are starting the effect. This can cause glitches with volume,
// see b/202360137.
- dstChain->lock();
+ dstChain->mutex().lock();
for (const auto& effect : removed) {
- if (effect->state() == EffectModule::ACTIVE ||
- effect->state() == EffectModule::STOPPING) {
+ if (effect->state() == IAfEffectModule::ACTIVE ||
+ effect->state() == IAfEffectModule::STOPPING) {
++started;
effect->start();
}
}
- dstChain->unlock();
+ dstChain->mutex().unlock();
}
if (status != NO_ERROR) {
@@ -4605,45 +4431,43 @@
}
status_t AudioFlinger::moveAuxEffectToIo(int EffectId,
- const sp<PlaybackThread>& dstThread,
- sp<PlaybackThread> *srcThread)
+ const sp<IAfPlaybackThread>& dstThread, sp<IAfPlaybackThread>* srcThread)
{
status_t status = NO_ERROR;
- Mutex::Autolock _l(mLock);
- sp<PlaybackThread> thread =
- static_cast<PlaybackThread *>(getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId).get());
+ audio_utils::lock_guard _l(mutex());
+ const sp<IAfThreadBase> threadBase = getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
+ const sp<IAfPlaybackThread> thread = threadBase ? threadBase->asIAfPlaybackThread() : nullptr;
if (EffectId != 0 && thread != 0 && dstThread != thread.get()) {
- Mutex::Autolock _dl(dstThread->mLock);
- Mutex::Autolock _sl(thread->mLock);
- sp<EffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
- sp<EffectChain> dstChain;
+ audio_utils::scoped_lock _ll(dstThread->mutex(), thread->mutex());
+ sp<IAfEffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+ sp<IAfEffectChain> dstChain;
if (srcChain == 0) {
return INVALID_OPERATION;
}
- sp<EffectModule> effect = srcChain->getEffectFromId_l(EffectId);
+ sp<IAfEffectModule> effect = srcChain->getEffectFromId_l(EffectId);
if (effect == 0) {
return INVALID_OPERATION;
}
thread->removeEffect_l(effect);
- status = dstThread->addEffect_l(effect);
+ status = dstThread->addEffect_ll(effect);
if (status != NO_ERROR) {
- thread->addEffect_l(effect);
+ thread->addEffect_ll(effect);
status = INVALID_OPERATION;
goto Exit;
}
dstChain = effect->getCallback()->chain().promote();
if (dstChain == 0) {
- thread->addEffect_l(effect);
+ thread->addEffect_ll(effect);
status = INVALID_OPERATION;
}
Exit:
// removeEffect_l() has stopped the effect if it was active so it must be restarted
- if (effect->state() == EffectModule::ACTIVE ||
- effect->state() == EffectModule::STOPPING) {
+ if (effect->state() == IAfEffectModule::ACTIVE ||
+ effect->state() == IAfEffectModule::STOPPING) {
effect->start();
}
}
@@ -4654,8 +4478,7 @@
return status;
}
-bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
-NO_THREAD_SAFETY_ANALYSIS // thread lock for getEffectChain_l.
+bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l() const
{
if (mGlobalEffectEnableTime != 0 &&
((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
@@ -4663,7 +4486,7 @@
}
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- sp<EffectChain> ec =
+ sp<IAfEffectChain> ec =
mPlaybackThreads.valueAt(i)->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
if (ec != 0 && ec->isNonOffloadableEnabled()) {
return true;
@@ -4674,20 +4497,20 @@
void AudioFlinger::onNonOffloadableGlobalEffectEnable()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mGlobalEffectEnableTime = systemTime();
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
- if (t->mType == ThreadBase::OFFLOAD) {
+ const sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
+ if (t->type() == IAfThreadBase::OFFLOAD) {
t->invalidateTracks(AUDIO_STREAM_MUSIC);
}
}
}
-status_t AudioFlinger::putOrphanEffectChain_l(const sp<AudioFlinger::EffectChain>& chain)
+status_t AudioFlinger::putOrphanEffectChain_l(const sp<IAfEffectChain>& chain)
{
// clear possible suspended state before parking the chain so that it starts in default state
// when attached to a new record thread
@@ -4705,9 +4528,9 @@
return NO_ERROR;
}
-sp<AudioFlinger::EffectChain> AudioFlinger::getOrphanEffectChain_l(audio_session_t session)
+sp<IAfEffectChain> AudioFlinger::getOrphanEffectChain_l(audio_session_t session)
{
- sp<EffectChain> chain;
+ sp<IAfEffectChain> chain;
ssize_t index = mOrphanEffectChains.indexOfKey(session);
ALOGV("getOrphanEffectChain_l session %d index %zd", session, index);
if (index >= 0) {
@@ -4717,14 +4540,14 @@
return chain;
}
-bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule>& effect)
+bool AudioFlinger::updateOrphanEffectChains(const sp<IAfEffectModule>& effect)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
audio_session_t session = effect->sessionId();
ssize_t index = mOrphanEffectChains.indexOfKey(session);
ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
if (index >= 0) {
- sp<EffectChain> chain = mOrphanEffectChains.valueAt(index);
+ sp<IAfEffectChain> chain = mOrphanEffectChains.valueAt(index);
if (chain->removeEffect_l(effect, true) == 0) {
ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
mOrphanEffectChains.removeItemsAt(index);
@@ -4734,6 +4557,55 @@
return false;
}
+// ----------------------------------------------------------------------------
+// from PatchPanel
+
+/* List connected audio ports and their attributes */
+status_t AudioFlinger::listAudioPorts(unsigned int* num_ports,
+ struct audio_port* ports) const
+{
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->listAudioPorts_l(num_ports, ports);
+}
+
+/* Get supported attributes for a given audio port */
+status_t AudioFlinger::getAudioPort(struct audio_port_v7* port) const {
+ const status_t status = AudioValidator::validateAudioPort(*port);
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->getAudioPort_l(port);
+}
+
+/* Connect a patch between several source and sink ports */
+status_t AudioFlinger::createAudioPatch(
+ const struct audio_patch* patch, audio_patch_handle_t* handle)
+{
+ const status_t status = AudioValidator::validateAudioPatch(*patch);
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->createAudioPatch_l(patch, handle);
+}
+
+/* Disconnect a patch */
+status_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle)
+{
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->releaseAudioPatch_l(handle);
+}
+
+/* List connected audio ports and they attributes */
+status_t AudioFlinger::listAudioPatches(
+ unsigned int* num_patches, struct audio_patch* patches) const
+{
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->listAudioPatches_l(num_patches, patches);
+}
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 8b1d70b..2c34144 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -15,325 +15,395 @@
** limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FLINGER_H
-#define ANDROID_AUDIO_FLINGER_H
+#pragma once
-#include "Configuration.h"
+// Classes and interfaces directly used.
+#include "Client.h"
+#include "DeviceEffectManager.h"
+#include "EffectConfiguration.h"
+#include "IAfEffect.h"
+#include "IAfPatchPanel.h"
+#include "IAfThread.h"
+#include "IAfTrack.h"
+#include "MelReporter.h"
+#include "PatchCommandThread.h"
+
+// External classes
+#include <audio_utils/mutex.h>
+#include <audio_utils/FdToString.h>
+#include <audio_utils/SimpleLog.h>
+#include <media/IAudioFlinger.h>
+#include <media/MediaMetricsItem.h>
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <mediautils/ServiceUtilities.h>
+#include <mediautils/Synchronization.h>
+
+// not needed with the includes above, added to prevent transitive include dependency.
+#include <utils/KeyedVector.h>
+#include <utils/String16.h>
#include <atomic>
-#include <mutex>
-#include <chrono>
-#include <deque>
+#include <functional>
#include <map>
-#include <numeric>
#include <optional>
#include <set>
-#include <string>
-#include <vector>
-#include <stdint.h>
-#include <sys/types.h>
-#include <limits.h>
-
-#include <android/media/BnAudioTrack.h>
-#include <android/media/IAudioFlingerClient.h>
-#include <android/media/IAudioTrackCallback.h>
-#include <android/os/BnExternalVibrationController.h>
-#include <android/content/AttributionSourceState.h>
-
-
-#include <android-base/macros.h>
-#include <cutils/atomic.h>
-#include <cutils/compiler.h>
-
-#include <cutils/properties.h>
-#include <media/IAudioFlinger.h>
-#include <media/AudioSystem.h>
-#include <media/AudioTrack.h>
-#include <media/MmapStreamInterface.h>
-#include <media/MmapStreamCallback.h>
-
-#include <utils/Errors.h>
-#include <utils/threads.h>
-#include <utils/SortedVector.h>
-#include <utils/TypeHelpers.h>
-#include <utils/Vector.h>
-
-#include <binder/AppOpsManager.h>
-#include <binder/BinderService.h>
-#include <binder/IAppOpsCallback.h>
-#include <binder/MemoryDealer.h>
-
-#include <system/audio.h>
-#include <system/audio_policy.h>
-
-#include <media/audiohal/EffectBufferHalInterface.h>
-#include <media/audiohal/StreamHalInterface.h>
-#include <media/AudioBufferProvider.h>
-#include <media/AudioContainers.h>
-#include <media/AudioDeviceTypeAddr.h>
-#include <media/AudioMixer.h>
-#include <media/DeviceDescriptorBase.h>
-#include <media/ExtendedAudioBufferProvider.h>
-#include <media/VolumeShaper.h>
-#include <mediautils/ServiceUtilities.h>
-#include <mediautils/SharedMemoryAllocator.h>
-#include <mediautils/Synchronization.h>
-#include <mediautils/ThreadSnapshot.h>
-
-#include <afutils/AllocatorFactory.h>
-#include <afutils/AudioWatchdog.h>
-#include <afutils/NBAIO_Tee.h>
-
-#include <audio_utils/clock.h>
-#include <audio_utils/FdToString.h>
-#include <audio_utils/LinearMap.h>
-#include <audio_utils/MelAggregator.h>
-#include <audio_utils/MelProcessor.h>
-#include <audio_utils/SimpleLog.h>
-#include <audio_utils/TimestampVerifier.h>
-
-#include <sounddose/SoundDoseManager.h>
-#include <timing/MonotonicFrameCounter.h>
-#include <timing/SyncEvent.h>
-#include <timing/SynchronizedRecordState.h>
-
-#include <datapath/AudioHwDevice.h>
-#include <datapath/AudioStreamOut.h>
-#include <datapath/SpdifStreamOut.h>
-#include <datapath/ThreadMetrics.h>
-#include <datapath/TrackMetrics.h>
-#include <fastpath/FastCapture.h>
-#include <fastpath/FastMixer.h>
-#include <media/nbaio/NBAIO.h>
-
-#include <android/os/IPowerManager.h>
-
-#include <media/nblog/NBLog.h>
-#include <private/media/AudioEffectShared.h>
-#include <private/media/AudioTrackShared.h>
-
-#include <vibrator/ExternalVibration.h>
-#include <vibrator/ExternalVibrationUtils.h>
-
-#include "android/media/BnAudioRecord.h"
-#include "android/media/BnEffect.h"
namespace android {
-class AudioMixer;
-class AudioBuffer;
-class AudioResampler;
-class DeviceHalInterface;
-class DevicesFactoryHalCallback;
-class DevicesFactoryHalInterface;
-class EffectsFactoryHalInterface;
-class FastMixer;
-class IAudioManager;
-class PassthruBufferProvider;
-class RecordBufferConverter;
-class ServerProxy;
-
-// ----------------------------------------------------------------------------
-
-static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
-
-#define INCLUDING_FROM_AUDIOFLINGER_H
-
-using android::content::AttributionSourceState;
-
-class AudioFlinger : public AudioFlingerServerAdapter::Delegate
+class AudioFlinger
+ : public AudioFlingerServerAdapter::Delegate // IAudioFlinger client interface
+ , public IAfClientCallback
+ , public IAfDeviceEffectManagerCallback
+ , public IAfMelReporterCallback
+ , public IAfPatchPanelCallback
+ , public IAfThreadCallback
{
friend class sp<AudioFlinger>;
public:
static void instantiate() ANDROID_API;
- static AttributionSourceState checkAttributionSourcePackage(
- const AttributionSourceState& attributionSource);
+private:
- status_t dump(int fd, const Vector<String16>& args) override;
+ // ---- begin IAudioFlinger interface
- // IAudioFlinger interface, in binder opcode order
+ status_t dump(int fd, const Vector<String16>& args) final EXCLUDES_AudioFlinger_Mutex;
+
status_t createTrack(const media::CreateTrackRequest& input,
- media::CreateTrackResponse& output) override;
+ media::CreateTrackResponse& output) final EXCLUDES_AudioFlinger_Mutex;
status_t createRecord(const media::CreateRecordRequest& input,
- media::CreateRecordResponse& output) override;
+ media::CreateRecordResponse& output) final EXCLUDES_AudioFlinger_Mutex;
- virtual uint32_t sampleRate(audio_io_handle_t ioHandle) const;
- virtual audio_format_t format(audio_io_handle_t output) const;
- virtual size_t frameCount(audio_io_handle_t ioHandle) const;
- virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const;
- virtual uint32_t latency(audio_io_handle_t output) const;
+ uint32_t sampleRate(audio_io_handle_t ioHandle) const final EXCLUDES_AudioFlinger_Mutex;
+ audio_format_t format(audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
+ size_t frameCount(audio_io_handle_t ioHandle) const final EXCLUDES_AudioFlinger_Mutex;
+ size_t frameCountHAL(audio_io_handle_t ioHandle) const final EXCLUDES_AudioFlinger_Mutex;
+ uint32_t latency(audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setMasterVolume(float value);
- virtual status_t setMasterMute(bool muted);
-
- virtual float masterVolume() const;
- virtual bool masterMute() const;
+ status_t setMasterVolume(float value) final EXCLUDES_AudioFlinger_Mutex;
+ status_t setMasterMute(bool muted) final EXCLUDES_AudioFlinger_Mutex;
+ float masterVolume() const final EXCLUDES_AudioFlinger_Mutex;
+ bool masterMute() const final EXCLUDES_AudioFlinger_Mutex;
// Balance value must be within -1.f (left only) to 1.f (right only) inclusive.
- status_t setMasterBalance(float balance) override;
- status_t getMasterBalance(float *balance) const override;
+ status_t setMasterBalance(float balance) final EXCLUDES_AudioFlinger_Mutex;
+ status_t getMasterBalance(float* balance) const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output);
- virtual status_t setStreamMute(audio_stream_type_t stream, bool muted);
+ status_t setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
+ status_t setStreamMute(audio_stream_type_t stream, bool muted) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual float streamVolume(audio_stream_type_t stream,
- audio_io_handle_t output) const;
- virtual bool streamMute(audio_stream_type_t stream) const;
+ float streamVolume(audio_stream_type_t stream,
+ audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
+ bool streamMute(audio_stream_type_t stream) const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setMode(audio_mode_t mode);
+ status_t setMode(audio_mode_t mode) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setMicMute(bool state);
- virtual bool getMicMute() const;
+ status_t setMicMute(bool state) final EXCLUDES_AudioFlinger_Mutex;
+ bool getMicMute() const final EXCLUDES_AudioFlinger_Mutex;
- virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced);
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
- virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const;
+ status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) final
+ EXCLUDES_AudioFlinger_Mutex;
+ String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual void registerClient(const sp<media::IAudioFlingerClient>& client);
+ void registerClient(const sp<media::IAudioFlingerClient>& client) final
+ EXCLUDES_AudioFlinger_Mutex;
+ size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+ audio_channel_mask_t channelMask) const final EXCLUDES_AudioFlinger_Mutex;
- virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
- audio_channel_mask_t channelMask) const;
+ status_t openOutput(const media::OpenOutputRequest& request,
+ media::OpenOutputResponse* response) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t openOutput(const media::OpenOutputRequest& request,
- media::OpenOutputResponse* response);
+ audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+ audio_io_handle_t output2) final EXCLUDES_AudioFlinger_Mutex;
- virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
- audio_io_handle_t output2);
+ status_t closeOutput(audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t closeOutput(audio_io_handle_t output);
+ status_t suspendOutput(audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t suspendOutput(audio_io_handle_t output);
+ status_t restoreOutput(audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t restoreOutput(audio_io_handle_t output);
+ status_t openInput(const media::OpenInputRequest& request,
+ media::OpenInputResponse* response) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t openInput(const media::OpenInputRequest& request,
- media::OpenInputResponse* response);
+ status_t closeInput(audio_io_handle_t input) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t closeInput(audio_io_handle_t input);
+ status_t setVoiceVolume(float volume) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setVoiceVolume(float volume);
+ status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
+ audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
- audio_io_handle_t output) const;
-
- virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const;
+ uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const final
+ EXCLUDES_AudioFlinger_Mutex;
// This is the binder API. For the internal API see nextUniqueId().
- virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
+ audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) final
+ EXCLUDES_AudioFlinger_Mutex;
- void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) override;
+ void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid);
+ void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t queryNumberEffects(uint32_t *numEffects) const;
+ status_t queryNumberEffects(uint32_t* numEffects) const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor) const;
+ status_t queryEffect(uint32_t index, effect_descriptor_t* descriptor) const final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t getEffectDescriptor(const effect_uuid_t *pUuid,
- const effect_uuid_t *pTypeUuid,
- uint32_t preferredTypeFlag,
- effect_descriptor_t *descriptor) const;
+ status_t getEffectDescriptor(const effect_uuid_t* pUuid,
+ const effect_uuid_t* pTypeUuid,
+ uint32_t preferredTypeFlag,
+ effect_descriptor_t* descriptor) const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t createEffect(const media::CreateEffectRequest& request,
- media::CreateEffectResponse* response);
+ status_t createEffect(const media::CreateEffectRequest& request,
+ media::CreateEffectResponse* response) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
- audio_io_handle_t dstOutput);
+ status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput) final EXCLUDES_AudioFlinger_Mutex;
- void setEffectSuspended(int effectId,
- audio_session_t sessionId,
- bool suspended) override;
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) final EXCLUDES_AudioFlinger_Mutex;
- virtual audio_module_handle_t loadHwModule(const char *name);
+ audio_module_handle_t loadHwModule(const char* name) final EXCLUDES_AudioFlinger_Mutex;
- virtual uint32_t getPrimaryOutputSamplingRate();
- virtual size_t getPrimaryOutputFrameCount();
+ uint32_t getPrimaryOutputSamplingRate() const final EXCLUDES_AudioFlinger_Mutex;
+ size_t getPrimaryOutputFrameCount() const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
-
- /* List available audio ports and their attributes */
- virtual status_t listAudioPorts(unsigned int *num_ports,
- struct audio_port *ports);
+ status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) final
+ EXCLUDES_AudioFlinger_Mutex;
/* Get attributes for a given audio port */
- virtual status_t getAudioPort(struct audio_port_v7 *port);
+ status_t getAudioPort(struct audio_port_v7* port) const final EXCLUDES_AudioFlinger_Mutex;
/* Create an audio patch between several source and sink ports */
- virtual status_t createAudioPatch(const struct audio_patch *patch,
- audio_patch_handle_t *handle);
+ status_t createAudioPatch(const struct audio_patch *patch,
+ audio_patch_handle_t* handle) final EXCLUDES_AudioFlinger_Mutex;
/* Release an audio patch */
- virtual status_t releaseAudioPatch(audio_patch_handle_t handle);
+ status_t releaseAudioPatch(audio_patch_handle_t handle) final EXCLUDES_AudioFlinger_Mutex;
/* List existing audio patches */
- virtual status_t listAudioPatches(unsigned int *num_patches,
- struct audio_patch *patches);
+ status_t listAudioPatches(unsigned int* num_patches,
+ struct audio_patch* patches) const final EXCLUDES_AudioFlinger_Mutex;
/* Set audio port configuration */
- virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+ status_t setAudioPortConfig(const struct audio_port_config* config) final
+ EXCLUDES_AudioFlinger_Mutex;
/* Get the HW synchronization source used for an audio session */
- virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId);
+ audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) final
+ EXCLUDES_AudioFlinger_Mutex;
/* Indicate JAVA services are ready (scheduling, power management ...) */
- virtual status_t systemReady();
- virtual status_t audioPolicyReady() { mAudioPolicyReady.store(true); return NO_ERROR; }
- bool isAudioPolicyReady() const { return mAudioPolicyReady.load(); }
+ status_t systemReady() final EXCLUDES_AudioFlinger_Mutex;
+ status_t audioPolicyReady() final { mAudioPolicyReady.store(true); return NO_ERROR; }
+ status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
+ status_t setAudioHalPids(const std::vector<pid_t>& pids) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
+ status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos);
+ status_t updateSecondaryOutputs(
+ const TrackSecondaryOutputsMap& trackSecondaryOutputs) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t updateSecondaryOutputs(
- const TrackSecondaryOutputsMap& trackSecondaryOutputs);
-
- virtual status_t getMmapPolicyInfos(
+ status_t getMmapPolicyInfos(
media::audio::common::AudioMMapPolicyType policyType,
- std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos);
+ std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual int32_t getAAudioMixerBurstCount();
+ int32_t getAAudioMixerBurstCount() const final EXCLUDES_AudioFlinger_Mutex;
- virtual int32_t getAAudioHardwareBurstMinUsec();
+ int32_t getAAudioHardwareBurstMinUsec() const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
- media::DeviceConnectedState state);
+ status_t setDeviceConnectedState(const struct audio_port_v7* port,
+ media::DeviceConnectedState state) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setSimulateDeviceConnections(bool enabled);
+ status_t setSimulateDeviceConnections(bool enabled) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setRequestedLatencyMode(
- audio_io_handle_t output, audio_latency_mode_t mode);
+ status_t setRequestedLatencyMode(
+ audio_io_handle_t output, audio_latency_mode_t mode) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
- std::vector<audio_latency_mode_t>* modes);
+ status_t getSupportedLatencyModes(audio_io_handle_t output,
+ std::vector<audio_latency_mode_t>* modes) const final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
+ status_t setBluetoothVariableLatencyEnabled(bool enabled) final EXCLUDES_AudioFlinger_Mutex;
- virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled);
+ status_t isBluetoothVariableLatencyEnabled(bool* enabled) const final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t supportsBluetoothVariableLatency(bool* support);
+ status_t supportsBluetoothVariableLatency(bool* support) const final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
- sp<media::ISoundDose>* soundDose);
+ status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose) const final EXCLUDES_AudioFlinger_Mutex;
- status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
+ status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) final
+ EXCLUDES_AudioFlinger_Mutex;
- virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* config);
+ status_t getAudioPolicyConfig(media::AudioPolicyConfig* config) final
+ EXCLUDES_AudioFlinger_Mutex;
status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
- const std::function<status_t()>& delegate) override;
+ const std::function<status_t()>& delegate) final EXCLUDES_AudioFlinger_Mutex;
- // end of IAudioFlinger interface
+ // ---- end of IAudioFlinger interface
- sp<NBLog::Writer> newWriter_l(size_t size, const char *name);
- void unregisterWriter(const sp<NBLog::Writer>& writer);
+ // ---- begin IAfClientCallback interface
+
+ audio_utils::mutex& clientMutex() const final
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_ClientMutex) {
+ return mClientMutex;
+ }
+ void removeClient_l(pid_t pid) REQUIRES(clientMutex()) final;
+ void removeNotificationClient(pid_t pid) final EXCLUDES_AudioFlinger_Mutex;
+ status_t moveAuxEffectToIo(
+ int effectId,
+ const sp<IAfPlaybackThread>& dstThread,
+ sp<IAfPlaybackThread>* srcThread) final EXCLUDES_AudioFlinger_Mutex;
+
+ // ---- end of IAfClientCallback interface
+
+ // ---- begin IAfDeviceEffectManagerCallback interface
+
+ // also used by IAfThreadCallback
+ bool isAudioPolicyReady() const final { return mAudioPolicyReady.load(); }
+ // below also used by IAfMelReporterCallback, IAfPatchPanelCallback
+ const sp<PatchCommandThread>& getPatchCommandThread() final { return mPatchCommandThread; }
+ status_t addEffectToHal(
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final
+ EXCLUDES_AudioFlinger_HardwareMutex;
+ status_t removeEffectFromHal(
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final
+ EXCLUDES_AudioFlinger_HardwareMutex;
+
+ // ---- end of IAfDeviceEffectManagerCallback interface
+
+ // ---- begin IAfMelReporterCallback interface
+
+ // below also used by IAfThreadCallback
+ audio_utils::mutex& mutex() const final
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex)
+ EXCLUDES_BELOW_AudioFlinger_Mutex { return mMutex; }
+ sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const final
+ REQUIRES(mutex());
+
+ // ---- end of IAfMelReporterCallback interface
+
+ // ---- begin IAfPatchPanelCallback interface
+
+ void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) final REQUIRES(mutex());
+ void closeThreadInternal_l(const sp<IAfRecordThread>& thread) final REQUIRES(mutex());
+ // return thread associated with primary hardware device, or NULL
+ IAfPlaybackThread* primaryPlaybackThread_l() const final REQUIRES(mutex());
+ IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const final
+ REQUIRES(mutex());
+ IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const final REQUIRES(mutex());
+ IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const final REQUIRES(mutex());
+ sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
+ audio_io_handle_t* input,
+ audio_config_t* config,
+ audio_devices_t device,
+ const char* address,
+ audio_source_t source,
+ audio_input_flags_t flags,
+ audio_devices_t outputDevice,
+ const String8& outputDeviceAddress) final REQUIRES(mutex());
+ sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
+ audio_io_handle_t* output,
+ audio_config_t* halConfig,
+ audio_config_base_t* mixerConfig,
+ audio_devices_t deviceType,
+ const String8& address,
+ audio_output_flags_t flags) final REQUIRES(mutex());
+ const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+ getAudioHwDevs_l() const final REQUIRES(mutex()) { return mAudioHwDevs; }
+ void updateDownStreamPatches_l(const struct audio_patch* patch,
+ const std::set<audio_io_handle_t>& streams) final REQUIRES(mutex());
+ void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final
+ REQUIRES(mutex());
+
+ // ---- end of IAfPatchPanelCallback interface
+
+ // ----- begin IAfThreadCallback interface
+
+ bool isNonOffloadableGlobalEffectEnabled_l() const final REQUIRES(mutex());
+ bool btNrecIsOff() const final { return mBtNrecIsOff.load(); }
+ float masterVolume_l() const final REQUIRES(mutex());
+ bool masterMute_l() const final REQUIRES(mutex());
+ float getMasterBalance_l() const REQUIRES(mutex());
+ // no range check, AudioFlinger::mutex() held
+ bool streamMute_l(audio_stream_type_t stream) const final REQUIRES(mutex()) {
+ return mStreamTypes[stream].mute;
+ }
+ audio_mode_t getMode() const final { return mMode; }
+ bool isLowRamDevice() const final { return mIsLowRamDevice; }
+ uint32_t getScreenState() const final { return mScreenState; }
+
+ std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const final
+ REQUIRES(mutex());
+ const sp<IAfPatchPanel>& getPatchPanel() const final { return mPatchPanel; }
+ const sp<MelReporter>& getMelReporter() const final { return mMelReporter; }
+ const sp<EffectsFactoryHalInterface>& getEffectsFactoryHal() const final {
+ return mEffectsFactoryHal;
+ }
+ sp<IAudioManager> getOrCreateAudioManager() final;
+
+ // Called when the last effect handle on an effect instance is removed. If this
+ // effect belongs to an effect chain in mOrphanEffectChains, the chain is updated
+ // and removed from mOrphanEffectChains if it does not contain any effect.
+ // Return true if the effect was found in mOrphanEffectChains, false otherwise.
+ bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect) final
+ EXCLUDES_AudioFlinger_Mutex;
+
+ status_t moveEffectChain_ll(audio_session_t sessionId,
+ IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final
+ REQUIRES(mutex(), audio_utils::ThreadBase_Mutex);
+
+ // This is a helper that is called during incoming binder calls.
+ // Requests media.log to start merging log buffers
+ void requestLogMerge() final;
+ sp<NBLog::Writer> newWriter_l(size_t size, const char *name) final REQUIRES(mutex());
+ void unregisterWriter(const sp<NBLog::Writer>& writer) final;
+
+ sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
+ audio_session_t triggerSession,
+ audio_session_t listenerSession,
+ const audioflinger::SyncEventCallback& callBack,
+ const wp<IAfTrackBase>& cookie) final EXCLUDES_AudioFlinger_Mutex;
+
+ void ioConfigChanged(audio_io_config_event_t event,
+ const sp<AudioIoDescriptor>& ioDesc,
+ pid_t pid = 0) final EXCLUDES_AudioFlinger_ClientMutex;
+ void onNonOffloadableGlobalEffectEnable() final EXCLUDES_AudioFlinger_Mutex;
+ void onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) final
+ EXCLUDES_AudioFlinger_ClientMutex;
+
+ // ---- end of IAfThreadCallback interface
+
+ /* List available audio ports and their attributes */
+ status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const
+ EXCLUDES_AudioFlinger_Mutex;
+
sp<EffectsFactoryHalInterface> getEffectsFactory();
+public:
+ // TODO(b/292281786): Remove this when Oboeservice can get access to
+ // openMmapStream through an IAudioFlinger handle directly.
+ static inline std::atomic<AudioFlinger*> gAudioFlinger = nullptr;
+
status_t openMmapStream(MmapStreamInterface::stream_direction_t direction,
const audio_attributes_t *attr,
audio_config_base_t *config,
@@ -342,22 +412,7 @@
audio_session_t *sessionId,
const sp<MmapStreamCallback>& callback,
sp<MmapStreamInterface>& interface,
- audio_port_handle_t *handle);
-
- static os::HapticScale onExternalVibrationStart(
- const sp<os::ExternalVibration>& externalVibration);
- static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
-
- status_t addEffectToHal(
- const struct audio_port_config *device, const sp<EffectHalInterface>& effect);
- status_t removeEffectFromHal(
- const struct audio_port_config *device, const sp<EffectHalInterface>& effect);
-
- void updateDownStreamPatches_l(const struct audio_patch *patch,
- const std::set<audio_io_handle_t>& streams);
-
- std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l();
-
+ audio_port_handle_t *handle) EXCLUDES_AudioFlinger_Mutex;
private:
// FIXME The 400 is temporarily too high until a leak of writers in media.log is fixed.
static const size_t kLogMemorySize = 400 * 1024;
@@ -365,145 +420,33 @@
// When a log writer is unregistered, it is done lazily so that media.log can continue to see it
// for as long as possible. The memory is only freed when it is needed for another log writer.
Vector< sp<NBLog::Writer> > mUnregisteredWriters;
- Mutex mUnregisteredWritersLock;
-
-public:
- // Life cycle of gAudioFlinger and AudioFlinger:
- //
- // AudioFlinger is created once and survives until audioserver crashes
- // irrespective of sp<> and wp<> as it is refcounted by ServiceManager and we
- // don't issue a ServiceManager::tryUnregisterService().
- //
- // gAudioFlinger is an atomic pointer set on AudioFlinger::onFirstRef().
- // After this is set, it is safe to obtain a wp<> or sp<> from it as the
- // underlying object does not go away.
- //
- // Note: For most inner classes, it is acceptable to hold a reference to the outer
- // AudioFlinger instance as creation requires AudioFlinger to exist in the first place.
- //
- // An atomic here ensures underlying writes have completed before setting
- // the pointer. Access by memory_order_seq_cst.
- //
-
- static inline std::atomic<AudioFlinger *> gAudioFlinger = nullptr;
-
- sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
- audio_session_t triggerSession,
- audio_session_t listenerSession,
- const audioflinger::SyncEventCallback& callBack,
- const wp<RefBase>& cookie);
-
- bool btNrecIsOff() const { return mBtNrecIsOff.load(); }
-
- void lock() ACQUIRE(mLock) { mLock.lock(); }
- void unlock() RELEASE(mLock) { mLock.unlock(); }
-
-private:
-
- audio_mode_t getMode() const { return mMode; }
+ audio_utils::mutex& unregisteredWritersMutex() const { return mUnregisteredWritersMutex; }
+ mutable audio_utils::mutex mUnregisteredWritersMutex;
AudioFlinger() ANDROID_API;
- virtual ~AudioFlinger();
+ ~AudioFlinger() override;
// call in any IAudioFlinger method that accesses mPrimaryHardwareDev
- status_t initCheck() const { return mPrimaryHardwareDev == NULL ?
+ status_t initCheck() const { return mPrimaryHardwareDev == NULL ?
NO_INIT : NO_ERROR; }
// RefBase
- virtual void onFirstRef();
+ void onFirstRef() override;
AudioHwDevice* findSuitableHwDev_l(audio_module_handle_t module,
- audio_devices_t deviceType);
-
- // Set kEnableExtendedChannels to true to enable greater than stereo output
- // for the MixerThread and device sink. Number of channels allowed is
- // FCC_2 <= channels <= AudioMixer::MAX_NUM_CHANNELS.
- static const bool kEnableExtendedChannels = true;
-
- // Returns true if channel mask is permitted for the PCM sink in the MixerThread
- static inline bool isValidPcmSinkChannelMask(audio_channel_mask_t channelMask) {
- switch (audio_channel_mask_get_representation(channelMask)) {
- case AUDIO_CHANNEL_REPRESENTATION_POSITION: {
- // Haptic channel mask is only applicable for channel position mask.
- const uint32_t channelCount = audio_channel_count_from_out_mask(
- static_cast<audio_channel_mask_t>(channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL));
- const uint32_t maxChannelCount = kEnableExtendedChannels
- ? AudioMixer::MAX_NUM_CHANNELS : FCC_2;
- if (channelCount < FCC_2 // mono is not supported at this time
- || channelCount > maxChannelCount) {
- return false;
- }
- // check that channelMask is the "canonical" one we expect for the channelCount.
- return audio_channel_position_mask_is_out_canonical(channelMask);
- }
- case AUDIO_CHANNEL_REPRESENTATION_INDEX:
- if (kEnableExtendedChannels) {
- const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
- if (channelCount >= FCC_2 // mono is not supported at this time
- && channelCount <= AudioMixer::MAX_NUM_CHANNELS) {
- return true;
- }
- }
- return false;
- default:
- return false;
- }
- }
-
- // Set kEnableExtendedPrecision to true to use extended precision in MixerThread
- static const bool kEnableExtendedPrecision = true;
-
- // Returns true if format is permitted for the PCM sink in the MixerThread
- static inline bool isValidPcmSinkFormat(audio_format_t format) {
- switch (format) {
- case AUDIO_FORMAT_PCM_16_BIT:
- return true;
- case AUDIO_FORMAT_PCM_FLOAT:
- case AUDIO_FORMAT_PCM_24_BIT_PACKED:
- case AUDIO_FORMAT_PCM_32_BIT:
- case AUDIO_FORMAT_PCM_8_24_BIT:
- return kEnableExtendedPrecision;
- default:
- return false;
- }
- }
-
- // standby delay for MIXER and DUPLICATING playback threads is read from property
- // ro.audio.flinger_standbytime_ms or defaults to kDefaultStandbyTimeInNsecs
- static nsecs_t mStandbyTimeInNsecs;
+ audio_devices_t deviceType) REQUIRES(mutex());
// incremented by 2 when screen state changes, bit 0 == 1 means "off"
- // AudioFlinger::setParameters() updates, other threads read w/o lock
- static uint32_t mScreenState;
+ // AudioFlinger::setParameters() updates with mutex().
+ std::atomic_uint32_t mScreenState{};
- // Internal dump utilities.
- static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
- static bool dumpTryLock(Mutex& mutex);
void dumpPermissionDenial(int fd, const Vector<String16>& args);
- void dumpClients(int fd, const Vector<String16>& args);
- void dumpInternals(int fd, const Vector<String16>& args);
+ void dumpClients_ll(int fd, const Vector<String16>& args) REQUIRES(mutex(), clientMutex());
+ void dumpInternals_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
SimpleLog mThreadLog{16}; // 16 Thread history limit
- class ThreadBase;
- void dumpToThreadLog_l(const sp<ThreadBase> &thread);
-
- // --- Client ---
- class Client : public RefBase {
- public:
- Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
- virtual ~Client();
- AllocatorFactory::ClientAllocator& allocator();
- pid_t pid() const { return mPid; }
- sp<AudioFlinger> audioFlinger() const { return mAudioFlinger; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Client);
-
- const sp<AudioFlinger> mAudioFlinger;
- const pid_t mPid;
- AllocatorFactory::ClientAllocator mClientAllocator;
- };
+ void dumpToThreadLog_l(const sp<IAfThreadBase>& thread) REQUIRES(mutex());
// --- Notification Client ---
class NotificationClient : public IBinder::DeathRecipient {
@@ -550,92 +493,29 @@
bool mPendingRequests;
// Mutex and condition variable around mPendingRequests' value
- Mutex mMutex;
- Condition mCond;
+ audio_utils::mutex mMutex;
+ audio_utils::condition_variable mCondition;
// Duration of the sleep period after a processed request
static const int kPostTriggerSleepPeriod = 1000000;
};
- const sp<MediaLogNotifier> mMediaLogNotifier;
-
- // This is a helper that is called during incoming binder calls.
- // Requests media.log to start merging log buffers
- void requestLogMerge();
-
- class TrackHandle;
- class RecordHandle;
- class RecordThread;
- class PlaybackThread;
- class MixerThread;
- class DirectOutputThread;
- class OffloadThread;
- class DuplicatingThread;
- class AsyncCallbackThread;
- class BitPerfectThread;
- class Track;
- class RecordTrack;
- class EffectBase;
- class EffectModule;
- class EffectHandle;
- class EffectChain;
- class DeviceEffectProxy;
- class DeviceEffectManager;
- class PatchPanel;
- class DeviceEffectManagerCallback;
-
- struct AudioStreamIn;
- struct TeePatch;
- using TeePatches = std::vector<TeePatch>;
-
-
- struct stream_type_t {
- stream_type_t()
- : volume(1.0f),
- mute(false)
- {
- }
- float volume;
- bool mute;
- };
-
- // Abstraction for the Audio Source for the RecordThread (HAL or PassthruPatchRecord).
- struct Source
- {
- virtual ~Source() = default;
- // The following methods have the same signatures as in StreamHalInterface.
- virtual status_t read(void *buffer, size_t bytes, size_t *read) = 0;
- virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
- virtual status_t standby() = 0;
- };
-
- // --- PlaybackThread ---
-
-#include "Threads.h"
-
-#include "PatchPanel.h"
-
-#include "PatchCommandThread.h"
-
-#include "Effects.h"
-
-#include "DeviceEffectManager.h"
-
-#include "MelReporter.h"
+ const sp<MediaLogNotifier> mMediaLogNotifier = sp<MediaLogNotifier>::make();
// Find io handle by session id.
// Preference is given to an io handle with a matching effect chain to session id.
// If none found, AUDIO_IO_HANDLE_NONE is returned.
template <typename T>
static audio_io_handle_t findIoHandleBySessionId_l(
- audio_session_t sessionId, const T& threads) {
+ audio_session_t sessionId, const T& threads)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) {
audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
for (size_t i = 0; i < threads.size(); i++) {
const uint32_t sessionType = threads.valueAt(i)->hasAudioSession(sessionId);
if (sessionType != 0) {
io = threads.keyAt(i);
- if ((sessionType & AudioFlinger::ThreadBase::EFFECT_SESSION) != 0) {
+ if ((sessionType & IAfThreadBase::EFFECT_SESSION) != 0) {
break; // effect chain here.
}
}
@@ -643,130 +523,15 @@
return io;
}
- // server side of the client's IAudioTrack
- class TrackHandle : public android::media::BnAudioTrack {
- public:
- explicit TrackHandle(const sp<PlaybackThread::Track>& track);
- virtual ~TrackHandle();
+ IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const REQUIRES(mutex());
+ IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const REQUIRES(mutex());
- binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) override;
- binder::Status start(int32_t* _aidl_return) override;
- binder::Status stop() override;
- binder::Status flush() override;
- binder::Status pause() override;
- binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) override;
- binder::Status setParameters(const std::string& keyValuePairs,
- int32_t* _aidl_return) override;
- binder::Status selectPresentation(int32_t presentationId, int32_t programId,
- int32_t* _aidl_return) override;
- binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
- int32_t* _aidl_return) override;
- binder::Status signal() override;
- binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
- const media::VolumeShaperOperation& operation,
- int32_t* _aidl_return) override;
- binder::Status getVolumeShaperState(
- int32_t id,
- std::optional<media::VolumeShaperState>* _aidl_return) override;
- binder::Status getDualMonoMode(
- media::audio::common::AudioDualMonoMode* _aidl_return) override;
- binder::Status setDualMonoMode(
- media::audio::common::AudioDualMonoMode mode) override;
- binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
- binder::Status setAudioDescriptionMixLevel(float leveldB) override;
- binder::Status getPlaybackRateParameters(
- media::audio::common::AudioPlaybackRate* _aidl_return) override;
- binder::Status setPlaybackRateParameters(
- const media::audio::common::AudioPlaybackRate& playbackRate) override;
+ sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const REQUIRES(mutex());
+ std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const REQUIRES(mutex());
- private:
- const sp<PlaybackThread::Track> mTrack;
- };
- // server side of the client's IAudioRecord
- class RecordHandle : public android::media::BnAudioRecord {
- public:
- explicit RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
- virtual ~RecordHandle();
- virtual binder::Status start(int /*AudioSystem::sync_event_t*/ event,
- int /*audio_session_t*/ triggerSession);
- virtual binder::Status stop();
- virtual binder::Status getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones);
- virtual binder::Status setPreferredMicrophoneDirection(
- int /*audio_microphone_direction_t*/ direction);
- virtual binder::Status setPreferredMicrophoneFieldDimension(float zoom);
- virtual binder::Status shareAudioHistory(const std::string& sharedAudioPackageName,
- int64_t sharedAudioStartMs);
-
- private:
- const sp<RecordThread::RecordTrack> mRecordTrack;
-
- // for use from destructor
- void stop_nonvirtual();
- };
-
- // Mmap stream control interface implementation. Each MmapThreadHandle controls one
- // MmapPlaybackThread or MmapCaptureThread instance.
- class MmapThreadHandle : public MmapStreamInterface {
- public:
- explicit MmapThreadHandle(const sp<MmapThread>& thread);
- virtual ~MmapThreadHandle();
-
- // MmapStreamInterface virtuals
- virtual status_t createMmapBuffer(int32_t minSizeFrames,
- struct audio_mmap_buffer_info *info);
- virtual status_t getMmapPosition(struct audio_mmap_position *position);
- virtual status_t getExternalPosition(uint64_t *position, int64_t *timeNanos);
- virtual status_t start(const AudioClient& client,
- const audio_attributes_t *attr,
- audio_port_handle_t *handle);
- virtual status_t stop(audio_port_handle_t handle);
- virtual status_t standby();
- status_t reportData(const void* buffer, size_t frameCount) override;
-
- private:
- const sp<MmapThread> mThread;
- };
-
- ThreadBase *checkThread_l(audio_io_handle_t ioHandle) const;
- sp<AudioFlinger::ThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const
- REQUIRES(mLock);
- PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const;
- MixerThread *checkMixerThread_l(audio_io_handle_t output) const;
- RecordThread *checkRecordThread_l(audio_io_handle_t input) const;
- MmapThread *checkMmapThread_l(audio_io_handle_t io) const;
- VolumeInterface *getVolumeInterface_l(audio_io_handle_t output) const;
- Vector <VolumeInterface *> getAllVolumeInterfaces_l() const;
-
- sp<ThreadBase> openInput_l(audio_module_handle_t module,
- audio_io_handle_t *input,
- audio_config_t *config,
- audio_devices_t device,
- const char* address,
- audio_source_t source,
- audio_input_flags_t flags,
- audio_devices_t outputDevice,
- const String8& outputDeviceAddress);
- sp<ThreadBase> openOutput_l(audio_module_handle_t module,
- audio_io_handle_t *output,
- audio_config_t *halConfig,
- audio_config_base_t *mixerConfig,
- audio_devices_t deviceType,
- const String8& address,
- audio_output_flags_t flags);
-
- void closeOutputFinish(const sp<PlaybackThread>& thread);
- void closeInputFinish(const sp<RecordThread>& thread);
-
- // no range check, AudioFlinger::mLock held
- bool streamMute_l(audio_stream_type_t stream) const
- { return mStreamTypes[stream].mute; }
- void ioConfigChanged(audio_io_config_event_t event,
- const sp<AudioIoDescriptor>& ioDesc,
- pid_t pid = 0);
- void onSupportedLatencyModesChanged(
- audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes);
+ static void closeOutputFinish(const sp<IAfPlaybackThread>& thread);
+ void closeInputFinish(const sp<IAfRecordThread>& thread);
// Allocate an audio_unique_id_t.
// Specific types are audio_io_handle_t, audio_session_t, effect ID (int),
@@ -779,38 +544,26 @@
// Thus it may fail by returning an ID of the wrong sign,
// or by returning a non-unique ID.
// This is the internal API. For the binder API see newAudioUniqueId().
- audio_unique_id_t nextUniqueId(audio_unique_id_use_t use);
-
- status_t moveEffectChain_l(audio_session_t sessionId,
- PlaybackThread *srcThread,
- PlaybackThread *dstThread);
-
- status_t moveAuxEffectToIo(int EffectId,
- const sp<PlaybackThread>& dstThread,
- sp<PlaybackThread> *srcThread);
+ // used by IAfDeviceEffectManagerCallback, IAfPatchPanelCallback, IAfThreadCallback
+ audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) final;
// return thread associated with primary hardware device, or NULL
- PlaybackThread *primaryPlaybackThread_l() const;
- DeviceTypeSet primaryOutputDevice_l() const;
+ DeviceTypeSet primaryOutputDevice_l() const REQUIRES(mutex());
// return the playback thread with smallest HAL buffer size, and prefer fast
- PlaybackThread *fastPlaybackThread_l() const;
+ IAfPlaybackThread* fastPlaybackThread_l() const REQUIRES(mutex());
- sp<ThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
+ sp<IAfThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId)
+ REQUIRES(mutex());
- ThreadBase *hapticPlaybackThread_l() const;
+ IAfThreadBase* hapticPlaybackThread_l() const REQUIRES(mutex());
void updateSecondaryOutputsForTrack_l(
- PlaybackThread::Track* track,
- PlaybackThread* thread,
- const std::vector<audio_io_handle_t>& secondaryOutputs) const;
+ IAfTrack* track,
+ IAfPlaybackThread* thread,
+ const std::vector<audio_io_handle_t>& secondaryOutputs) const REQUIRES(mutex());
-
- void removeClient_l(pid_t pid);
- void removeNotificationClient(pid_t pid);
- bool isNonOffloadableGlobalEffectEnabled_l();
- void onNonOffloadableGlobalEffectEnable();
- bool isSessionAcquired_l(audio_session_t audioSession);
+ bool isSessionAcquired_l(audio_session_t audioSession) REQUIRES(mutex());
// Store an effect chain to mOrphanEffectChains keyed vector.
// Called when a thread exits and effects are still attached to it.
@@ -819,51 +572,18 @@
// return ALREADY_EXISTS if a chain with the same session already exists in
// mOrphanEffectChains. Note that this should never happen as there is only one
// chain for a given session and it is attached to only one thread at a time.
- status_t putOrphanEffectChain_l(const sp<EffectChain>& chain);
+ status_t putOrphanEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
// Get an effect chain for the specified session in mOrphanEffectChains and remove
// it if found. Returns 0 if not found (this is the most common case).
- sp<EffectChain> getOrphanEffectChain_l(audio_session_t session);
- // Called when the last effect handle on an effect instance is removed. If this
- // effect belongs to an effect chain in mOrphanEffectChains, the chain is updated
- // and removed from mOrphanEffectChains if it does not contain any effect.
- // Return true if the effect was found in mOrphanEffectChains, false otherwise.
- bool updateOrphanEffectChains(const sp<EffectModule>& effect);
+ sp<IAfEffectChain> getOrphanEffectChain_l(audio_session_t session) REQUIRES(mutex());
- std::vector< sp<EffectModule> > purgeStaleEffects_l();
+ std::vector< sp<IAfEffectModule> > purgeStaleEffects_l() REQUIRES(mutex());
- void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
- void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
- void forwardParametersToDownstreamPatches_l(
+ void broadcastParametersToRecordThreads_l(const String8& keyValuePairs) REQUIRES(mutex());
+ void forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
- const std::function<bool(const sp<PlaybackThread>&)>& useThread = nullptr);
-
- // AudioStreamIn is immutable, so their fields are const.
- // For emphasis, we could also make all pointers to them be "const *",
- // but that would clutter the code unnecessarily.
-
- struct AudioStreamIn : public Source {
- AudioHwDevice* const audioHwDev;
- sp<StreamInHalInterface> stream;
- audio_input_flags_t flags;
-
- sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
-
- AudioStreamIn(AudioHwDevice *dev, const sp<StreamInHalInterface>& in,
- audio_input_flags_t flags) :
- audioHwDev(dev), stream(in), flags(flags) {}
- status_t read(void *buffer, size_t bytes, size_t *read) override {
- return stream->read(buffer, bytes, read);
- }
- status_t getCapturePosition(int64_t *frames, int64_t *time) override {
- return stream->getCapturePosition(frames, time);
- }
- status_t standby() override { return stream->standby(); }
- };
-
- struct TeePatch {
- sp<RecordThread::PatchRecord> patchRecord;
- sp<PlaybackThread::PatchTrack> patchTrack;
- };
+ const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread = nullptr)
+ REQUIRES(mutex());
// for mAudioSessionRefs only
struct AudioSessionRef {
@@ -875,25 +595,28 @@
int mCnt;
};
- mutable Mutex mLock;
+ mutable audio_utils::mutex mMutex;
// protects mClients and mNotificationClients.
- // must be locked after mLock and ThreadBase::mLock if both must be locked
- // avoids acquiring AudioFlinger::mLock from inside thread loop.
- mutable Mutex mClientLock;
- // protected by mClientLock
- DefaultKeyedVector< pid_t, wp<Client> > mClients; // see ~Client()
+ // must be locked after mutex() and ThreadBase::mutex() if both must be locked
+ // avoids acquiring AudioFlinger::mutex() from inside thread loop.
- mutable Mutex mHardwareLock;
- // NOTE: If both mLock and mHardwareLock mutexes must be held,
- // always take mLock before mHardwareLock
+ mutable audio_utils::mutex mClientMutex;
- // guarded by mHardwareLock
- AudioHwDevice* mPrimaryHardwareDev;
- DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs;
+ DefaultKeyedVector<pid_t, wp<Client>> mClients GUARDED_BY(clientMutex()); // see ~Client()
- // These two fields are immutable after onFirstRef(), so no lock needed to access
- sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
- sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;
+ audio_utils::mutex& hardwareMutex() const { return mHardwareMutex; }
+
+ mutable audio_utils::mutex mHardwareMutex;
+ // NOTE: If both mMutex and mHardwareMutex mutexes must be held,
+ // always take mMutex before mHardwareMutex
+
+ std::atomic<AudioHwDevice*> mPrimaryHardwareDev = nullptr;
+ DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs
+ GUARDED_BY(hardwareMutex()) {nullptr /* defValue */};
+
+ const sp<DevicesFactoryHalInterface> mDevicesFactoryHal =
+ DevicesFactoryHalInterface::create();
+ /* const */ sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback; // set onFirstRef().
// for dump, indicates which hardware operation is currently in progress (but not stream ops)
enum hardware_call_state {
@@ -923,131 +646,110 @@
AUDIO_HW_SET_SIMULATE_CONNECTIONS, // setSimulateDeviceConnections
};
- mutable hardware_call_state mHardwareStatus; // for dump only
+ mutable hardware_call_state mHardwareStatus = AUDIO_HW_IDLE; // for dump only
+ DefaultKeyedVector<audio_io_handle_t, sp<IAfPlaybackThread>> mPlaybackThreads
+ GUARDED_BY(mutex());
+ stream_type_t mStreamTypes[AUDIO_STREAM_CNT] GUARDED_BY(mutex());
+ float mMasterVolume GUARDED_BY(mutex()) = 1.f;
+ bool mMasterMute GUARDED_BY(mutex()) = false;
+ float mMasterBalance GUARDED_BY(mutex()) = 0.f;
- DefaultKeyedVector< audio_io_handle_t, sp<PlaybackThread> > mPlaybackThreads;
- stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
+ DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads GUARDED_BY(mutex());
- // member variables below are protected by mLock
- float mMasterVolume;
- bool mMasterMute;
- float mMasterBalance = 0.f;
- // end of variables protected by mLock
-
- DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> > mRecordThreads;
-
- // protected by mClientLock
- DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
+ DefaultKeyedVector<pid_t, sp<NotificationClient>> mNotificationClients
+ GUARDED_BY(clientMutex());
// updated by atomic_fetch_add_explicit
- volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX];
+ volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX]; // ctor init
- audio_mode_t mMode;
- std::atomic_bool mBtNrecIsOff;
+ std::atomic<audio_mode_t> mMode = AUDIO_MODE_INVALID;
+ std::atomic<bool> mBtNrecIsOff = false;
- // protected by mLock
- Vector<AudioSessionRef*> mAudioSessionRefs;
+ Vector<AudioSessionRef*> mAudioSessionRefs GUARDED_BY(mutex());
- float masterVolume_l() const;
- float getMasterBalance_l() const;
- bool masterMute_l() const;
- AudioHwDevice* loadHwModule_l(const char *name);
+ AudioHwDevice* loadHwModule_ll(const char *name) REQUIRES(mutex(), hardwareMutex());
// sync events awaiting for a session to be created.
- std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents;
+ std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents GUARDED_BY(mutex());
// Effect chains without a valid thread
- DefaultKeyedVector< audio_session_t , sp<EffectChain> > mOrphanEffectChains;
+ DefaultKeyedVector<audio_session_t, sp<IAfEffectChain>> mOrphanEffectChains
+ GUARDED_BY(mutex());
// list of sessions for which a valid HW A/V sync ID was retrieved from the HAL
- DefaultKeyedVector< audio_session_t , audio_hw_sync_t >mHwAvSyncIds;
+ DefaultKeyedVector<audio_session_t, audio_hw_sync_t> mHwAvSyncIds GUARDED_BY(mutex());
// list of MMAP stream control threads. Those threads allow for wake lock, routing
// and volume control for activity on the associated MMAP stream at the HAL.
// Audio data transfer is directly handled by the client creating the MMAP stream
- DefaultKeyedVector< audio_io_handle_t, sp<MmapThread> > mMmapThreads;
+ DefaultKeyedVector<audio_io_handle_t, sp<IAfMmapThread>> mMmapThreads GUARDED_BY(mutex());
-private:
- sp<Client> registerPid(pid_t pid); // always returns non-0
+ sp<Client> registerPid(pid_t pid) EXCLUDES_AudioFlinger_ClientMutex; // always returns non-0
// for use from destructor
- status_t closeOutput_nonvirtual(audio_io_handle_t output);
- void closeThreadInternal_l(const sp<PlaybackThread>& thread);
- status_t closeInput_nonvirtual(audio_io_handle_t input);
- void closeThreadInternal_l(const sp<RecordThread>& thread);
- void setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId);
+ status_t closeOutput_nonvirtual(audio_io_handle_t output) EXCLUDES_AudioFlinger_Mutex;
+ status_t closeInput_nonvirtual(audio_io_handle_t input) EXCLUDES_AudioFlinger_Mutex;
+ void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId)
+ REQUIRES(mutex());
- status_t checkStreamType(audio_stream_type_t stream) const;
+ static status_t checkStreamType(audio_stream_type_t stream);
+ // no mutex needed.
void filterReservedParameters(String8& keyValuePairs, uid_t callingUid);
void logFilteredParameters(size_t originalKVPSize, const String8& originalKVPs,
size_t rejectedKVPSize, const String8& rejectedKVPs,
uid_t callingUid);
- sp<IAudioManager> getOrCreateAudioManager();
-
-public:
// These methods read variables atomically without mLock,
// though the variables are updated with mLock.
- bool isLowRamDevice() const { return mIsLowRamDevice; }
size_t getClientSharedHeapSize() const;
-private:
- std::atomic<bool> mIsLowRamDevice;
- bool mIsDeviceTypeKnown;
- int64_t mTotalMemory;
- std::atomic<size_t> mClientSharedHeapSize;
+ std::atomic<bool> mIsLowRamDevice = true;
+ bool mIsDeviceTypeKnown GUARDED_BY(mutex()) = false;
+ int64_t mTotalMemory GUARDED_BY(mutex()) = 0;
+ std::atomic<size_t> mClientSharedHeapSize = kMinimumClientSharedHeapSizeBytes;
static constexpr size_t kMinimumClientSharedHeapSizeBytes = 1024 * 1024; // 1MB
- nsecs_t mGlobalEffectEnableTime; // when a global effect was last enabled
+ // when a global effect was last enabled
+ nsecs_t mGlobalEffectEnableTime GUARDED_BY(mutex()) = 0;
- // protected by mLock
- PatchPanel mPatchPanel;
- sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
+ /* const */ sp<IAfPatchPanel> mPatchPanel;
- const sp<PatchCommandThread> mPatchCommandThread;
- sp<DeviceEffectManager> mDeviceEffectManager;
- sp<MelReporter> mMelReporter;
+ const sp<EffectsFactoryHalInterface> mEffectsFactoryHal =
+ audioflinger::EffectConfiguration::getEffectsFactoryHal();
- bool mSystemReady;
- std::atomic_bool mAudioPolicyReady{};
+ const sp<PatchCommandThread> mPatchCommandThread = sp<PatchCommandThread>::make();
+ /* const */ sp<DeviceEffectManager> mDeviceEffectManager; // set onFirstRef
+ /* const */ sp<MelReporter> mMelReporter; // set onFirstRef
- mediautils::UidInfo mUidInfo;
+ bool mSystemReady GUARDED_BY(mutex()) = false;
+ std::atomic<bool> mAudioPolicyReady = false;
+ mediautils::UidInfo mUidInfo GUARDED_BY(mutex());
+
+ // no mutex needed.
SimpleLog mRejectedSetParameterLog;
SimpleLog mAppSetParameterLog;
SimpleLog mSystemSetParameterLog;
- std::vector<media::AudioVibratorInfo> mAudioVibratorInfos;
+ std::vector<media::AudioVibratorInfo> mAudioVibratorInfos GUARDED_BY(mutex());
static inline constexpr const char *mMetricsId = AMEDIAMETRICS_KEY_AUDIO_FLINGER;
- // Keep in sync with java definition in media/java/android/media/AudioRecord.java
- static constexpr int32_t kMaxSharedAudioHistoryMs = 5000;
-
std::map<media::audio::common::AudioMMapPolicyType,
- std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos;
- int32_t mAAudioBurstsPerBuffer = 0;
- int32_t mAAudioHwBurstMinMicros = 0;
+ std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos
+ GUARDED_BY(mutex());
+ int32_t mAAudioBurstsPerBuffer GUARDED_BY(mutex()) = 0;
+ int32_t mAAudioHwBurstMinMicros GUARDED_BY(mutex()) = 0;
/** Interface for interacting with the AudioService. */
- mediautils::atomic_sp<IAudioManager> mAudioManager;
+ mediautils::atomic_sp<IAudioManager> mAudioManager;
// Bluetooth Variable latency control logic is enabled or disabled
- std::atomic_bool mBluetoothLatencyModesEnabled;
+ std::atomic<bool> mBluetoothLatencyModesEnabled = true;
};
-#undef INCLUDING_FROM_AUDIOFLINGER_H
-
-std::string formatToString(audio_format_t format);
-std::string inputFlagsToString(audio_input_flags_t flags);
-std::string outputFlagsToString(audio_output_flags_t flags);
-std::string devicesToString(audio_devices_t devices);
-const char *sourceToString(audio_source_t source);
-
// ----------------------------------------------------------------------------
} // namespace android
-
-#endif // ANDROID_AUDIO_FLINGER_H
diff --git a/services/audioflinger/Client.cpp b/services/audioflinger/Client.cpp
new file mode 100644
index 0000000..93599ac
--- /dev/null
+++ b/services/audioflinger/Client.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Client.h"
+
+namespace android {
+
+Client::Client(const sp<IAfClientCallback>& afClientCallback, pid_t pid)
+ : mAfClientCallback(afClientCallback)
+ , mPid(pid)
+ , mClientAllocator(AllocatorFactory::getClientAllocator()) {}
+
+// Client destructor must be called with AudioFlinger::mClientLock held
+Client::~Client()
+{
+ mAfClientCallback->removeClient_l(mPid);
+}
+
+AllocatorFactory::ClientAllocator& Client::allocator()
+{
+ return mClientAllocator;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/Client.h b/services/audioflinger/Client.h
new file mode 100644
index 0000000..ff0d751
--- /dev/null
+++ b/services/audioflinger/Client.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <afutils/AllocatorFactory.h>
+#include <audio_utils/mutex.h>
+#include <android-base/macros.h> // DISALLOW_COPY_AND_ASSIGN
+#include <utils/RefBase.h> // avoid transitive dependency
+
+// TODO(b/291318727) Move to nested namespace
+namespace android {
+
+class IAfPlaybackThread;
+
+class IAfClientCallback : public virtual RefBase {
+public:
+ virtual audio_utils::mutex& clientMutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_ClientMutex) = 0;
+ virtual void removeClient_l(pid_t pid) REQUIRES(clientMutex()) = 0;
+ virtual void removeNotificationClient(pid_t pid) EXCLUDES_AudioFlinger_Mutex = 0;
+
+ // used indirectly by clients.
+ virtual status_t moveAuxEffectToIo(
+ int effectId,
+ const sp<IAfPlaybackThread>& dstThread,
+ sp<IAfPlaybackThread>* srcThread) EXCLUDES_AudioFlinger_Mutex = 0;
+};
+
+class Client : public RefBase {
+public:
+ Client(const sp<IAfClientCallback>& audioFlinger, pid_t pid);
+
+ // TODO(b/289139675) make Client container.
+ // Client destructor must be called with AudioFlinger::mClientLock held
+ ~Client() override;
+ AllocatorFactory::ClientAllocator& allocator();
+ pid_t pid() const { return mPid; }
+ const auto& afClientCallback() const { return mAfClientCallback; }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(Client);
+
+ const sp<IAfClientCallback> mAfClientCallback;
+ const pid_t mPid;
+ AllocatorFactory::ClientAllocator mClientAllocator;
+};
+
+} // namespace android
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index f996157..0a7be75 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -15,16 +15,17 @@
** limitations under the License.
*/
-
-#define LOG_TAG "AudioFlinger::DeviceEffectManager"
+#define LOG_TAG "DeviceEffectManager"
//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-#include <audio_utils/primitives.h>
+#include "DeviceEffectManager.h"
-#include "AudioFlinger.h"
#include "EffectConfiguration.h"
+
+#include <afutils/DumpTryLock.h>
+#include <audio_utils/primitives.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <utils/Log.h>
// ----------------------------------------------------------------------------
@@ -34,12 +35,31 @@
using detail::AudioHalVersionInfo;
using media::IEffectClient;
-void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
- const PatchPanel::Patch& patch) {
+DeviceEffectManager::DeviceEffectManager(
+ const sp<IAfDeviceEffectManagerCallback>& afDeviceEffectManagerCallback)
+ : mAfDeviceEffectManagerCallback(afDeviceEffectManagerCallback),
+ mMyCallback(sp<DeviceEffectManagerCallback>::make(*this)) {}
+
+void DeviceEffectManager::onFirstRef() {
+ mAfDeviceEffectManagerCallback->getPatchCommandThread()->addListener(this);
+}
+
+status_t DeviceEffectManager::addEffectToHal(const struct audio_port_config* device,
+ const sp<EffectHalInterface>& effect) {
+ return mAfDeviceEffectManagerCallback->addEffectToHal(device, effect);
+};
+
+status_t DeviceEffectManager::removeEffectFromHal(const struct audio_port_config* device,
+ const sp<EffectHalInterface>& effect) {
+ return mAfDeviceEffectManagerCallback->removeEffectFromHal(device, effect);
+};
+
+void DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
+ const IAfPatchPanel::Patch& patch) {
ALOGV("%s handle %d mHalHandle %d device sink %08x",
__func__, handle, patch.mHalHandle,
patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (auto& effect : mDeviceEffects) {
status_t status = effect.second->onCreatePatch(handle, patch);
ALOGV("%s Effect onCreatePatch status %d", __func__, status);
@@ -47,27 +67,27 @@
}
}
-void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
+void DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
ALOGV("%s", __func__);
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (auto& effect : mDeviceEffects) {
effect.second->onReleasePatch(handle);
}
}
-// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
+// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mutex() held
+sp<IAfEffectHandle> DeviceEffectManager::createEffect_l(
effect_descriptor_t *descriptor,
const AudioDeviceTypeAddr& device,
- const sp<AudioFlinger::Client>& client,
+ const sp<Client>& client,
const sp<IEffectClient>& effectClient,
- const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
+ const std::map<audio_patch_handle_t, IAfPatchPanel::Patch>& patches,
int *enabled,
status_t *status,
bool probe,
bool notifyFramesProcessed) {
- sp<DeviceEffectProxy> effect;
- sp<EffectHandle> handle;
+ sp<IAfDeviceEffectProxy> effect;
+ sp<IAfEffectHandle> handle;
status_t lStatus;
lStatus = checkEffectCompatibility(descriptor);
@@ -77,18 +97,19 @@
}
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
auto iter = mDeviceEffects.find(device);
if (iter != mDeviceEffects.end()) {
effect = iter->second;
} else {
- effect = new DeviceEffectProxy(device, mMyCallback,
- descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
+ effect = IAfDeviceEffectProxy::create(device, mMyCallback,
+ descriptor,
+ mAfDeviceEffectManagerCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
notifyFramesProcessed);
}
// create effect handle and connect it to effect module
- handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/,
- notifyFramesProcessed);
+ handle = IAfEffectHandle::create(
+ effect, client, effectClient, 0 /*priority*/, notifyFramesProcessed);
lStatus = handle->initCheck();
if (lStatus == NO_ERROR) {
lStatus = effect->addHandle(handle.get());
@@ -110,7 +131,8 @@
return handle;
}
-status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
+/* static */
+status_t DeviceEffectManager::checkEffectCompatibility(
const effect_descriptor_t *desc) {
const sp<EffectsFactoryHalInterface> effectsFactory =
audioflinger::EffectConfiguration::getEffectsFactoryHal();
@@ -136,7 +158,8 @@
return NO_ERROR;
}
-status_t AudioFlinger::DeviceEffectManager::createEffectHal(
+/* static */
+status_t DeviceEffectManager::createEffectHal(
const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *effect) {
status_t status = NO_INIT;
@@ -149,10 +172,10 @@
return status;
}
-void AudioFlinger::DeviceEffectManager::dump(int fd)
+void DeviceEffectManager::dump(int fd)
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
- const bool locked = dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
if (!locked) {
String8 result("DeviceEffectManager may be deadlocked\n");
write(fd, result.c_str(), result.size());
@@ -165,30 +188,29 @@
outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
write(fd, outStr.c_str(), outStr.size());
- iter.second->dump(fd, 4);
+ iter.second->dump2(fd, 4);
}
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
}
-
-size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<DeviceEffectProxy>& effect)
+size_t DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mDeviceEffects.erase(effect->device());
return mDeviceEffects.size();
}
-bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
- EffectHandle *handle, bool unpinIfLast) {
- sp<EffectBase> effectBase = handle->effect().promote();
+bool DeviceEffectManagerCallback::disconnectEffectHandle(
+ IAfEffectHandle *handle, bool unpinIfLast) {
+ sp<IAfEffectBase> effectBase = handle->effect().promote();
if (effectBase == nullptr) {
return false;
}
- sp<DeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
+ sp<IAfDeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
if (effect == nullptr) {
return false;
}
@@ -203,4 +225,12 @@
return true;
}
+bool DeviceEffectManagerCallback::isAudioPolicyReady() const {
+ return mManager.afDeviceEffectManagerCallback()->isAudioPolicyReady();
+}
+
+int DeviceEffectManagerCallback::newEffectId() const {
+ return mManager.afDeviceEffectManagerCallback()->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
+}
+
} // namespace android
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index b87f830..6a5c889 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -15,61 +15,77 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "IAfEffect.h"
+#include "PatchCommandThread.h"
+
+namespace android {
+
+class IAfDeviceEffectManagerCallback : public virtual RefBase {
+public:
+ virtual bool isAudioPolicyReady() const = 0;
+ virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
+ virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+ virtual status_t addEffectToHal(
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect)
+ EXCLUDES_AudioFlinger_HardwareMutex = 0;
+ virtual status_t removeEffectFromHal(
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect)
+ EXCLUDES_AudioFlinger_HardwareMutex= 0;
+};
+
+class DeviceEffectManagerCallback;
// DeviceEffectManager is concealed within AudioFlinger, their lifetimes are the same.
class DeviceEffectManager : public PatchCommandThread::PatchCommandListener {
public:
- explicit DeviceEffectManager(AudioFlinger& audioFlinger)
- : mAudioFlinger(audioFlinger),
- mMyCallback(new DeviceEffectManagerCallback(*this)) {}
+ explicit DeviceEffectManager(
+ const sp<IAfDeviceEffectManagerCallback>& afDeviceEffectManagerCallback);
- void onFirstRef() override {
- mAudioFlinger.mPatchCommandThread->addListener(this);
- }
+ void onFirstRef() override;
- sp<EffectHandle> createEffect_l(effect_descriptor_t *descriptor,
+ sp<IAfEffectHandle> createEffect_l(effect_descriptor_t *descriptor,
const AudioDeviceTypeAddr& device,
- const sp<AudioFlinger::Client>& client,
+ const sp<Client>& client,
const sp<media::IEffectClient>& effectClient,
- const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
+ const std::map<audio_patch_handle_t, IAfPatchPanel::Patch>& patches,
int *enabled,
status_t *status,
bool probe,
- bool notifyFramesProcessed);
+ bool notifyFramesProcessed) REQUIRES(audio_utils::AudioFlinger_Mutex);
- size_t removeEffect(const sp<DeviceEffectProxy>& effect);
- status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+ size_t removeEffect(const sp<IAfDeviceEffectProxy>& effect);
+ static status_t createEffectHal(const effect_uuid_t *pEffectUuid,
int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *effect);
status_t addEffectToHal(const struct audio_port_config *device,
- const sp<EffectHalInterface>& effect) {
- return mAudioFlinger.addEffectToHal(device, effect);
- };
+ const sp<EffectHalInterface>& effect);
status_t removeEffectFromHal(const struct audio_port_config *device,
- const sp<EffectHalInterface>& effect) {
- return mAudioFlinger.removeEffectFromHal(device, effect);
- };
+ const sp<EffectHalInterface>& effect);
- AudioFlinger& audioFlinger() const { return mAudioFlinger; }
+ const auto& afDeviceEffectManagerCallback() const { return mAfDeviceEffectManagerCallback; }
void dump(int fd);
// PatchCommandThread::PatchCommandListener implementation
void onCreateAudioPatch(audio_patch_handle_t handle,
- const PatchPanel::Patch& patch) override;
- void onReleaseAudioPatch(audio_patch_handle_t handle) override;
+ const IAfPatchPanel::Patch& patch) final
+ EXCLUDES_DeviceEffectManager_Mutex;
+ void onReleaseAudioPatch(audio_patch_handle_t handle) final
+ EXCLUDES_DeviceEffectManager_Mutex;
private:
- status_t checkEffectCompatibility(const effect_descriptor_t *desc);
+ static status_t checkEffectCompatibility(const effect_descriptor_t *desc);
- Mutex mLock;
- AudioFlinger &mAudioFlinger;
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::DeviceEffectManager_Mutex) {
+ return mMutex;
+ }
+ mutable audio_utils::mutex mMutex;
+ const sp<IAfDeviceEffectManagerCallback> mAfDeviceEffectManagerCallback;
const sp<DeviceEffectManagerCallback> mMyCallback;
- std::map<AudioDeviceTypeAddr, sp<DeviceEffectProxy>> mDeviceEffects;
+ std::map<AudioDeviceTypeAddr, sp<IAfDeviceEffectProxy>> mDeviceEffects GUARDED_BY(mutex());
};
class DeviceEffectManagerCallback : public EffectCallbackInterface {
@@ -78,59 +94,58 @@
: mManager(manager) {}
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
- int32_t sessionId, int32_t deviceId,
- sp<EffectHalInterface> *effect) override {
+ int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) final {
return mManager.createEffectHal(pEffectUuid, sessionId, deviceId, effect);
}
status_t allocateHalBuffer(size_t size __unused,
- sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
- bool updateOrphanEffectChains(const sp<EffectBase>& effect __unused) override { return false; }
+ sp<EffectBufferHalInterface>* buffer __unused) final { return NO_ERROR; }
+ bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) final {
+ return false;
+ }
- audio_io_handle_t io() const override { return AUDIO_IO_HANDLE_NONE; }
- bool isOutput() const override { return false; }
- bool isOffload() const override { return false; }
- bool isOffloadOrDirect() const override { return false; }
- bool isOffloadOrMmap() const override { return false; }
- bool isSpatializer() const override { return false; }
+ audio_io_handle_t io() const final { return AUDIO_IO_HANDLE_NONE; }
+ bool isOutput() const final { return false; }
+ bool isOffload() const final { return false; }
+ bool isOffloadOrDirect() const final { return false; }
+ bool isOffloadOrMmap() const final { return false; }
+ bool isSpatializer() const final { return false; }
- uint32_t sampleRate() const override { return 0; }
- audio_channel_mask_t inChannelMask(int id __unused) const override {
+ uint32_t sampleRate() const final { return 0; }
+ audio_channel_mask_t inChannelMask(int id __unused) const final {
return AUDIO_CHANNEL_NONE;
}
- uint32_t inChannelCount(int id __unused) const override { return 0; }
- audio_channel_mask_t outChannelMask() const override { return AUDIO_CHANNEL_NONE; }
- uint32_t outChannelCount() const override { return 0; }
+ uint32_t inChannelCount(int id __unused) const final { return 0; }
+ audio_channel_mask_t outChannelMask() const final { return AUDIO_CHANNEL_NONE; }
+ uint32_t outChannelCount() const final { return 0; }
- audio_channel_mask_t hapticChannelMask() const override { return AUDIO_CHANNEL_NONE; }
- size_t frameCount() const override { return 0; }
- uint32_t latency() const override { return 0; }
+ audio_channel_mask_t hapticChannelMask() const final { return AUDIO_CHANNEL_NONE; }
+ size_t frameCount() const final { return 0; }
+ uint32_t latency() const final { return 0; }
- status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) override {
+ status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) final {
return NO_ERROR;
}
- status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) override {
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) final {
return NO_ERROR;
}
- bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
- void setVolumeForOutput(float left __unused, float right __unused) const override {}
+ bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) final;
+ void setVolumeForOutput(float left __unused, float right __unused) const final {}
// check if effects should be suspended or restored when a given effect is enable or disabled
- void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect __unused,
- bool enabled __unused, bool threadLocked __unused) override {}
- void resetVolume() override {}
- product_strategy_t strategy() const override { return static_cast<product_strategy_t>(0); }
- int32_t activeTrackCnt() const override { return 0; }
- void onEffectEnable(const sp<EffectBase>& effect __unused) override {}
- void onEffectDisable(const sp<EffectBase>& effect __unused) override {}
+ void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect __unused,
+ bool enabled __unused, bool threadLocked __unused) final {}
+ void resetVolume() final {}
+ product_strategy_t strategy() const final { return static_cast<product_strategy_t>(0); }
+ int32_t activeTrackCnt() const final { return 0; }
+ void onEffectEnable(const sp<IAfEffectBase>& effect __unused) final {}
+ void onEffectDisable(const sp<IAfEffectBase>& effect __unused) final {}
- wp<EffectChain> chain() const override { return nullptr; }
+ wp<IAfEffectChain> chain() const final { return nullptr; }
- bool isAudioPolicyReady() const override {
- return mManager.audioFlinger().isAudioPolicyReady();
- }
+ bool isAudioPolicyReady() const final;
- int newEffectId() { return mManager.audioFlinger().nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT); }
+ int newEffectId() const;
status_t addEffectToHal(const struct audio_port_config *device,
const sp<EffectHalInterface>& effect) {
@@ -143,3 +158,5 @@
private:
DeviceEffectManager& mManager;
};
+
+} // namespace android
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 081d9a9..0f3e130 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -19,10 +19,25 @@
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
-#include <algorithm>
+#include "Effects.h"
-#include "Configuration.h"
-#include <utils/Log.h>
+#include "Client.h"
+#include "EffectConfiguration.h"
+
+#include <afutils/DumpTryLock.h>
+#include <audio_utils/channels.h>
+#include <audio_utils/primitives.h>
+#include <media/AudioCommonTypes.h>
+#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
+#include <media/AudioEffect.h>
+#include <media/ShmemCompat.h>
+#include <media/TypeConverter.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <mediautils/MethodStatistics.h>
+#include <mediautils/ServiceUtilities.h>
+#include <mediautils/TimeCheck.h>
#include <system/audio_effects/effect_aec.h>
#include <system/audio_effects/effect_downmix.h>
#include <system/audio_effects/effect_dynamicsprocessing.h>
@@ -30,21 +45,9 @@
#include <system/audio_effects/effect_ns.h>
#include <system/audio_effects/effect_spatializer.h>
#include <system/audio_effects/effect_visualizer.h>
-#include <audio_utils/channels.h>
-#include <audio_utils/primitives.h>
-#include <media/AudioCommonTypes.h>
-#include <media/AudioContainers.h>
-#include <media/AudioEffect.h>
-#include <media/AudioDeviceTypeAddr.h>
-#include <media/ShmemCompat.h>
-#include <media/audiohal/EffectHalInterface.h>
-#include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <mediautils/MethodStatistics.h>
-#include <mediautils/ServiceUtilities.h>
-#include <mediautils/TimeCheck.h>
+#include <utils/Log.h>
-#include "AudioFlinger.h"
-#include "EffectConfiguration.h"
+#include <algorithm>
// ----------------------------------------------------------------------------
@@ -93,9 +96,9 @@
// ----------------------------------------------------------------------------
#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectBase"
+#define LOG_TAG "EffectBase"
-AudioFlinger::EffectBase::EffectBase(const sp<AudioFlinger::EffectCallbackInterface>& callback,
+EffectBase::EffectBase(const sp<EffectCallbackInterface>& callback,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
@@ -106,8 +109,8 @@
{
}
-// must be called with EffectModule::mLock held
-status_t AudioFlinger::EffectBase::setEnabled_l(bool enabled)
+// must be called with EffectModule::mutex() held
+status_t EffectBase::setEnabled_l(bool enabled)
{
ALOGV("setEnabled %p enabled %d", this, enabled);
@@ -139,7 +142,7 @@
return NO_ERROR; // simply ignore as we are being destroyed
}
for (size_t i = 1; i < mHandles.size(); i++) {
- EffectHandle *h = mHandles[i];
+ IAfEffectHandle *h = mHandles[i];
if (h != NULL && !h->disconnected()) {
h->setEnabled(enabled);
}
@@ -148,11 +151,11 @@
return NO_ERROR;
}
-status_t AudioFlinger::EffectBase::setEnabled(bool enabled, bool fromHandle)
+status_t EffectBase::setEnabled(bool enabled, bool fromHandle)
{
status_t status;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
status = setEnabled_l(enabled);
}
if (fromHandle) {
@@ -169,7 +172,7 @@
return status;
}
-bool AudioFlinger::EffectBase::isEnabled() const
+bool EffectBase::isEnabled() const
{
switch (mState) {
case RESTART:
@@ -185,29 +188,29 @@
}
}
-void AudioFlinger::EffectBase::setSuspended(bool suspended)
+void EffectBase::setSuspended(bool suspended)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mSuspended = suspended;
}
-bool AudioFlinger::EffectBase::suspended() const
+bool EffectBase::suspended() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mSuspended;
}
-status_t AudioFlinger::EffectBase::addHandle(EffectHandle *handle)
+status_t EffectBase::addHandle(IAfEffectHandle *handle)
{
status_t status;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
int priority = handle->priority();
size_t size = mHandles.size();
- EffectHandle *controlHandle = NULL;
+ IAfEffectHandle *controlHandle = nullptr;
size_t i;
for (i = 0; i < size; i++) {
- EffectHandle *h = mHandles[i];
+ IAfEffectHandle *h = mHandles[i];
if (h == NULL || h->disconnected()) {
continue;
}
@@ -236,7 +239,7 @@
return status;
}
-status_t AudioFlinger::EffectBase::updatePolicyState()
+status_t EffectBase::updatePolicyState()
{
status_t status = NO_ERROR;
bool doRegister = false;
@@ -247,7 +250,7 @@
product_strategy_t strategy = PRODUCT_STRATEGY_NONE;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if ((isInternal_l() && !mPolicyRegistered)
|| !getCallback()->isAudioPolicyReady()) {
@@ -266,7 +269,7 @@
}
// enable effect when registered according to enable state requested by controlling handle
if (mHandles.size() > 0) {
- EffectHandle *handle = controlHandle_l();
+ IAfEffectHandle *handle = controlHandle_l();
if (handle != nullptr && mPolicyEnabled != handle->enabled()) {
doEnable = true;
mPolicyEnabled = handle->enabled();
@@ -281,7 +284,7 @@
return NO_ERROR;
}
}
- mPolicyLock.lock();
+ policyMutex().lock();
ALOGV("%s name %s id %d session %d doRegister %d registered %d doEnable %d enabled %d",
__func__, mDescriptor.name, mId, mSessionId, doRegister, registered, doEnable, enabled);
if (doRegister) {
@@ -299,19 +302,19 @@
if (registered && doEnable) {
status = AudioSystem::setEffectEnabled(mId, enabled);
}
- mPolicyLock.unlock();
+ policyMutex().unlock();
return status;
}
-ssize_t AudioFlinger::EffectBase::removeHandle(EffectHandle *handle)
+ssize_t EffectBase::removeHandle(IAfEffectHandle *handle)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return removeHandle_l(handle);
}
-ssize_t AudioFlinger::EffectBase::removeHandle_l(EffectHandle *handle)
+ssize_t EffectBase::removeHandle_l(IAfEffectHandle *handle)
{
size_t size = mHandles.size();
size_t i;
@@ -329,7 +332,7 @@
mHandles.removeAt(i);
// if removed from first place, move effect control from this handle to next in line
if (i == 0) {
- EffectHandle *h = controlHandle_l();
+ IAfEffectHandle *h = controlHandle_l();
if (h != NULL) {
h->setControl(true /*hasControl*/, true /*signal*/ , handle->enabled() /*enabled*/);
}
@@ -345,12 +348,12 @@
return mHandles.size();
}
-// must be called with EffectModule::mLock held
-AudioFlinger::EffectHandle *AudioFlinger::EffectBase::controlHandle_l()
+// must be called with EffectModule::mutex() held
+IAfEffectHandle *EffectBase::controlHandle_l()
{
// the first valid handle in the list has control over the module
for (size_t i = 0; i < mHandles.size(); i++) {
- EffectHandle *h = mHandles[i];
+ IAfEffectHandle *h = mHandles[i];
if (h != NULL && !h->disconnected()) {
return h;
}
@@ -360,7 +363,7 @@
}
// unsafe method called when the effect parent thread has been destroyed
-ssize_t AudioFlinger::EffectBase::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
+ssize_t EffectBase::disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast)
{
const auto callback = getCallback();
ALOGV("disconnect() %p handle %p", this, handle);
@@ -368,21 +371,21 @@
return mHandles.size();
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ssize_t numHandles = removeHandle_l(handle);
if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
- mLock.unlock();
+ mutex().unlock();
callback->updateOrphanEffectChains(this);
- mLock.lock();
+ mutex().lock();
}
return numHandles;
}
-bool AudioFlinger::EffectBase::purgeHandles()
+bool EffectBase::purgeHandles()
{
bool enabled = false;
- Mutex::Autolock _l(mLock);
- EffectHandle *handle = controlHandle_l();
+ audio_utils::lock_guard _l(mutex());
+ IAfEffectHandle *handle = controlHandle_l();
if (handle != NULL) {
enabled = handle->enabled();
}
@@ -390,7 +393,7 @@
return enabled;
}
-void AudioFlinger::EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
+void EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
getCallback()->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
}
@@ -499,14 +502,14 @@
return s;
}
-void AudioFlinger::EffectBase::dump(int fd, const Vector<String16>& args __unused)
+void EffectBase::dump(int fd, const Vector<String16>& args __unused) const
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
String8 result;
result.appendFormat("\tEffect ID %d:\n", mId);
- bool locked = AudioFlinger::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
result.append("\t\tCould not lock Fx mutex:\n");
@@ -537,14 +540,14 @@
result.append("\t\t\t Pid Priority Ctrl Locked client server\n");
char buffer[256];
for (size_t i = 0; i < mHandles.size(); ++i) {
- EffectHandle *handle = mHandles[i];
+ IAfEffectHandle *handle = mHandles[i];
if (handle != NULL && !handle->disconnected()) {
handle->dumpToBuffer(buffer, sizeof(buffer));
result.append(buffer);
}
}
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
write(fd, result.c_str(), result.length());
@@ -555,9 +558,9 @@
// ----------------------------------------------------------------------------
#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectModule"
+#define LOG_TAG "EffectModule"
-AudioFlinger::EffectModule::EffectModule(const sp<AudioFlinger::EffectCallbackInterface>& callback,
+EffectModule::EffectModule(const sp<EffectCallbackInterface>& callback,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
@@ -599,7 +602,7 @@
ALOGV("Constructor Error %d", mStatus);
}
-AudioFlinger::EffectModule::~EffectModule()
+EffectModule::~EffectModule()
{
ALOGV("Destructor %p", this);
if (mEffectInterface != 0) {
@@ -612,8 +615,8 @@
}
-bool AudioFlinger::EffectModule::updateState() {
- Mutex::Autolock _l(mLock);
+bool EffectModule::updateState() {
+ audio_utils::lock_guard _l(mutex());
bool started = false;
switch (mState) {
@@ -667,9 +670,9 @@
return started;
}
-void AudioFlinger::EffectModule::process()
+void EffectModule::process()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mState == DESTROYED || mEffectInterface == 0 || mInBuffer == 0 || mOutBuffer == 0) {
return;
@@ -821,7 +824,7 @@
}
}
-void AudioFlinger::EffectModule::reset_l()
+void EffectModule::reset_l()
{
if (mStatus != NO_ERROR || mEffectInterface == 0) {
return;
@@ -832,7 +835,7 @@
mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, &replySize, &reply);
}
-status_t AudioFlinger::EffectModule::configure()
+status_t EffectModule::configure()
{
ALOGVV("configure() started");
status_t status;
@@ -1011,9 +1014,9 @@
return status;
}
-status_t AudioFlinger::EffectModule::init()
+status_t EffectModule::init()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mEffectInterface == 0) {
return NO_INIT;
}
@@ -1030,7 +1033,7 @@
return status;
}
-void AudioFlinger::EffectModule::addEffectToHal_l()
+void EffectModule::addEffectToHal_l()
{
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
@@ -1043,12 +1046,12 @@
}
}
-// start() must be called with PlaybackThread::mLock or EffectChain::mLock held
-status_t AudioFlinger::EffectModule::start()
+// start() must be called with PlaybackThread::mutex() or EffectChain::mutex() held
+status_t EffectModule::start()
{
status_t status;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
status = start_l();
}
if (status == NO_ERROR) {
@@ -1057,7 +1060,7 @@
return status;
}
-status_t AudioFlinger::EffectModule::start_l()
+status_t EffectModule::start_l()
{
if (mEffectInterface == 0) {
return NO_INIT;
@@ -1081,13 +1084,13 @@
return status;
}
-status_t AudioFlinger::EffectModule::stop()
+status_t EffectModule::stop()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return stop_l();
}
-status_t AudioFlinger::EffectModule::stop_l()
+status_t EffectModule::stop_l()
{
if (mEffectInterface == 0) {
return NO_INIT;
@@ -1120,8 +1123,8 @@
return status;
}
-// must be called with EffectChain::mLock held
-void AudioFlinger::EffectModule::release_l()
+// must be called with EffectChain::mutex() held
+void EffectModule::release_l()
{
if (mEffectInterface != 0) {
removeEffectFromHal_l();
@@ -1131,7 +1134,7 @@
}
}
-status_t AudioFlinger::EffectModule::removeEffectFromHal_l()
+status_t EffectModule::removeEffectFromHal_l()
{
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
@@ -1151,12 +1154,12 @@
return remainder == 0 ? 0 : divisor - remainder;
}
-status_t AudioFlinger::EffectModule::command(int32_t cmdCode,
+status_t EffectModule::command(int32_t cmdCode,
const std::vector<uint8_t>& cmdData,
int32_t maxReplySize,
std::vector<uint8_t>* reply)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());
if (mState == DESTROYED || mEffectInterface == 0) {
@@ -1224,7 +1227,7 @@
reply->resize(status == NO_ERROR ? replySize : 0);
if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
for (size_t i = 1; i < mHandles.size(); i++) {
- EffectHandle *h = mHandles[i];
+ IAfEffectHandle *h = mHandles[i];
if (h != NULL && !h->disconnected()) {
h->commandExecuted(cmdCode, cmdData, *reply);
}
@@ -1233,7 +1236,7 @@
return status;
}
-bool AudioFlinger::EffectModule::isProcessEnabled() const
+bool EffectModule::isProcessEnabled() const
{
if (mStatus != NO_ERROR) {
return false;
@@ -1253,17 +1256,17 @@
}
}
-bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
+bool EffectModule::isOffloadedOrDirect() const
{
return getCallback()->isOffloadOrDirect();
}
-bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
+bool EffectModule::isVolumeControlEnabled() const
{
return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled()));
}
-void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+void EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
ALOGVV("setInBuffer %p",(&buffer));
// mConfig.inputCfg.buffer.frameCount may be zero if configure() is not called yet.
@@ -1309,7 +1312,7 @@
}
}
-void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+void EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
ALOGVV("setOutBuffer %p",(&buffer));
// mConfig.outputCfg.buffer.frameCount may be zero if configure() is not called yet.
@@ -1351,9 +1354,9 @@
}
}
-status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
+status_t EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
{
- AutoLockReentrant _l(mLock, mSetVolumeReentrantTid);
+ AutoLockReentrant _l(mutex(), mSetVolumeReentrantTid);
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1369,7 +1372,7 @@
return status;
}
-status_t AudioFlinger::EffectModule::setVolumeInternal(
+status_t EffectModule::setVolumeInternal(
uint32_t *left, uint32_t *right, bool controller) {
uint32_t volume[2] = {*left, *right};
uint32_t *pVolume = controller ? volume : nullptr;
@@ -1386,7 +1389,7 @@
return status;
}
-void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
+void EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
{
// for offload or direct thread, if the effect chain has non-offloadable
// effect and any effect module within the chain has volume control, then
@@ -1399,7 +1402,7 @@
}
}
-status_t AudioFlinger::EffectModule::sendSetAudioDevicesCommand(
+status_t EffectModule::sendSetAudioDevicesCommand(
const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode)
{
audio_devices_t deviceType = deviceTypesToBitMask(getAudioDeviceTypes(devices));
@@ -1407,7 +1410,7 @@
return NO_ERROR;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1425,19 +1428,19 @@
return status;
}
-status_t AudioFlinger::EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
+status_t EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
{
return sendSetAudioDevicesCommand(devices, EFFECT_CMD_SET_DEVICE);
}
-status_t AudioFlinger::EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
+status_t EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
{
return sendSetAudioDevicesCommand({device}, EFFECT_CMD_SET_INPUT_DEVICE);
}
-status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
+status_t EffectModule::setMode(audio_mode_t mode)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1457,9 +1460,9 @@
return status;
}
-status_t AudioFlinger::EffectModule::setAudioSource(audio_source_t source)
+status_t EffectModule::setAudioSource(audio_source_t source)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1475,9 +1478,9 @@
return status;
}
-status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
+status_t EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1508,22 +1511,22 @@
return status;
}
-bool AudioFlinger::EffectModule::isOffloaded() const
+bool EffectModule::isOffloaded() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mOffloaded;
}
/*static*/
-bool AudioFlinger::EffectModule::isHapticGenerator(const effect_uuid_t *type) {
+bool IAfEffectModule::isHapticGenerator(const effect_uuid_t *type) {
return memcmp(type, FX_IID_HAPTICGENERATOR, sizeof(effect_uuid_t)) == 0;
}
-bool AudioFlinger::EffectModule::isHapticGenerator() const {
- return isHapticGenerator(&mDescriptor.type);
+bool EffectModule::isHapticGenerator() const {
+ return IAfEffectModule::isHapticGenerator(&mDescriptor.type);
}
-status_t AudioFlinger::EffectModule::setHapticIntensity(int id, os::HapticScale intensity)
+status_t EffectModule::setHapticIntensity(int id, os::HapticScale intensity)
{
if (mStatus != NO_ERROR) {
return mStatus;
@@ -1549,7 +1552,7 @@
return status;
}
-status_t AudioFlinger::EffectModule::setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo)
+status_t EffectModule::setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo)
{
if (mStatus != NO_ERROR) {
return mStatus;
@@ -1579,9 +1582,9 @@
return status;
}
-status_t AudioFlinger::EffectModule::getConfigs(
+status_t EffectModule::getConfigs(
audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, bool* isOutput) const {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mConfig.inputCfg.mask == 0 || mConfig.outputCfg.mask == 0) {
return NO_INIT;
}
@@ -1610,13 +1613,13 @@
return ss.str();
}
-void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
+void EffectModule::dump(int fd, const Vector<String16>& args) const
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
EffectBase::dump(fd, args);
String8 result;
- bool locked = AudioFlinger::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
result.append("\t\tStatus Engine:\n");
result.appendFormat("\t\t%03d %p\n",
@@ -1632,7 +1635,7 @@
mConfig.inputCfg.samplingRate,
mConfig.inputCfg.channels,
mConfig.inputCfg.format,
- formatToString((audio_format_t)mConfig.inputCfg.format).c_str());
+ toString(static_cast<audio_format_t>(mConfig.inputCfg.format)).c_str());
result.append("\t\t- Output configuration:\n");
result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
@@ -1642,7 +1645,7 @@
mConfig.outputCfg.samplingRate,
mConfig.outputCfg.channels,
mConfig.outputCfg.format,
- formatToString((audio_format_t)mConfig.outputCfg.format).c_str());
+ toString(static_cast<audio_format_t>(mConfig.outputCfg.format)).c_str());
result.appendFormat("\t\t- HAL buffers:\n"
"\t\t\tIn(%s) InConversion(%s) Out(%s) OutConversion(%s)\n",
@@ -1659,7 +1662,7 @@
}
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
}
@@ -1668,10 +1671,21 @@
// ----------------------------------------------------------------------------
#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectHandle"
+#define LOG_TAG "EffectHandle"
-AudioFlinger::EffectHandle::EffectHandle(const sp<EffectBase>& effect,
- const sp<AudioFlinger::Client>& client,
+/* static */
+sp<IAfEffectHandle> IAfEffectHandle::create(
+ const sp<IAfEffectBase>& effect,
+ const sp<Client>& client,
+ const sp<media::IEffectClient>& effectClient,
+ int32_t priority, bool notifyFramesProcessed)
+{
+ return sp<EffectHandle>::make(
+ effect, client, effectClient, priority, notifyFramesProcessed);
+}
+
+EffectHandle::EffectHandle(const sp<IAfEffectBase>& effect,
+ const sp<Client>& client,
const sp<media::IEffectClient>& effectClient,
int32_t priority, bool notifyFramesProcessed)
: BnEffect(),
@@ -1705,7 +1719,7 @@
mBuffer = (uint8_t *)mCblk + bufOffset;
}
-AudioFlinger::EffectHandle::~EffectHandle()
+EffectHandle::~EffectHandle()
{
ALOGV("Destructor %p", this);
disconnect(false);
@@ -1738,7 +1752,7 @@
return methodStatistics;
}
-status_t AudioFlinger::EffectHandle::onTransact(
+status_t EffectHandle::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
const std::string methodName = getIEffectStatistics().getMethodForCode(code);
mediautils::TimeCheck check(
@@ -1753,7 +1767,7 @@
return BnEffect::onTransact(code, data, reply, flags);
}
-status_t AudioFlinger::EffectHandle::initCheck()
+status_t EffectHandle::initCheck() const
{
return mClient == 0 || mCblkMemory != 0 ? OK : NO_MEMORY;
}
@@ -1769,11 +1783,11 @@
std::move(_tmp.value()); \
})
-Status AudioFlinger::EffectHandle::enable(int32_t* _aidl_return)
+Status EffectHandle::enable(int32_t* _aidl_return)
{
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGV("enable %p", this);
- sp<EffectBase> effect = mEffect.promote();
+ sp<IAfEffectBase> effect = mEffect.promote();
if (effect == 0 || mDisconnected) {
RETURN(DEAD_OBJECT);
}
@@ -1807,11 +1821,11 @@
RETURN(status);
}
-Status AudioFlinger::EffectHandle::disable(int32_t* _aidl_return)
+Status EffectHandle::disable(int32_t* _aidl_return)
{
ALOGV("disable %p", this);
- AutoMutex _l(mLock);
- sp<EffectBase> effect = mEffect.promote();
+ audio_utils::lock_guard _l(mutex());
+ sp<IAfEffectBase> effect = mEffect.promote();
if (effect == 0 || mDisconnected) {
RETURN(DEAD_OBJECT);
}
@@ -1834,16 +1848,16 @@
RETURN(status);
}
-Status AudioFlinger::EffectHandle::disconnect()
+Status EffectHandle::disconnect()
{
ALOGV("%s %p", __FUNCTION__, this);
disconnect(true);
return Status::ok();
}
-void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
+void EffectHandle::disconnect(bool unpinIfLast)
{
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
if (mDisconnected) {
if (unpinIfLast) {
@@ -1853,7 +1867,7 @@
}
mDisconnected = true;
{
- sp<EffectBase> effect = mEffect.promote();
+ sp<IAfEffectBase> effect = mEffect.promote();
if (effect != 0) {
if (effect->disconnectHandle(this, unpinIfLast) > 0) {
ALOGW("%s Effect handle %p disconnected after thread destruction",
@@ -1870,24 +1884,24 @@
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
// Client destructor must run with AudioFlinger client mutex locked
- Mutex::Autolock _l2(mClient->audioFlinger()->mClientLock);
+ audio_utils::lock_guard _l2(mClient->afClientCallback()->clientMutex());
mClient.clear();
}
}
-Status AudioFlinger::EffectHandle::getCblk(media::SharedFileRegion* _aidl_return) {
+Status EffectHandle::getCblk(media::SharedFileRegion* _aidl_return) {
LOG_ALWAYS_FATAL_IF(!convertIMemoryToSharedFileRegion(mCblkMemory, _aidl_return));
return Status::ok();
}
-Status AudioFlinger::EffectHandle::getConfig(
+Status EffectHandle::getConfig(
media::EffectConfig* _config, int32_t* _aidl_return) {
- AutoMutex _l(mLock);
- sp<EffectBase> effect = mEffect.promote();
+ audio_utils::lock_guard _l(mutex());
+ sp<IAfEffectBase> effect = mEffect.promote();
if (effect == nullptr || mDisconnected) {
RETURN(DEAD_OBJECT);
}
- sp<EffectModule> effectModule = effect->asEffectModule();
+ sp<IAfEffectModule> effectModule = effect->asEffectModule();
if (effectModule == nullptr) {
RETURN(INVALID_OPERATION);
}
@@ -1906,7 +1920,7 @@
RETURN(status);
}
-Status AudioFlinger::EffectHandle::command(int32_t cmdCode,
+Status EffectHandle::command(int32_t cmdCode,
const std::vector<uint8_t>& cmdData,
int32_t maxResponseSize,
std::vector<uint8_t>* response,
@@ -1949,8 +1963,8 @@
return disable(_aidl_return);
}
- AutoMutex _l(mLock);
- sp<EffectBase> effect = mEffect.promote();
+ audio_utils::lock_guard _l(mutex());
+ sp<IAfEffectBase> effect = mEffect.promote();
if (effect == 0 || mDisconnected) {
RETURN(DEAD_OBJECT);
}
@@ -2039,7 +2053,7 @@
RETURN(status);
}
-void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
+void EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
{
ALOGV("setControl %p control %d", this, hasControl);
@@ -2051,7 +2065,7 @@
}
}
-void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
+void EffectHandle::commandExecuted(uint32_t cmdCode,
const std::vector<uint8_t>& cmdData,
const std::vector<uint8_t>& replyData)
{
@@ -2062,24 +2076,24 @@
-void AudioFlinger::EffectHandle::setEnabled(bool enabled)
+void EffectHandle::setEnabled(bool enabled)
{
if (mEffectClient != 0) {
mEffectClient->enableStatusChanged(enabled);
}
}
-void AudioFlinger::EffectHandle::framesProcessed(int32_t frames) const
+void EffectHandle::framesProcessed(int32_t frames) const
{
if (mEffectClient != 0 && mNotifyFramesProcessed) {
mEffectClient->framesProcessed(frames);
}
}
-void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
+void EffectHandle::dumpToBuffer(char* buffer, size_t size) const
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
- bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
+ const bool locked = mCblk != nullptr && afutils::dumpTryLock(mCblk->lock);
snprintf(buffer, size, "\t\t\t%5d %5d %3s %3s %5u %5u\n",
(mClient == 0) ? getpid() : mClient->pid(),
@@ -2096,31 +2110,31 @@
}
#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectChain"
+#define LOG_TAG "EffectChain"
-AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread,
+/* static */
+sp<IAfEffectChain> IAfEffectChain::create(
+ const sp<IAfThreadBase>& thread,
+ audio_session_t sessionId)
+{
+ return sp<EffectChain>::make(thread, sessionId);
+}
+
+EffectChain::EffectChain(const sp<IAfThreadBase>& thread,
audio_session_t sessionId)
: mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
{
- sp<ThreadBase> p = thread.promote();
- if (p == nullptr) {
- return;
- }
- mStrategy = p->getStrategyForStream(AUDIO_STREAM_MUSIC);
- mMaxTailBuffers = ((kProcessTailDurationMs * p->sampleRate()) / 1000) /
- p->frameCount();
+ mStrategy = thread->getStrategyForStream(AUDIO_STREAM_MUSIC);
+ mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
+ thread->frameCount();
}
-AudioFlinger::EffectChain::~EffectChain()
-{
-}
-
-// getEffectFromDesc_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(
- effect_descriptor_t *descriptor)
+// getEffectFromDesc_l() must be called with IAfThreadBase::mutex() held
+sp<IAfEffectModule> EffectChain::getEffectFromDesc_l(
+ effect_descriptor_t *descriptor) const
{
size_t size = mEffects.size();
@@ -2132,8 +2146,8 @@
return 0;
}
-// getEffectFromId_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
+// getEffectFromId_l() must be called with IAfThreadBase::mutex() held
+sp<IAfEffectModule> EffectChain::getEffectFromId_l(int id) const
{
size_t size = mEffects.size();
@@ -2146,9 +2160,9 @@
return 0;
}
-// getEffectFromType_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
- const effect_uuid_t *type)
+// getEffectFromType_l() must be called with IAfThreadBase::mutex() held
+sp<IAfEffectModule> EffectChain::getEffectFromType_l(
+ const effect_uuid_t *type) const
{
size_t size = mEffects.size();
@@ -2160,24 +2174,24 @@
return 0;
}
-std::vector<int> AudioFlinger::EffectChain::getEffectIds()
+std::vector<int> EffectChain::getEffectIds() const
{
std::vector<int> ids;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); i++) {
ids.push_back(mEffects[i]->id());
}
return ids;
}
-void AudioFlinger::EffectChain::clearInputBuffer()
+void EffectChain::clearInputBuffer()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
clearInputBuffer_l();
}
-// Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::clearInputBuffer_l()
+// Must be called with EffectChain::mutex() locked
+void EffectChain::clearInputBuffer_l()
{
if (mInBuffer == NULL) {
return;
@@ -2189,8 +2203,8 @@
mInBuffer->commit();
}
-// Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::process_l()
+// Must be called with EffectChain::mutex() locked
+void EffectChain::process_l()
{
// never process effects when:
// - on an OFFLOAD thread
@@ -2241,14 +2255,14 @@
}
}
-// createEffect_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect,
+// createEffect_l() must be called with IAfThreadBase::mutex() held
+status_t EffectChain::createEffect_l(sp<IAfEffectModule>& effect,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
bool pinned)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned, AUDIO_PORT_HANDLE_NONE);
status_t lStatus = effect->status();
if (lStatus == NO_ERROR) {
@@ -2260,14 +2274,14 @@
return lStatus;
}
-// addEffect_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
+// addEffect_l() must be called with IAfThreadBase::mutex() held
+status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return addEffect_ll(effect);
}
-// addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held
-status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
+// addEffect_l() must be called with IAfThreadBase::mutex() and EffectChain::mutex() held
+status_t EffectChain::addEffect_ll(const sp<IAfEffectModule>& effect)
{
effect->setCallback(mEffectCallback);
@@ -2347,7 +2361,7 @@
return NO_ERROR;
}
-std::optional<size_t> AudioFlinger::EffectChain::findVolumeControl_l(size_t from, size_t to) const {
+std::optional<size_t> EffectChain::findVolumeControl_l(size_t from, size_t to) const {
for (size_t i = std::min(to, mEffects.size()); i > from; i--) {
if (mEffects[i - 1]->isVolumeControlEnabled()) {
return i - 1;
@@ -2356,7 +2370,7 @@
return std::nullopt;
}
-ssize_t AudioFlinger::EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
+ssize_t EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
// Insert effects are inserted at the end of mEffects vector as they are processed
// after track and auxiliary effects.
// Insert effect order as a function of indicated preference:
@@ -2429,11 +2443,11 @@
return idx_insert;
}
-// removeEffect_l() must be called with ThreadBase::mLock held
-size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect,
+// removeEffect_l() must be called with IAfThreadBase::mutex() held
+size_t EffectChain::removeEffect_l(const sp<IAfEffectModule>& effect,
bool release)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
@@ -2477,8 +2491,8 @@
return mEffects.size();
}
-// setDevices_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
+// setDevices_l() must be called with IAfThreadBase::mutex() held
+void EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
{
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -2486,8 +2500,8 @@
}
}
-// setInputDevice_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
+// setInputDevice_l() must be called with IAfThreadBase::mutex() held
+void EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
{
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -2495,8 +2509,8 @@
}
}
-// setMode_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
+// setMode_l() must be called with IAfThreadBase::mutex() held
+void EffectChain::setMode_l(audio_mode_t mode)
{
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -2504,8 +2518,8 @@
}
}
-// setAudioSource_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
+// setAudioSource_l() must be called with IAfThreadBase::mutex() held
+void EffectChain::setAudioSource_l(audio_source_t source)
{
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -2513,15 +2527,15 @@
}
}
-bool AudioFlinger::EffectChain::hasVolumeControlEnabled_l() const {
+bool EffectChain::hasVolumeControlEnabled_l() const {
for (const auto &effect : mEffects) {
if (effect->isVolumeControlEnabled()) return true;
}
return false;
}
-// setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
-bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
+// setVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mutex() held
+bool EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
{
uint32_t newLeft = *left;
uint32_t newRight = *right;
@@ -2530,9 +2544,9 @@
// first update volume controller
const auto volumeControlIndex = findVolumeControl_l(0, size);
const int ctrlIdx = volumeControlIndex.value_or(-1);
- const sp<EffectModule> volumeControlEffect =
+ const sp<IAfEffectModule> volumeControlEffect =
volumeControlIndex.has_value() ? mEffects[ctrlIdx] : nullptr;
- const sp<EffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote();
+ const sp<IAfEffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote();
if (!force && volumeControlEffect == cachedVolumeControlEffect &&
*left == mLeftVolume && *right == mRightVolume) {
@@ -2596,8 +2610,8 @@
return volumeControlIndex.has_value();
}
-// resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
-void AudioFlinger::EffectChain::resetVolume_l()
+// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mutex() held
+void EffectChain::resetVolume_l()
{
if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
uint32_t left = mLeftVolume;
@@ -2606,8 +2620,9 @@
}
}
-// containsHapticGeneratingEffect_l must be called with ThreadBase::mLock or EffectChain::mLock held
-bool AudioFlinger::EffectChain::containsHapticGeneratingEffect_l()
+// containsHapticGeneratingEffect_l must be called with
+// IAfThreadBase::mutex() or EffectChain::mutex() held
+bool EffectChain::containsHapticGeneratingEffect_l()
{
for (size_t i = 0; i < mEffects.size(); ++i) {
if (mEffects[i]->isHapticGenerator()) {
@@ -2617,17 +2632,17 @@
return false;
}
-void AudioFlinger::EffectChain::setHapticIntensity_l(int id, os::HapticScale intensity)
+void EffectChain::setHapticIntensity_l(int id, os::HapticScale intensity)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); ++i) {
mEffects[i]->setHapticIntensity(id, intensity);
}
}
-void AudioFlinger::EffectChain::syncHalEffectsState()
+void EffectChain::syncHalEffectsState()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); i++) {
if (mEffects[i]->state() == EffectModule::ACTIVE ||
mEffects[i]->state() == EffectModule::STOPPING) {
@@ -2636,7 +2651,7 @@
}
}
-void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
+void EffectChain::dump(int fd, const Vector<String16>& args) const
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
String8 result;
@@ -2645,7 +2660,7 @@
result.appendFormat(" %zu effects for session %d\n", numEffects, mSessionId);
if (numEffects) {
- bool locked = AudioFlinger::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
result.append("\tCould not lock mutex:\n");
@@ -2661,22 +2676,22 @@
write(fd, result.c_str(), result.size());
for (size_t i = 0; i < numEffects; ++i) {
- sp<EffectModule> effect = mEffects[i];
+ sp<IAfEffectModule> effect = mEffects[i];
if (effect != 0) {
effect->dump(fd, args);
}
}
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
} else {
write(fd, result.c_str(), result.size());
}
}
-// must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setEffectSuspended_l(
+// must be called with IAfThreadBase::mutex() held
+void EffectChain::setEffectSuspended_l(
const effect_uuid_t *type, bool suspend)
{
sp<SuspendedEffectDesc> desc;
@@ -2694,7 +2709,7 @@
}
if (desc->mRefCount++ == 0) {
- sp<EffectModule> effect = getEffectIfEnabled(type);
+ sp<IAfEffectModule> effect = getEffectIfEnabled(type);
if (effect != 0) {
desc->mEffect = effect;
effect->setSuspended(true);
@@ -2714,15 +2729,15 @@
if (--desc->mRefCount == 0) {
ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
if (desc->mEffect != 0) {
- sp<EffectModule> effect = desc->mEffect.promote();
+ sp<IAfEffectModule> effect = desc->mEffect.promote();
if (effect != 0) {
effect->setSuspended(false);
- effect->lock();
- EffectHandle *handle = effect->controlHandle_l();
+ effect->mutex().lock();
+ IAfEffectHandle *handle = effect->controlHandle_l();
if (handle != NULL && !handle->disconnected()) {
effect->setEnabled_l(handle->enabled());
}
- effect->unlock();
+ effect->mutex().unlock();
}
desc->mEffect.clear();
}
@@ -2731,8 +2746,8 @@
}
}
-// must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
+// must be called with IAfThreadBase::mutex() held
+void EffectChain::setEffectSuspendedAll_l(bool suspend)
{
sp<SuspendedEffectDesc> desc;
@@ -2746,7 +2761,7 @@
ALOGV("setEffectSuspendedAll_l() add entry for 0");
}
if (desc->mRefCount++ == 0) {
- Vector< sp<EffectModule> > effects;
+ Vector< sp<IAfEffectModule> > effects;
getSuspendEligibleEffects(effects);
for (size_t i = 0; i < effects.size(); i++) {
setEffectSuspended_l(&effects[i]->desc().type, true);
@@ -2788,7 +2803,7 @@
#endif //OPENSL_ES_H_
/* static */
-bool AudioFlinger::EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
+bool EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
{
// Only NS and AEC are suspended when BtNRec is off
if ((memcmp(type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) ||
@@ -2798,7 +2813,7 @@
return false;
}
-bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
+bool EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
{
// auxiliary effects and visualizer are never suspended on output mix
if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
@@ -2811,8 +2826,8 @@
return true;
}
-void AudioFlinger::EffectChain::getSuspendEligibleEffects(
- Vector< sp<AudioFlinger::EffectModule> > &effects)
+void EffectChain::getSuspendEligibleEffects(
+ Vector< sp<IAfEffectModule> > &effects)
{
effects.clear();
for (size_t i = 0; i < mEffects.size(); i++) {
@@ -2822,14 +2837,13 @@
}
}
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
- const effect_uuid_t *type)
+sp<IAfEffectModule> EffectChain::getEffectIfEnabled(const effect_uuid_t *type)
{
- sp<EffectModule> effect = getEffectFromType_l(type);
+ sp<IAfEffectModule> effect = getEffectFromType_l(type);
return effect != 0 && effect->isEnabled() ? effect : 0;
}
-void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+void EffectChain::checkSuspendOnEffectEnabled(const sp<IAfEffectModule>& effect,
bool enabled)
{
ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
@@ -2871,13 +2885,13 @@
}
}
-bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
+bool EffectChain::isNonOffloadableEnabled() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return isNonOffloadableEnabled_l();
}
-bool AudioFlinger::EffectChain::isNonOffloadableEnabled_l()
+bool EffectChain::isNonOffloadableEnabled_l() const
{
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -2888,13 +2902,13 @@
return false;
}
-void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
+void EffectChain::setThread(const sp<IAfThreadBase>& thread)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mEffectCallback->setThread(thread);
}
-void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
+void EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
{
if ((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
*flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
@@ -2907,7 +2921,7 @@
}
}
-void AudioFlinger::EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
+void EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
{
if ((*flags & AUDIO_INPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
*flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
@@ -2917,9 +2931,9 @@
}
}
-bool AudioFlinger::EffectChain::isRawCompatible() const
+bool EffectChain::isRawCompatible() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (const auto &effect : mEffects) {
if (effect->isProcessImplemented()) {
return false;
@@ -2929,9 +2943,9 @@
return true;
}
-bool AudioFlinger::EffectChain::isFastCompatible() const
+bool EffectChain::isFastCompatible() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (const auto &effect : mEffects) {
if (effect->isProcessImplemented()
&& effect->isImplementationSoftware()) {
@@ -2942,8 +2956,8 @@
return true;
}
-bool AudioFlinger::EffectChain::isBitPerfectCompatible() const {
- Mutex::Autolock _l(mLock);
+bool EffectChain::isBitPerfectCompatible() const {
+ audio_utils::lock_guard _l(mutex());
for (const auto &effect : mEffects) {
if (effect->isProcessImplemented()
&& effect->isImplementationSoftware()) {
@@ -2954,10 +2968,10 @@
return true;
}
-// isCompatibleWithThread_l() must be called with thread->mLock held
-bool AudioFlinger::EffectChain::isCompatibleWithThread_l(const sp<ThreadBase>& thread) const
+// isCompatibleWithThread_l() must be called with thread->mutex() held
+bool EffectChain::isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); i++) {
if (thread->checkEffectCompatibility_l(&(mEffects[i]->desc()), mSessionId) != NO_ERROR) {
return false;
@@ -2967,7 +2981,7 @@
}
// EffectCallbackInterface implementation
-status_t AudioFlinger::EffectChain::EffectCallback::createEffectHal(
+status_t EffectChain::EffectCallback::createEffectHal(
const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *effect) {
status_t status = NO_INIT;
@@ -2979,21 +2993,21 @@
return status;
}
-bool AudioFlinger::EffectChain::EffectCallback::updateOrphanEffectChains(
- const sp<AudioFlinger::EffectBase>& effect) {
+bool EffectChain::EffectCallback::updateOrphanEffectChains(
+ const sp<IAfEffectBase>& effect) {
// in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
- return mAudioFlinger.updateOrphanEffectChains(effect->asEffectModule());
+ return mAfThreadCallback->updateOrphanEffectChains(effect->asEffectModule());
}
-status_t AudioFlinger::EffectChain::EffectCallback::allocateHalBuffer(
+status_t EffectChain::EffectCallback::allocateHalBuffer(
size_t size, sp<EffectBufferHalInterface>* buffer) {
- return mAudioFlinger.mEffectsFactoryHal->allocateBuffer(size, buffer);
+ return mAfThreadCallback->getEffectsFactoryHal()->allocateBuffer(size, buffer);
}
-status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
+status_t EffectChain::EffectCallback::addEffectToHal(
const sp<EffectHalInterface>& effect) {
status_t result = NO_INIT;
- sp<ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return result;
}
@@ -3006,10 +3020,10 @@
return result;
}
-status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
+status_t EffectChain::EffectCallback::removeEffectFromHal(
const sp<EffectHalInterface>& effect) {
status_t result = NO_INIT;
- sp<ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return result;
}
@@ -3022,64 +3036,65 @@
return result;
}
-audio_io_handle_t AudioFlinger::EffectChain::EffectCallback::io() const {
- sp<ThreadBase> t = thread().promote();
+audio_io_handle_t EffectChain::EffectCallback::io() const {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_IO_HANDLE_NONE;
}
return t->id();
}
-bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
- sp<ThreadBase> t = thread().promote();
+bool EffectChain::EffectCallback::isOutput() const {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return true;
}
return t->isOutput();
}
-bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
- return mThreadType == ThreadBase::OFFLOAD;
+bool EffectChain::EffectCallback::isOffload() const {
+ return mThreadType == IAfThreadBase::OFFLOAD;
}
-bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
- return mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT;
+bool EffectChain::EffectCallback::isOffloadOrDirect() const {
+ return mThreadType == IAfThreadBase::OFFLOAD
+ || mThreadType == IAfThreadBase::DIRECT;
}
-bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
+bool EffectChain::EffectCallback::isOffloadOrMmap() const {
switch (mThreadType) {
- case ThreadBase::OFFLOAD:
- case ThreadBase::MMAP_PLAYBACK:
- case ThreadBase::MMAP_CAPTURE:
+ case IAfThreadBase::OFFLOAD:
+ case IAfThreadBase::MMAP_PLAYBACK:
+ case IAfThreadBase::MMAP_CAPTURE:
return true;
default:
return false;
}
}
-bool AudioFlinger::EffectChain::EffectCallback::isSpatializer() const {
- return mThreadType == ThreadBase::SPATIALIZER;
+bool EffectChain::EffectCallback::isSpatializer() const {
+ return mThreadType == IAfThreadBase::SPATIALIZER;
}
-uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
- sp<ThreadBase> t = thread().promote();
+uint32_t EffectChain::EffectCallback::sampleRate() const {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return 0;
}
return t->sampleRate();
}
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::inChannelMask(int id) const {
- sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
}
- sp<EffectChain> c = chain().promote();
+ sp<IAfEffectChain> c = chain().promote();
if (c == nullptr) {
return AUDIO_CHANNEL_NONE;
}
- if (mThreadType == ThreadBase::SPATIALIZER) {
+ if (mThreadType == IAfThreadBase::SPATIALIZER) {
if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
if (c->isFirstEffect(id)) {
return t->mixerChannelMask();
@@ -3087,7 +3102,8 @@
return t->channelMask();
}
} else if (!audio_is_global_session(c->sessionId())) {
- if ((t->hasAudioSession_l(c->sessionId()) & ThreadBase::SPATIALIZED_SESSION) != 0) {
+ if ((t->hasAudioSession_l(c->sessionId())
+ & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
return t->mixerChannelMask();
} else {
return t->channelMask();
@@ -3100,23 +3116,24 @@
}
}
-uint32_t AudioFlinger::EffectChain::EffectCallback::inChannelCount(int id) const {
+uint32_t EffectChain::EffectCallback::inChannelCount(int id) const {
return audio_channel_count_from_out_mask(inChannelMask(id));
}
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::outChannelMask() const {
- sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
}
- sp<EffectChain> c = chain().promote();
+ sp<IAfEffectChain> c = chain().promote();
if (c == nullptr) {
return AUDIO_CHANNEL_NONE;
}
- if (mThreadType == ThreadBase::SPATIALIZER) {
+ if (mThreadType == IAfThreadBase::SPATIALIZER) {
if (!audio_is_global_session(c->sessionId())) {
- if ((t->hasAudioSession_l(c->sessionId()) & ThreadBase::SPATIALIZED_SESSION) != 0) {
+ if ((t->hasAudioSession_l(c->sessionId())
+ & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
return t->mixerChannelMask();
} else {
return t->channelMask();
@@ -3129,30 +3146,30 @@
}
}
-uint32_t AudioFlinger::EffectChain::EffectCallback::outChannelCount() const {
+uint32_t EffectChain::EffectCallback::outChannelCount() const {
return audio_channel_count_from_out_mask(outChannelMask());
}
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::hapticChannelMask() const {
- sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::hapticChannelMask() const {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
}
return t->hapticChannelMask();
}
-size_t AudioFlinger::EffectChain::EffectCallback::frameCount() const {
- sp<ThreadBase> t = thread().promote();
+size_t EffectChain::EffectCallback::frameCount() const {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return 0;
}
return t->frameCount();
}
-uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const
+uint32_t EffectChain::EffectCallback::latency() const
NO_THREAD_SAFETY_ANALYSIS // latency_l() access
{
- sp<ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return 0;
}
@@ -3160,25 +3177,25 @@
return t->latency_l();
}
-void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
+void EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
NO_THREAD_SAFETY_ANALYSIS // setVolumeForOutput_l() access
{
- sp<ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return;
}
t->setVolumeForOutput_l(left, right);
}
-void AudioFlinger::EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
- const sp<EffectBase>& effect, bool enabled, bool threadLocked) {
- sp<ThreadBase> t = thread().promote();
+void EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
+ const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return;
}
t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);
- sp<EffectChain> c = chain().promote();
+ sp<IAfEffectChain> c = chain().promote();
if (c == nullptr) {
return;
}
@@ -3186,8 +3203,8 @@
c->checkSuspendOnEffectEnabled(effect->asEffectModule(), enabled);
}
-void AudioFlinger::EffectChain::EffectCallback::onEffectEnable(const sp<EffectBase>& effect) {
- sp<ThreadBase> t = thread().promote();
+void EffectChain::EffectCallback::onEffectEnable(const sp<IAfEffectBase>& effect) {
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return;
}
@@ -3195,19 +3212,19 @@
t->onEffectEnable(effect->asEffectModule());
}
-void AudioFlinger::EffectChain::EffectCallback::onEffectDisable(const sp<EffectBase>& effect) {
+void EffectChain::EffectCallback::onEffectDisable(const sp<IAfEffectBase>& effect) {
checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
- sp<ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return;
}
t->onEffectDisable();
}
-bool AudioFlinger::EffectChain::EffectCallback::disconnectEffectHandle(EffectHandle *handle,
+bool EffectChain::EffectCallback::disconnectEffectHandle(IAfEffectHandle *handle,
bool unpinIfLast) {
- sp<ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return false;
}
@@ -3215,8 +3232,8 @@
return true;
}
-void AudioFlinger::EffectChain::EffectCallback::resetVolume() {
- sp<EffectChain> c = chain().promote();
+void EffectChain::EffectCallback::resetVolume() {
+ sp<IAfEffectChain> c = chain().promote();
if (c == nullptr) {
return;
}
@@ -3224,16 +3241,16 @@
}
-product_strategy_t AudioFlinger::EffectChain::EffectCallback::strategy() const {
- sp<EffectChain> c = chain().promote();
+product_strategy_t EffectChain::EffectCallback::strategy() const {
+ sp<IAfEffectChain> c = chain().promote();
if (c == nullptr) {
return PRODUCT_STRATEGY_NONE;
}
return c->strategy();
}
-int32_t AudioFlinger::EffectChain::EffectCallback::activeTrackCnt() const {
- sp<EffectChain> c = chain().promote();
+int32_t EffectChain::EffectCallback::activeTrackCnt() const {
+ sp<IAfEffectChain> c = chain().promote();
if (c == nullptr) {
return 0;
}
@@ -3242,19 +3259,30 @@
#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::DeviceEffectProxy"
+#define LOG_TAG "DeviceEffectProxy"
-status_t AudioFlinger::DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
+/* static */
+sp<IAfDeviceEffectProxy> IAfDeviceEffectProxy::create(
+ const AudioDeviceTypeAddr& device,
+ const sp<DeviceEffectManagerCallback>& callback,
+ effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
+{
+ return sp<DeviceEffectProxy>::make(device,
+ callback,
+ desc, id, notifyFramesProcessed);
+}
+
+status_t DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
{
status_t status = EffectBase::setEnabled(enabled, fromHandle);
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
if (status == NO_ERROR) {
for (auto& handle : mEffectHandles) {
Status bs;
if (enabled) {
- bs = handle.second->enable(&status);
+ bs = handle.second->asIEffect()->enable(&status);
} else {
- bs = handle.second->disable(&status);
+ bs = handle.second->asIEffect()->disable(&status);
}
if (!bs.isOk()) {
status = statusTFromBinderStatus(bs);
@@ -3265,8 +3293,8 @@
return status;
}
-status_t AudioFlinger::DeviceEffectProxy::init(
- const std::map <audio_patch_handle_t, PatchPanel::Patch>& patches) {
+status_t DeviceEffectProxy::init(
+ const std::map <audio_patch_handle_t, IAfPatchPanel::Patch>& patches) {
//For all audio patches
//If src or sink device match
//If the effect is HW accelerated
@@ -3288,10 +3316,10 @@
return status;
}
-status_t AudioFlinger::DeviceEffectProxy::onCreatePatch(
- audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch) {
+status_t DeviceEffectProxy::onCreatePatch(
+ audio_patch_handle_t patchHandle, const IAfPatchPanel::Patch& patch) {
status_t status = NAME_NOT_FOUND;
- sp<EffectHandle> handle;
+ sp<IAfEffectHandle> handle;
// only consider source[0] as this is the only "true" source of a patch
status = checkPort(patch, &patch.mAudioPatch.sources[0], &handle);
ALOGV("%s source checkPort status %d", __func__, status);
@@ -3300,7 +3328,7 @@
ALOGV("%s sink %d checkPort status %d", __func__, i, status);
}
if (status == NO_ERROR || status == ALREADY_EXISTS) {
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
mEffectHandles.emplace(patchHandle, handle);
}
ALOGW_IF(status == BAD_VALUE,
@@ -3309,8 +3337,11 @@
return status;
}
-status_t AudioFlinger::DeviceEffectProxy::checkPort(const PatchPanel::Patch& patch,
- const struct audio_port_config *port, sp <EffectHandle> *handle) {
+status_t DeviceEffectProxy::checkPort(const IAfPatchPanel::Patch& patch,
+ const struct audio_port_config *port, sp<IAfEffectHandle> *handle)
+NO_THREAD_SAFETY_ANALYSIS
+// calling function 'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
+{
ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
__func__, port->type, port->ext.device.type,
@@ -3332,7 +3363,7 @@
status_t status = NAME_NOT_FOUND;
if (mDescriptor.flags & EFFECT_FLAG_HW_ACC_TUNNEL) {
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
mDevicePort = *port;
mHalEffect = new EffectModule(mMyCallback,
const_cast<effect_descriptor_t *>(&mDescriptor),
@@ -3355,7 +3386,7 @@
mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
}
} else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
- sp <ThreadBase> thread;
+ sp<IAfThreadBase> thread;
if (audio_port_config_has_input_direction(port)) {
if (patch.isSoftware()) {
thread = patch.mRecord.thread();
@@ -3382,9 +3413,9 @@
if (status == NO_ERROR || status == ALREADY_EXISTS) {
Status bs;
if (isEnabled()) {
- bs = (*handle)->enable(&status);
+ bs = (*handle)->asIEffect()->enable(&status);
} else {
- bs = (*handle)->disable(&status);
+ bs = (*handle)->asIEffect()->disable(&status);
}
if (!bs.isOk()) {
status = statusTFromBinderStatus(bs);
@@ -3393,10 +3424,10 @@
return status;
}
-void AudioFlinger::DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
- sp<EffectHandle> effect;
+void DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
+ sp<IAfEffectHandle> effect;
{
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
if (mEffectHandles.find(patchHandle) != mEffectHandles.end()) {
effect = mEffectHandles.at(patchHandle);
mEffectHandles.erase(patchHandle);
@@ -3405,9 +3436,9 @@
}
-size_t AudioFlinger::DeviceEffectProxy::removeEffect(const sp<EffectModule>& effect)
+size_t DeviceEffectProxy::removeEffect(const sp<IAfEffectModule>& effect)
{
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
if (effect == mHalEffect) {
mHalEffect->release_l();
mHalEffect.clear();
@@ -3416,7 +3447,7 @@
return mHalEffect == nullptr ? 0 : 1;
}
-status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
+status_t DeviceEffectProxy::addEffectToHal(
const sp<EffectHalInterface>& effect) {
if (mHalEffect == nullptr) {
return NO_INIT;
@@ -3424,7 +3455,7 @@
return mManagerCallback->addEffectToHal(&mDevicePort, effect);
}
-status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
+status_t DeviceEffectProxy::removeEffectFromHal(
const sp<EffectHalInterface>& effect) {
if (mHalEffect == nullptr) {
return NO_INIT;
@@ -3432,14 +3463,14 @@
return mManagerCallback->removeEffectFromHal(&mDevicePort, effect);
}
-bool AudioFlinger::DeviceEffectProxy::isOutput() const {
+bool DeviceEffectProxy::isOutput() const {
if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE) {
return mDevicePort.role == AUDIO_PORT_ROLE_SINK;
}
return true;
}
-uint32_t AudioFlinger::DeviceEffectProxy::sampleRate() const {
+uint32_t DeviceEffectProxy::sampleRate() const {
if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
(mDevicePort.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) != 0) {
return mDevicePort.sample_rate;
@@ -3447,7 +3478,7 @@
return DEFAULT_OUTPUT_SAMPLE_RATE;
}
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::channelMask() const {
+audio_channel_mask_t DeviceEffectProxy::channelMask() const {
if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
(mDevicePort.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) != 0) {
return mDevicePort.channel_mask;
@@ -3455,20 +3486,20 @@
return AUDIO_CHANNEL_OUT_STEREO;
}
-uint32_t AudioFlinger::DeviceEffectProxy::channelCount() const {
+uint32_t DeviceEffectProxy::channelCount() const {
if (isOutput()) {
return audio_channel_count_from_out_mask(channelMask());
}
return audio_channel_count_from_in_mask(channelMask());
}
-void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces)
+void DeviceEffectProxy::dump2(int fd, int spaces) const
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
const Vector<String16> args;
EffectBase::dump(fd, args);
- const bool locked = dumpTryLock(mProxyLock);
+ const bool locked = afutils::dumpTryLock(proxyMutex());
if (!locked) {
String8 result("DeviceEffectProxy may be deadlocked\n");
write(fd, result.c_str(), result.size());
@@ -3491,33 +3522,33 @@
outStr.appendFormat("%*sEffect for patch handle %d:\n", spaces + 2, "", iter.first);
write(fd, outStr.c_str(), outStr.size());
outStr.clear();
- sp<EffectBase> effect = iter.second->effect().promote();
+ sp<IAfEffectBase> effect = iter.second->effect().promote();
if (effect != nullptr) {
effect->dump(fd, args);
}
}
if (locked) {
- mLock.unlock();
+ proxyMutex().unlock();
}
}
#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::DeviceEffectProxy::ProxyCallback"
+#define LOG_TAG "DeviceEffectProxy::ProxyCallback"
-int AudioFlinger::DeviceEffectProxy::ProxyCallback::newEffectId() {
+int DeviceEffectProxy::ProxyCallback::newEffectId() {
return mManagerCallback->newEffectId();
}
-bool AudioFlinger::DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
- EffectHandle *handle, bool unpinIfLast) {
- sp<EffectBase> effectBase = handle->effect().promote();
+bool DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
+ IAfEffectHandle *handle, bool unpinIfLast) {
+ sp<IAfEffectBase> effectBase = handle->effect().promote();
if (effectBase == nullptr) {
return false;
}
- sp<EffectModule> effect = effectBase->asEffectModule();
+ sp<IAfEffectModule> effect = effectBase->asEffectModule();
if (effect == nullptr) {
return false;
}
@@ -3536,13 +3567,13 @@
return true;
}
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::createEffectHal(
+status_t DeviceEffectProxy::ProxyCallback::createEffectHal(
const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *effect) {
return mManagerCallback->createEffectHal(pEffectUuid, sessionId, deviceId, effect);
}
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
+status_t DeviceEffectProxy::ProxyCallback::addEffectToHal(
const sp<EffectHalInterface>& effect) {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
@@ -3551,7 +3582,7 @@
return proxy->addEffectToHal(effect);
}
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
+status_t DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
const sp<EffectHalInterface>& effect) {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
@@ -3560,7 +3591,7 @@
return proxy->removeEffectFromHal(effect);
}
-bool AudioFlinger::DeviceEffectProxy::ProxyCallback::isOutput() const {
+bool DeviceEffectProxy::ProxyCallback::isOutput() const {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return true;
@@ -3568,7 +3599,7 @@
return proxy->isOutput();
}
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::sampleRate() const {
+uint32_t DeviceEffectProxy::ProxyCallback::sampleRate() const {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return DEFAULT_OUTPUT_SAMPLE_RATE;
@@ -3576,7 +3607,7 @@
return proxy->sampleRate();
}
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::inChannelMask(
+audio_channel_mask_t DeviceEffectProxy::ProxyCallback::inChannelMask(
int id __unused) const {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
@@ -3585,7 +3616,7 @@
return proxy->channelMask();
}
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::inChannelCount(int id __unused) const {
+uint32_t DeviceEffectProxy::ProxyCallback::inChannelCount(int id __unused) const {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return 2;
@@ -3593,7 +3624,7 @@
return proxy->channelCount();
}
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::outChannelMask() const {
+audio_channel_mask_t DeviceEffectProxy::ProxyCallback::outChannelMask() const {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return AUDIO_CHANNEL_OUT_STEREO;
@@ -3601,7 +3632,7 @@
return proxy->channelMask();
}
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::outChannelCount() const {
+uint32_t DeviceEffectProxy::ProxyCallback::outChannelCount() const {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return 2;
@@ -3609,18 +3640,18 @@
return proxy->channelCount();
}
-void AudioFlinger::DeviceEffectProxy::ProxyCallback::onEffectEnable(
- const sp<EffectBase>& effectBase) {
- sp<EffectModule> effect = effectBase->asEffectModule();
+void DeviceEffectProxy::ProxyCallback::onEffectEnable(
+ const sp<IAfEffectBase>& effectBase) {
+ sp<IAfEffectModule> effect = effectBase->asEffectModule();
if (effect == nullptr) {
return;
}
effect->start();
}
-void AudioFlinger::DeviceEffectProxy::ProxyCallback::onEffectDisable(
- const sp<EffectBase>& effectBase) {
- sp<EffectModule> effect = effectBase->asEffectModule();
+void DeviceEffectProxy::ProxyCallback::onEffectDisable(
+ const sp<IAfEffectBase>& effectBase) {
+ sp<IAfEffectModule> effect = effectBase->asEffectModule();
if (effect == nullptr) {
return;
}
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 7ceb6c6..aeb0fea 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -15,62 +15,21 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "DeviceEffectManager.h"
+#include "IAfEffect.h"
+
+#include <android-base/macros.h> // DISALLOW_COPY_AND_ASSIGN
+#include <mediautils/Synchronization.h>
+#include <private/media/AudioEffectShared.h>
+
+#include <map> // avoid transitive dependency
+
+namespace android {
//--- Audio Effect Management
-// Interface implemented by the EffectModule parent or owner (e.g an EffectChain) to abstract
-// interactions between the EffectModule and the reset of the audio framework.
-class EffectCallbackInterface : public RefBase {
-public:
- ~EffectCallbackInterface() override = default;
-
- // Trivial methods usually implemented with help from ThreadBase
- virtual audio_io_handle_t io() const = 0;
- virtual bool isOutput() const = 0;
- virtual bool isOffload() const = 0;
- virtual bool isOffloadOrDirect() const = 0;
- virtual bool isOffloadOrMmap() const = 0;
- virtual bool isSpatializer() const = 0;
- virtual uint32_t sampleRate() const = 0;
- virtual audio_channel_mask_t inChannelMask(int id) const = 0;
- virtual uint32_t inChannelCount(int id) const = 0;
- virtual audio_channel_mask_t outChannelMask() const = 0;
- virtual uint32_t outChannelCount() const = 0;
- virtual audio_channel_mask_t hapticChannelMask() const = 0;
- virtual size_t frameCount() const = 0;
-
- // Non trivial methods usually implemented with help from ThreadBase:
- // pay attention to mutex locking order
- virtual uint32_t latency() const { return 0; }
- virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
- virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
- virtual void setVolumeForOutput(float left, float right) const = 0;
- virtual bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) = 0;
- virtual void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
- bool enabled,
- bool threadLocked) = 0;
- virtual void onEffectEnable(const sp<EffectBase>& effect) = 0;
- virtual void onEffectDisable(const sp<EffectBase>& effect) = 0;
-
- // Methods usually implemented with help from AudioFlinger: pay attention to mutex locking order
- virtual status_t createEffectHal(const effect_uuid_t *pEffectUuid,
- int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) = 0;
- virtual status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
- virtual bool updateOrphanEffectChains(const sp<EffectBase>& effect) = 0;
-
- // Methods usually implemented with help from EffectChain: pay attention to mutex locking order
- virtual product_strategy_t strategy() const = 0;
- virtual int32_t activeTrackCnt() const = 0;
- virtual void resetVolume() = 0;
-
- virtual wp<EffectChain> chain() const = 0;
-
- virtual bool isAudioPolicyReady() const = 0;
-};
-
// EffectBase(EffectModule) and EffectChain classes both have their own mutex to protect
// state changes or resource modifications. Always respect the following order
// if multiple mutexes must be acquired to avoid cross deadlock:
@@ -90,7 +49,7 @@
// The EffectBase class contains common properties, state and behavior for and EffectModule or
// other derived classes managing an audio effect instance within the effect framework.
// It also contains the class mutex (see comment on locking order above).
-class EffectBase : public RefBase {
+class EffectBase : public virtual IAfEffectBase {
public:
EffectBase(const sp<EffectCallbackInterface>& callback,
effect_descriptor_t *desc,
@@ -98,76 +57,68 @@
audio_session_t sessionId,
bool pinned);
- ~EffectBase() override = default;
-
- enum effect_state {
- IDLE,
- RESTART,
- STARTING,
- ACTIVE,
- STOPPING,
- STOPPED,
- DESTROYED
- };
-
- int id() const { return mId; }
- effect_state state() const {
+ int id() const final { return mId; }
+ effect_state state() const final {
return mState;
}
- audio_session_t sessionId() const {
+ audio_session_t sessionId() const final {
return mSessionId;
}
- const effect_descriptor_t& desc() const { return mDescriptor; }
- bool isOffloadable() const
+ const effect_descriptor_t& desc() const final { return mDescriptor; }
+ bool isOffloadable() const final
{ return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; }
- bool isImplementationSoftware() const
+ bool isImplementationSoftware() const final
{ return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; }
- bool isProcessImplemented() const
+ bool isProcessImplemented() const final
{ return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; }
- bool isVolumeControl() const
+ bool isVolumeControl() const
{ return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
== EFFECT_FLAG_VOLUME_CTRL; }
- bool isVolumeMonitor() const
+ bool isVolumeMonitor() const final
{ return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
== EFFECT_FLAG_VOLUME_MONITOR; }
- virtual status_t setEnabled(bool enabled, bool fromHandle);
- status_t setEnabled_l(bool enabled);
- bool isEnabled() const;
+ status_t setEnabled(bool enabled, bool fromHandle) override;
+ status_t setEnabled_l(bool enabled) final;
+ bool isEnabled() const final;
+ void setSuspended(bool suspended) final;
+ bool suspended() const final;
- void setSuspended(bool suspended);
- bool suspended() const;
-
- virtual status_t command(int32_t __unused,
+ status_t command(int32_t __unused,
const std::vector<uint8_t>& __unused,
int32_t __unused,
- std::vector<uint8_t>* __unused) { return NO_ERROR; };
+ std::vector<uint8_t>* __unused) override {
+ return NO_ERROR;
+ }
// mCallback is atomic so this can be lock-free.
- void setCallback(const sp<EffectCallbackInterface>& callback) { mCallback = callback; }
- sp<EffectCallbackInterface> getCallback() const { return mCallback.load(); }
+ void setCallback(const sp<EffectCallbackInterface>& callback) final {
+ mCallback = callback;
+ }
+ sp<EffectCallbackInterface> getCallback() const final {
+ return mCallback.load();
+ }
- status_t addHandle(EffectHandle *handle);
- ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast);
- ssize_t removeHandle(EffectHandle *handle);
- ssize_t removeHandle_l(EffectHandle *handle);
- EffectHandle* controlHandle_l();
- bool purgeHandles();
+ status_t addHandle(IAfEffectHandle *handle) final;
+ ssize_t disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast) final;
+ ssize_t removeHandle(IAfEffectHandle *handle) final;
+ ssize_t removeHandle_l(IAfEffectHandle *handle) final;
+ IAfEffectHandle* controlHandle_l() final;
+ bool purgeHandles() final;
- void checkSuspendOnEffectEnabled(bool enabled, bool threadLocked);
+ void checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) final;
- bool isPinned() const { return mPinned; }
- void unPin() { mPinned = false; }
+ bool isPinned() const final { return mPinned; }
+ void unPin() final { mPinned = false; }
- void lock() ACQUIRE(mLock) { mLock.lock(); }
- void unlock() RELEASE(mLock) { mLock.unlock(); }
+ audio_utils::mutex& mutex() const final { return mMutex; }
- status_t updatePolicyState();
+ status_t updatePolicyState() final;
- virtual sp<EffectModule> asEffectModule() { return nullptr; }
- virtual sp<DeviceEffectProxy> asDeviceEffectProxy() { return nullptr; }
+ sp<IAfEffectModule> asEffectModule() override { return nullptr; }
+ sp<IAfDeviceEffectProxy> asDeviceEffectProxy() override { return nullptr; }
- void dump(int fd, const Vector<String16>& args);
+ void dump(int fd, const Vector<String16>& args) const override;
protected:
bool isInternal_l() const {
@@ -179,13 +130,12 @@
return true;
}
-private:
- friend class AudioFlinger; // for mHandles
bool mPinned = false;
DISALLOW_COPY_AND_ASSIGN(EffectBase);
-mutable Mutex mLock; // mutex for process, commands and handles list protection
+ // mutex for process, commands and handles list protection
+ mutable audio_utils::mutex mMutex;
mediautils::atomic_sp<EffectCallbackInterface> mCallback; // parent effect chain
const int mId; // this instance unique ID
const audio_session_t mSessionId; // audio session ID
@@ -194,13 +144,14 @@
// effect is suspended: temporarily disabled by framework
bool mSuspended = false;
- Vector<EffectHandle *> mHandles; // list of client handles
+ Vector<IAfEffectHandle *> mHandles; // list of client handles
// First handle in mHandles has highest priority and controls the effect module
// Audio policy effect state management
- // Mutex protecting transactions with audio policy manager as mLock cannot
+ // Mutex protecting transactions with audio policy manager as mutex() cannot
// be held to avoid cross deadlocks with audio policy mutex
- Mutex mPolicyLock;
+ audio_utils::mutex& policyMutex() const { return mPolicyMutex; }
+ mutable audio_utils::mutex mPolicyMutex;
// Effect is registered in APM or not
bool mPolicyRegistered = false;
// Effect enabled state communicated to APM. Enabled state corresponds to
@@ -217,7 +168,7 @@
// ramping when effects are activated/deactivated.
// When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
// the attached track(s) to accumulate their auxiliary channel.
-class EffectModule : public EffectBase {
+class EffectModule : public IAfEffectModule, public EffectBase {
public:
EffectModule(const sp<EffectCallbackInterface>& callabck,
effect_descriptor_t *desc,
@@ -225,72 +176,65 @@
audio_session_t sessionId,
bool pinned,
audio_port_handle_t deviceId);
- virtual ~EffectModule();
+ ~EffectModule() override;
- void process();
- bool updateState();
+ void process() final;
+ bool updateState() final;
status_t command(int32_t cmdCode,
const std::vector<uint8_t>& cmdData,
int32_t maxReplySize,
- std::vector<uint8_t>* reply) override;
+ std::vector<uint8_t>* reply) final;
- void reset_l();
- status_t configure();
- status_t init();
-
- uint32_t status() {
+ void reset_l() final;
+ status_t configure() final;
+ status_t init() final;
+ uint32_t status() const final {
return mStatus;
}
-
- bool isProcessEnabled() const;
- bool isOffloadedOrDirect() const;
- bool isVolumeControlEnabled() const;
-
- void setInBuffer(const sp<EffectBufferHalInterface>& buffer);
- int16_t *inBuffer() const {
+ bool isProcessEnabled() const final;
+ bool isOffloadedOrDirect() const final;
+ bool isVolumeControlEnabled() const final;
+ void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final;
+ int16_t *inBuffer() const final {
return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
}
- void setOutBuffer(const sp<EffectBufferHalInterface>& buffer);
- int16_t *outBuffer() const {
+ void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) final;
+ int16_t *outBuffer() const final {
return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
}
-
// Updates the access mode if it is out of date. May issue a new effect configure.
- void updateAccessMode() {
+ void updateAccessMode() final {
if (requiredEffectBufferAccessMode() != mConfig.outputCfg.accessMode) {
configure();
}
}
+ status_t setDevices(const AudioDeviceTypeAddrVector &devices) final;
+ status_t setInputDevice(const AudioDeviceTypeAddr &device) final;
+ status_t setVolume(uint32_t *left, uint32_t *right, bool controller) final;
+ status_t setMode(audio_mode_t mode) final;
+ status_t setAudioSource(audio_source_t source) final;
+ status_t start() final;
+ status_t stop() final;
- status_t setDevices(const AudioDeviceTypeAddrVector &devices);
- status_t setInputDevice(const AudioDeviceTypeAddr &device);
- status_t setVolume(uint32_t *left, uint32_t *right, bool controller);
- status_t setMode(audio_mode_t mode);
- status_t setAudioSource(audio_source_t source);
- status_t start();
- status_t stop();
+ status_t setOffloaded(bool offloaded, audio_io_handle_t io) final;
+ bool isOffloaded() const final;
+ void addEffectToHal_l() final;
+ void release_l() final;
- status_t setOffloaded(bool offloaded, audio_io_handle_t io);
- bool isOffloaded() const;
- void addEffectToHal_l();
- void release_l();
+ sp<IAfEffectModule> asEffectModule() final { return this; }
- sp<EffectModule> asEffectModule() override { return this; }
+ bool isHapticGenerator() const final;
- static bool isHapticGenerator(const effect_uuid_t* type);
- bool isHapticGenerator() const;
+ status_t setHapticIntensity(int id, os::HapticScale intensity) final;
+ status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo) final;
- status_t setHapticIntensity(int id, os::HapticScale intensity);
- status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo);
-
- status_t getConfigs(audio_config_base_t* inputCfg,
+ status_t getConfigs(audio_config_base_t* inputCfg,
audio_config_base_t* outputCfg,
- bool* isOutput) const;
+ bool* isOutput) const final;
- void dump(int fd, const Vector<String16>& args);
+ void dump(int fd, const Vector<String16>& args) const final;
private:
- friend class AudioFlinger; // for mHandles
// Maximum time allocated to effect engines to complete the turn off sequence
static const uint32_t MAX_DISABLE_TIME_MS = 10000;
@@ -329,9 +273,10 @@
uint32_t mInChannelCountRequested;
uint32_t mOutChannelCountRequested;
+ template <typename MUTEX>
class AutoLockReentrant {
public:
- AutoLockReentrant(Mutex& mutex, pid_t allowedTid)
+ AutoLockReentrant(MUTEX& mutex, pid_t allowedTid)
: mMutex(gettid() == allowedTid ? nullptr : &mutex)
{
if (mMutex != nullptr) mMutex->lock();
@@ -340,7 +285,7 @@
if (mMutex != nullptr) mMutex->unlock();
}
private:
- Mutex * const mMutex;
+ MUTEX * const mMutex;
};
static constexpr pid_t INVALID_PID = (pid_t)-1;
@@ -354,32 +299,36 @@
// There is one EffectHandle object for each application controlling (or using)
// an effect module.
// The EffectHandle is obtained by calling AudioFlinger::createEffect().
-class EffectHandle: public android::media::BnEffect {
+class EffectHandle: public IAfEffectHandle, public android::media::BnEffect {
public:
- EffectHandle(const sp<EffectBase>& effect,
- const sp<AudioFlinger::Client>& client,
+ EffectHandle(const sp<IAfEffectBase>& effect,
+ const sp<Client>& client,
const sp<media::IEffectClient>& effectClient,
int32_t priority, bool notifyFramesProcessed);
- virtual ~EffectHandle();
+ ~EffectHandle() override;
status_t onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
- virtual status_t initCheck();
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) final;
+ status_t initCheck() const final;
// IEffect
- android::binder::Status enable(int32_t* _aidl_return) override;
- android::binder::Status disable(int32_t* _aidl_return) override;
+ android::binder::Status enable(int32_t* _aidl_return) final;
+ android::binder::Status disable(int32_t* _aidl_return) final;
android::binder::Status command(int32_t cmdCode,
const std::vector<uint8_t>& cmdData,
int32_t maxResponseSize,
std::vector<uint8_t>* response,
- int32_t* _aidl_return) override;
- android::binder::Status disconnect() override;
- android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) override;
+ int32_t* _aidl_return) final;
+ android::binder::Status disconnect() final;
+ android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) final;
android::binder::Status getConfig(media::EffectConfig* _config,
- int32_t* _aidl_return) override;
+ int32_t* _aidl_return) final;
- sp<Client> client() const { return mClient; }
+ const sp<Client>& client() const final { return mClient; }
+
+ sp<android::media::IEffect> asIEffect() final {
+ return sp<android::media::IEffect>::fromExisting(this);
+ }
private:
void disconnect(bool unpinIfLast);
@@ -388,36 +337,38 @@
// - hasControl: true if control is given, false if removed
// - signal: true client app should be signaled of change, false otherwise
// - enabled: state of the effect when control is passed
- void setControl(bool hasControl, bool signal, bool enabled);
+ void setControl(bool hasControl, bool signal, bool enabled) final;
void commandExecuted(uint32_t cmdCode,
const std::vector<uint8_t>& cmdData,
- const std::vector<uint8_t>& replyData);
- void setEnabled(bool enabled);
- bool enabled() const { return mEnabled; }
+ const std::vector<uint8_t>& replyData) final;
+ bool enabled() const final { return mEnabled; }
+ void setEnabled(bool enabled) final;
+ void framesProcessed(int32_t frames) const final;
- void framesProcessed(int32_t frames) const;
-
+public:
// Getters
- wp<EffectBase> effect() const { return mEffect; }
- int id() const {
- sp<EffectBase> effect = mEffect.promote();
+ wp<IAfEffectBase> effect() const final { return mEffect; }
+ int id() const final {
+ sp<IAfEffectBase> effect = mEffect.promote();
if (effect == 0) {
return 0;
}
return effect->id();
}
- int priority() const { return mPriority; }
- bool hasControl() const { return mHasControl; }
- bool disconnected() const { return mDisconnected; }
+private:
+ int priority() const final { return mPriority; }
+ bool hasControl() const final { return mHasControl; }
+ bool disconnected() const final { return mDisconnected; }
- void dumpToBuffer(char* buffer, size_t size);
+ void dumpToBuffer(char* buffer, size_t size) const final;
+
private:
- friend class AudioFlinger; // for mEffect, mHasControl, mEnabled
DISALLOW_COPY_AND_ASSIGN(EffectHandle);
- Mutex mLock; // protects IEffect method calls
- const wp<EffectBase> mEffect; // pointer to controlled EffectModule
+ audio_utils::mutex& mutex() const { return mMutex; }
+ mutable audio_utils::mutex mMutex; // protects IEffect method calls
+ const wp<IAfEffectBase> mEffect; // pointer to controlled EffectModule
const sp<media::IEffectClient> mEffectClient; // callback interface for client notifications
/*const*/ sp<Client> mClient; // client for shared memory allocation, see
// disconnect()
@@ -443,123 +394,123 @@
// order corresponding in the effect process order. When attached to a track (session ID !=
// AUDIO_SESSION_OUTPUT_MIX),
// it also provide it's own input buffer used by the track as accumulation buffer.
-class EffectChain : public RefBase {
+class EffectChain : public IAfEffectChain {
public:
- EffectChain(const wp<ThreadBase>& wThread, audio_session_t sessionId);
- virtual ~EffectChain();
+ EffectChain(const sp<IAfThreadBase>& thread, audio_session_t sessionId);
- // special key used for an entry in mSuspendedEffects keyed vector
- // corresponding to a suspend all request.
- static const int kKeyForSuspendAll = 0;
+ void process_l() final;
- // minimum duration during which we force calling effect process when last track on
- // a session is stopped or removed to allow effect tail to be rendered
- static const int kProcessTailDurationMs = 1000;
+ audio_utils::mutex& mutex() const final { return mMutex; }
- void process_l();
-
- void lock() ACQUIRE(mLock) {
- mLock.lock();
- }
- void unlock() RELEASE(mLock) {
- mLock.unlock();
- }
-
- status_t createEffect_l(sp<EffectModule>& effect,
+ status_t createEffect_l(sp<IAfEffectModule>& effect,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
- bool pinned);
- status_t addEffect_l(const sp<EffectModule>& handle);
- status_t addEffect_ll(const sp<EffectModule>& handle);
- size_t removeEffect_l(const sp<EffectModule>& handle, bool release = false);
+ bool pinned) final;
+ status_t addEffect_l(const sp<IAfEffectModule>& handle) final;
+ status_t addEffect_ll(const sp<IAfEffectModule>& handle) final;
+ size_t removeEffect_l(const sp<IAfEffectModule>& handle, bool release = false) final;
- audio_session_t sessionId() const { return mSessionId; }
- void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; }
+ audio_session_t sessionId() const final { return mSessionId; }
+ void setSessionId(audio_session_t sessionId) final { mSessionId = sessionId; }
- sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
- sp<EffectModule> getEffectFromId_l(int id);
- sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
- std::vector<int> getEffectIds();
+ sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor) const final;
+ sp<IAfEffectModule> getEffectFromId_l(int id) const final;
+ sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t *type) const final;
+ std::vector<int> getEffectIds() const final;
// FIXME use float to improve the dynamic range
- bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false);
- void resetVolume_l();
- void setDevices_l(const AudioDeviceTypeAddrVector &devices);
- void setInputDevice_l(const AudioDeviceTypeAddr &device);
- void setMode_l(audio_mode_t mode);
- void setAudioSource_l(audio_source_t source);
- void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false) final;
+ void resetVolume_l() final;
+ void setDevices_l(const AudioDeviceTypeAddrVector &devices) final;
+ void setInputDevice_l(const AudioDeviceTypeAddr &device) final;
+ void setMode_l(audio_mode_t mode) final;
+ void setAudioSource_l(audio_source_t source) final;
+
+ void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final {
mInBuffer = buffer;
}
- float *inBuffer() const {
+ float *inBuffer() const final {
return mInBuffer != 0 ? reinterpret_cast<float*>(mInBuffer->ptr()) : NULL;
}
- void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) final {
mOutBuffer = buffer;
}
- float *outBuffer() const {
+ float *outBuffer() const final {
return mOutBuffer != 0 ? reinterpret_cast<float*>(mOutBuffer->ptr()) : NULL;
}
+ void incTrackCnt() final { android_atomic_inc(&mTrackCnt); }
+ void decTrackCnt() final { android_atomic_dec(&mTrackCnt); }
+ int32_t trackCnt() const final { return android_atomic_acquire_load(&mTrackCnt); }
- void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
- void decTrackCnt() { android_atomic_dec(&mTrackCnt); }
- int32_t trackCnt() const { return android_atomic_acquire_load(&mTrackCnt); }
-
- void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt);
+ void incActiveTrackCnt() final { android_atomic_inc(&mActiveTrackCnt);
mTailBufferCount = mMaxTailBuffers; }
- void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); }
- int32_t activeTrackCnt() const { return android_atomic_acquire_load(&mActiveTrackCnt); }
+ void decActiveTrackCnt() final { android_atomic_dec(&mActiveTrackCnt); }
+ int32_t activeTrackCnt() const final {
+ return android_atomic_acquire_load(&mActiveTrackCnt);
+ }
- product_strategy_t strategy() const { return mStrategy; }
- void setStrategy(product_strategy_t strategy)
+ product_strategy_t strategy() const final { return mStrategy; }
+ void setStrategy(product_strategy_t strategy) final
{ mStrategy = strategy; }
// suspend or restore effects of the specified type. The number of suspend requests is counted
// and restore occurs once all suspend requests are cancelled.
void setEffectSuspended_l(const effect_uuid_t *type,
- bool suspend);
+ bool suspend) final;
// suspend all eligible effects
- void setEffectSuspendedAll_l(bool suspend);
+ void setEffectSuspendedAll_l(bool suspend) final;
// check if effects should be suspended or restored when a given effect is enable or disabled
- void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, bool enabled);
+ void checkSuspendOnEffectEnabled(
+ const sp<IAfEffectModule>& effect, bool enabled) final;
- void clearInputBuffer();
+ void clearInputBuffer() final;
// At least one non offloadable effect in the chain is enabled
- bool isNonOffloadableEnabled();
- bool isNonOffloadableEnabled_l();
+ bool isNonOffloadableEnabled() const final;
+ bool isNonOffloadableEnabled_l() const final;
- void syncHalEffectsState();
+ void syncHalEffectsState() final;
// flags is an ORed set of audio_output_flags_t which is updated on return.
- void checkOutputFlagCompatibility(audio_output_flags_t *flags) const;
+ void checkOutputFlagCompatibility(audio_output_flags_t *flags) const final;
// flags is an ORed set of audio_input_flags_t which is updated on return.
- void checkInputFlagCompatibility(audio_input_flags_t *flags) const;
+ void checkInputFlagCompatibility(audio_input_flags_t *flags) const final;
// Is this EffectChain compatible with the RAW audio flag.
- bool isRawCompatible() const;
+ bool isRawCompatible() const final;
// Is this EffectChain compatible with the FAST audio flag.
- bool isFastCompatible() const;
+ bool isFastCompatible() const final;
// Is this EffectChain compatible with the bit-perfect audio flag.
- bool isBitPerfectCompatible() const;
+ bool isBitPerfectCompatible() const final;
- // isCompatibleWithThread_l() must be called with thread->mLock held
- bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const;
+ // isCompatibleWithThread_l() must be called with thread->mutex() held
+ bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final;
- bool containsHapticGeneratingEffect_l();
+ bool containsHapticGeneratingEffect_l() final;
- void setHapticIntensity_l(int id, os::HapticScale intensity);
+ void setHapticIntensity_l(int id, os::HapticScale intensity) final;
- sp<EffectCallbackInterface> effectCallback() const { return mEffectCallback; }
- wp<ThreadBase> thread() const { return mEffectCallback->thread(); }
+ sp<EffectCallbackInterface> effectCallback() const final { return mEffectCallback; }
- bool isFirstEffect(int id) const { return !mEffects.isEmpty() && id == mEffects[0]->id(); }
+ wp<IAfThreadBase> thread() const final { return mEffectCallback->thread(); }
- void dump(int fd, const Vector<String16>& args);
+ bool isFirstEffect(int id) const final {
+ return !mEffects.isEmpty() && id == mEffects[0]->id();
+ }
+
+ void dump(int fd, const Vector<String16>& args) const final;
+
+ size_t numberOfEffects() const final { return mEffects.size(); }
+
+ sp<IAfEffectModule> getEffectModule(size_t index) const final {
+ return mEffects[index];
+ }
+
+ void setThread(const sp<IAfThreadBase>& thread) final;
private:
@@ -574,22 +525,17 @@
// Note: ctors taking a weak pointer to their owner must not promote it
// during construction (but may keep a reference for later promotion).
EffectCallback(const wp<EffectChain>& owner,
- const wp<ThreadBase>& thread)
+ const sp<IAfThreadBase>& thread) // we take a sp<> but store a wp<>.
: mChain(owner)
- , mThread(thread)
- , mAudioFlinger(*gAudioFlinger) {
- sp<ThreadBase> base = thread.promote();
- if (base != nullptr) {
- mThreadType = base->type();
- } else {
- mThreadType = ThreadBase::MIXER; // assure a consistent value.
- }
+ , mThread(thread) {
+ mThreadType = thread->type();
+ mAfThreadCallback = thread->afThreadCallback();
}
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
- bool updateOrphanEffectChains(const sp<EffectBase>& effect) override;
+ bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect) override;
audio_io_handle_t io() const override;
bool isOutput() const override;
@@ -609,39 +555,39 @@
status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
- bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+ bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override;
void setVolumeForOutput(float left, float right) const override;
// check if effects should be suspended/restored when a given effect is enable/disabled
- void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
+ void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect,
bool enabled, bool threadLocked) override;
void resetVolume() override;
product_strategy_t strategy() const override;
int32_t activeTrackCnt() const override;
- void onEffectEnable(const sp<EffectBase>& effect) override;
- void onEffectDisable(const sp<EffectBase>& effect) override;
+ void onEffectEnable(const sp<IAfEffectBase>& effect) override;
+ void onEffectDisable(const sp<IAfEffectBase>& effect) override;
- wp<EffectChain> chain() const override { return mChain; }
+ wp<IAfEffectChain> chain() const final { return mChain; }
- bool isAudioPolicyReady() const override {
- return mAudioFlinger.isAudioPolicyReady();
+ bool isAudioPolicyReady() const final {
+ return mAfThreadCallback->isAudioPolicyReady();
}
- wp<ThreadBase> thread() const { return mThread.load(); }
+ wp<IAfThreadBase> thread() const { return mThread.load(); }
- void setThread(const sp<ThreadBase>& thread) {
+ void setThread(const sp<IAfThreadBase>& thread) {
mThread = thread;
mThreadType = thread->type();
+ mAfThreadCallback = thread->afThreadCallback();
}
private:
- const wp<EffectChain> mChain;
- mediautils::atomic_wp<ThreadBase> mThread;
- AudioFlinger &mAudioFlinger; // implementation detail: outer instance always exists.
- ThreadBase::type_t mThreadType;
+ const wp<IAfEffectChain> mChain;
+ mediautils::atomic_wp<IAfThreadBase> mThread;
+ sp<IAfThreadCallback> mAfThreadCallback;
+ IAfThreadBase::type_t mThreadType;
};
- friend class AudioFlinger; // for mThread, mEffects
DISALLOW_COPY_AND_ASSIGN(EffectChain);
class SuspendedEffectDesc : public RefBase {
@@ -650,15 +596,15 @@
int mRefCount; // > 0 when suspended
effect_uuid_t mType;
- wp<EffectModule> mEffect;
+ wp<IAfEffectModule> mEffect;
};
// get a list of effect modules to suspend when an effect of the type
// passed is enabled.
- void getSuspendEligibleEffects(Vector< sp<EffectModule> > &effects);
+ void getSuspendEligibleEffects(Vector<sp<IAfEffectModule>> &effects);
// get an effect module if it is currently enable
- sp<EffectModule> getEffectIfEnabled(const effect_uuid_t *type);
+ sp<IAfEffectModule> getEffectIfEnabled(const effect_uuid_t *type);
// true if the effect whose descriptor is passed can be suspended
// OEMs can modify the rules implemented in this method to exclude specific effect
// types or implementations from the suspend/restore mechanism.
@@ -668,8 +614,6 @@
void clearInputBuffer_l();
- void setThread(const sp<ThreadBase>& thread);
-
// true if any effect module within the chain has volume control
bool hasVolumeControlEnabled_l() const;
@@ -679,8 +623,8 @@
std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const;
- mutable Mutex mLock; // mutex protecting effect list
- Vector< sp<EffectModule> > mEffects; // list of effect modules
+ mutable audio_utils::mutex mMutex; // mutex protecting effect list
+ Vector<sp<IAfEffectModule>> mEffects; // list of effect modules
audio_session_t mSessionId; // audio session ID
sp<EffectBufferHalInterface> mInBuffer; // chain input buffer
sp<EffectBufferHalInterface> mOutBuffer; // chain output buffer
@@ -707,35 +651,39 @@
wp<EffectModule> mVolumeControlEffect;
};
-class DeviceEffectProxy : public EffectBase {
+class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase {
public:
- DeviceEffectProxy (const AudioDeviceTypeAddr& device,
- const sp<DeviceEffectManagerCallback>& callback,
+ DeviceEffectProxy(const AudioDeviceTypeAddr& device,
+ const sp<DeviceEffectManagerCallback>& callback,
effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
: EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false),
mDevice(device), mManagerCallback(callback),
mMyCallback(new ProxyCallback(wp<DeviceEffectProxy>(this), callback)),
mNotifyFramesProcessed(notifyFramesProcessed) {}
- status_t setEnabled(bool enabled, bool fromHandle) override;
- sp<DeviceEffectProxy> asDeviceEffectProxy() override { return this; }
+ status_t setEnabled(bool enabled, bool fromHandle) final;
+ sp<IAfDeviceEffectProxy> asDeviceEffectProxy() final { return this; }
- status_t init(const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches);
- status_t onCreatePatch(audio_patch_handle_t patchHandle, const PatchPanel::Patch& patch);
- void onReleasePatch(audio_patch_handle_t patchHandle);
+ status_t init(const std::map<audio_patch_handle_t,
+ IAfPatchPanel::Patch>& patches) final;
- size_t removeEffect(const sp<EffectModule>& effect);
+ status_t onCreatePatch(audio_patch_handle_t patchHandle,
+ const IAfPatchPanel::Patch& patch) final;
- status_t addEffectToHal(const sp<EffectHalInterface>& effect);
- status_t removeEffectFromHal(const sp<EffectHalInterface>& effect);
+ void onReleasePatch(audio_patch_handle_t patchHandle) final;
- const AudioDeviceTypeAddr& device() { return mDevice; };
- bool isOutput() const;
- uint32_t sampleRate() const;
- audio_channel_mask_t channelMask() const;
- uint32_t channelCount() const;
+ size_t removeEffect(const sp<IAfEffectModule>& effect) final;
- void dump(int fd, int spaces);
+ status_t addEffectToHal(const sp<EffectHalInterface>& effect) final;
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) final;
+
+ const AudioDeviceTypeAddr& device() const final { return mDevice; };
+ bool isOutput() const final;
+ uint32_t sampleRate() const final;
+ audio_channel_mask_t channelMask() const final;
+ uint32_t channelCount() const final;
+
+ void dump2(int fd, int spaces) const final;
private:
@@ -751,7 +699,7 @@
int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
status_t allocateHalBuffer(size_t size __unused,
sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
- bool updateOrphanEffectChains(const sp<EffectBase>& effect __unused) override {
+ bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) override {
return false;
}
@@ -774,18 +722,18 @@
status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
- bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+ bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override;
void setVolumeForOutput(float left __unused, float right __unused) const override {}
- void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect __unused,
+ void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect __unused,
bool enabled __unused, bool threadLocked __unused) override {}
void resetVolume() override {}
product_strategy_t strategy() const override { return static_cast<product_strategy_t>(0); }
int32_t activeTrackCnt() const override { return 0; }
- void onEffectEnable(const sp<EffectBase>& effect __unused) override;
- void onEffectDisable(const sp<EffectBase>& effect __unused) override;
+ void onEffectEnable(const sp<IAfEffectBase>& effect __unused) override;
+ void onEffectDisable(const sp<IAfEffectBase>& effect __unused) override;
- wp<EffectChain> chain() const override { return nullptr; }
+ wp<IAfEffectChain> chain() const override { return nullptr; }
bool isAudioPolicyReady() const override {
return mManagerCallback->isAudioPolicyReady();
@@ -798,16 +746,19 @@
const sp<DeviceEffectManagerCallback> mManagerCallback;
};
- status_t checkPort(const PatchPanel::Patch& patch, const struct audio_port_config *port,
- sp<EffectHandle> *handle);
+ status_t checkPort(const IAfPatchPanel::Patch& patch,
+ const struct audio_port_config *port, sp<IAfEffectHandle> *handle);
const AudioDeviceTypeAddr mDevice;
const sp<DeviceEffectManagerCallback> mManagerCallback;
const sp<ProxyCallback> mMyCallback;
- Mutex mProxyLock;
- std::map<audio_patch_handle_t, sp<EffectHandle>> mEffectHandles; // protected by mProxyLock
- sp<EffectModule> mHalEffect; // protected by mProxyLock
+ audio_utils::mutex& proxyMutex() const { return mProxyMutex; }
+ mutable audio_utils::mutex mProxyMutex;
+ std::map<audio_patch_handle_t, sp<IAfEffectHandle>> mEffectHandles; // protected by mProxyMutex
+ sp<IAfEffectModule> mHalEffect; // protected by mProxyMutex
struct audio_port_config mDevicePort = { .id = AUDIO_PORT_HANDLE_NONE };
const bool mNotifyFramesProcessed;
};
+
+} // namespace android
diff --git a/services/audioflinger/IAfEffect.h b/services/audioflinger/IAfEffect.h
new file mode 100644
index 0000000..ea0c6d9
--- /dev/null
+++ b/services/audioflinger/IAfEffect.h
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "IAfPatchPanel.h" // full class Patch definition needed
+
+#include <android/media/AudioVibratorInfo.h>
+#include <android/media/BnEffect.h>
+#include <android/media/BnEffectClient.h>
+#include <audio_utils/mutex.h>
+#include <media/AudioCommonTypes.h> // product_strategy_t
+#include <media/AudioDeviceTypeAddr.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <utils/RefBase.h>
+#include <vibrator/ExternalVibration.h>
+
+namespace android {
+
+class Client;
+class DeviceEffectManagerCallback;
+
+class IAfDeviceEffectProxy;
+class IAfEffectBase;
+class IAfEffectChain;
+class IAfEffectHandle;
+class IAfEffectModule;
+class IAfThreadBase;
+
+// Interface implemented by the EffectModule parent or owner (e.g an EffectChain) to abstract
+// interactions between the EffectModule and the reset of the audio framework.
+class EffectCallbackInterface : public RefBase {
+public:
+ // Trivial methods usually implemented with help from ThreadBase
+ virtual audio_io_handle_t io() const = 0;
+ virtual bool isOutput() const = 0;
+ virtual bool isOffload() const = 0;
+ virtual bool isOffloadOrDirect() const = 0;
+ virtual bool isOffloadOrMmap() const = 0;
+ virtual bool isSpatializer() const = 0;
+ virtual uint32_t sampleRate() const = 0;
+ virtual audio_channel_mask_t inChannelMask(int id) const = 0;
+ virtual uint32_t inChannelCount(int id) const = 0;
+ virtual audio_channel_mask_t outChannelMask() const = 0;
+ virtual uint32_t outChannelCount() const = 0;
+ virtual audio_channel_mask_t hapticChannelMask() const = 0;
+ virtual size_t frameCount() const = 0;
+
+ // Non trivial methods usually implemented with help from ThreadBase:
+ // pay attention to mutex locking order
+ virtual uint32_t latency() const { return 0; }
+ virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+ virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
+ virtual void setVolumeForOutput(float left, float right) const = 0;
+ virtual bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) = 0;
+ virtual void checkSuspendOnEffectEnabled(
+ const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) = 0;
+ virtual void onEffectEnable(const sp<IAfEffectBase>& effect) = 0;
+ virtual void onEffectDisable(const sp<IAfEffectBase>& effect) = 0;
+
+ // Methods usually implemented with help from AudioFlinger: pay attention to mutex locking order
+ virtual status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+ int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) = 0;
+ virtual status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
+ virtual bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect) = 0;
+
+ // Methods usually implemented with help from EffectChain: pay attention to mutex locking order
+ virtual product_strategy_t strategy() const = 0;
+ virtual int32_t activeTrackCnt() const = 0;
+ virtual void resetVolume() = 0;
+ virtual wp<IAfEffectChain> chain() const = 0;
+ virtual bool isAudioPolicyReady() const = 0;
+};
+
+class IAfEffectBase : public virtual RefBase {
+ friend class EffectChain;
+ friend class EffectHandle;
+
+public:
+ enum effect_state {
+ IDLE,
+ RESTART,
+ STARTING,
+ ACTIVE,
+ STOPPING,
+ STOPPED,
+ DESTROYED
+ };
+ virtual int id() const = 0;
+ virtual effect_state state() const = 0;
+ virtual audio_session_t sessionId() const = 0;
+ virtual const effect_descriptor_t& desc() const = 0;
+ virtual bool isOffloadable() const = 0;
+ virtual bool isImplementationSoftware() const = 0;
+ virtual bool isProcessImplemented() const = 0;
+ virtual bool isVolumeControl() const = 0;
+ virtual bool isVolumeMonitor() const = 0;
+ virtual bool isEnabled() const = 0;
+ virtual bool isPinned() const = 0;
+ virtual void unPin() = 0;
+ virtual status_t updatePolicyState() = 0;
+ virtual bool purgeHandles() = 0;
+ virtual void checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) = 0;
+
+ // mCallback is atomic so this can be lock-free.
+ virtual void setCallback(const sp<EffectCallbackInterface>& callback) = 0;
+ virtual sp<EffectCallbackInterface> getCallback() const = 0;
+
+ virtual status_t addHandle(IAfEffectHandle *handle) = 0;
+ virtual ssize_t removeHandle(IAfEffectHandle *handle) = 0;
+
+ virtual sp<IAfEffectModule> asEffectModule() = 0;
+ virtual sp<IAfDeviceEffectProxy> asDeviceEffectProxy() = 0;
+
+ virtual void dump(int fd, const Vector<String16>& args) const = 0;
+
+private:
+ virtual status_t setEnabled(bool enabled, bool fromHandle) = 0;
+ virtual status_t setEnabled_l(bool enabled) = 0;
+ virtual void setSuspended(bool suspended) = 0;
+ virtual bool suspended() const = 0;
+
+ virtual status_t command(int32_t cmdCode,
+ const std::vector<uint8_t>& cmdData,
+ int32_t maxReplySize,
+ std::vector<uint8_t>* reply) = 0;
+
+ virtual ssize_t disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast) = 0;
+ virtual ssize_t removeHandle_l(IAfEffectHandle *handle) = 0;
+ virtual IAfEffectHandle* controlHandle_l() = 0;
+
+ virtual audio_utils::mutex& mutex() const = 0;
+};
+
+class IAfEffectModule : public virtual IAfEffectBase {
+ friend class DeviceEffectProxy;
+ friend class EffectChain;
+
+public:
+ static sp<IAfEffectModule> create(
+ const sp<EffectCallbackInterface>& callabck,
+ effect_descriptor_t *desc,
+ int id,
+ audio_session_t sessionId,
+ bool pinned,
+ audio_port_handle_t deviceId);
+
+ virtual int16_t *inBuffer() const = 0;
+ virtual status_t setDevices(const AudioDeviceTypeAddrVector &devices) = 0;
+ virtual status_t setInputDevice(const AudioDeviceTypeAddr &device) = 0;
+ virtual status_t setVolume(uint32_t *left, uint32_t *right, bool controller) = 0;
+ virtual status_t setOffloaded(bool offloaded, audio_io_handle_t io) = 0;
+ virtual bool isOffloaded() const = 0;
+
+ virtual status_t setAudioSource(audio_source_t source) = 0;
+ virtual status_t setMode(audio_mode_t mode) = 0;
+
+ virtual status_t start() = 0;
+ virtual status_t getConfigs(audio_config_base_t* inputCfg,
+ audio_config_base_t* outputCfg,
+ bool* isOutput) const = 0;
+
+ static bool isHapticGenerator(const effect_uuid_t* type);
+ virtual bool isHapticGenerator() const = 0;
+ virtual status_t setHapticIntensity(int id, os::HapticScale intensity) = 0;
+ virtual status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo) = 0;
+
+private:
+ virtual void process() = 0;
+ virtual bool updateState() = 0;
+ virtual void reset_l() = 0;
+ virtual status_t configure() = 0;
+ virtual status_t init() = 0;
+ virtual uint32_t status() const = 0;
+ virtual bool isProcessEnabled() const = 0;
+ virtual bool isOffloadedOrDirect() const = 0;
+ virtual bool isVolumeControlEnabled() const = 0;
+
+ virtual void setInBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+ virtual void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+ virtual int16_t *outBuffer() const = 0;
+
+ // Updates the access mode if it is out of date. May issue a new effect configure.
+ virtual void updateAccessMode() = 0;
+
+ virtual status_t stop() = 0;
+ virtual void addEffectToHal_l() = 0;
+ virtual void release_l() = 0;
+};
+
+class IAfEffectChain : public RefBase {
+ // Most of these methods are accessed from AudioFlinger::Thread
+public:
+ static sp<IAfEffectChain> create(
+ const sp<IAfThreadBase>& thread,
+ audio_session_t sessionId);
+
+ // special key used for an entry in mSuspendedEffects keyed vector
+ // corresponding to a suspend all request.
+ static constexpr int kKeyForSuspendAll = 0;
+
+ // minimum duration during which we force calling effect process when last track on
+ // a session is stopped or removed to allow effect tail to be rendered
+ static constexpr int kProcessTailDurationMs = 1000;
+
+ virtual void process_l() = 0;
+
+ virtual audio_utils::mutex& mutex() const = 0;
+
+ virtual status_t createEffect_l(sp<IAfEffectModule>& effect,
+ effect_descriptor_t *desc,
+ int id,
+ audio_session_t sessionId,
+ bool pinned) = 0;
+
+ virtual status_t addEffect_l(const sp<IAfEffectModule>& handle) = 0;
+ virtual status_t addEffect_ll(const sp<IAfEffectModule>& handle) = 0;
+ virtual size_t removeEffect_l(const sp<IAfEffectModule>& handle, bool release = false) = 0;
+
+ virtual audio_session_t sessionId() const = 0;
+ virtual void setSessionId(audio_session_t sessionId) = 0;
+
+ virtual sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor) const = 0;
+ virtual sp<IAfEffectModule> getEffectFromId_l(int id) const = 0;
+ virtual sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t *type) const = 0;
+ virtual std::vector<int> getEffectIds() const = 0;
+ virtual bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false) = 0;
+ virtual void resetVolume_l() = 0;
+ virtual void setDevices_l(const AudioDeviceTypeAddrVector &devices) = 0;
+ virtual void setInputDevice_l(const AudioDeviceTypeAddr &device) = 0;
+ virtual void setMode_l(audio_mode_t mode) = 0;
+ virtual void setAudioSource_l(audio_source_t source) = 0;
+
+ virtual void setInBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+ virtual float *inBuffer() const = 0;
+ virtual void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+ virtual float *outBuffer() const = 0;
+
+ virtual void incTrackCnt() = 0;
+ virtual void decTrackCnt() = 0;
+ virtual int32_t trackCnt() const = 0;
+
+ virtual void incActiveTrackCnt() = 0;
+ virtual void decActiveTrackCnt() = 0;
+ virtual int32_t activeTrackCnt() const = 0;
+
+ virtual product_strategy_t strategy() const = 0;
+ virtual void setStrategy(product_strategy_t strategy) = 0;
+
+ // suspend or restore effects of the specified type. The number of suspend requests is counted
+ // and restore occurs once all suspend requests are cancelled.
+ virtual void setEffectSuspended_l(
+ const effect_uuid_t *type, bool suspend) = 0;
+ // suspend all eligible effects
+ virtual void setEffectSuspendedAll_l(bool suspend) = 0;
+ // check if effects should be suspended or restored when a given effect is enable or disabled
+ virtual void checkSuspendOnEffectEnabled(const sp<IAfEffectModule>& effect, bool enabled) = 0;
+
+ virtual void clearInputBuffer() = 0;
+
+ // At least one non offloadable effect in the chain is enabled
+ virtual bool isNonOffloadableEnabled() const = 0;
+ virtual bool isNonOffloadableEnabled_l() const = 0;
+
+ virtual void syncHalEffectsState() = 0;
+
+ // flags is an ORed set of audio_output_flags_t which is updated on return.
+ virtual void checkOutputFlagCompatibility(audio_output_flags_t *flags) const = 0;
+
+ // flags is an ORed set of audio_input_flags_t which is updated on return.
+ virtual void checkInputFlagCompatibility(audio_input_flags_t *flags) const = 0;
+
+ // Is this EffectChain compatible with the RAW audio flag.
+ virtual bool isRawCompatible() const = 0;
+
+ // Is this EffectChain compatible with the FAST audio flag.
+ virtual bool isFastCompatible() const = 0;
+
+ // Is this EffectChain compatible with the bit-perfect audio flag.
+ virtual bool isBitPerfectCompatible() const = 0;
+
+ // isCompatibleWithThread_l() must be called with thread->mLock held
+ virtual bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const = 0;
+
+ virtual bool containsHapticGeneratingEffect_l() = 0;
+
+ virtual void setHapticIntensity_l(int id, os::HapticScale intensity) = 0;
+
+ virtual sp<EffectCallbackInterface> effectCallback() const = 0;
+
+ virtual wp<IAfThreadBase> thread() const = 0;
+ virtual void setThread(const sp<IAfThreadBase>& thread) = 0;
+
+ virtual bool isFirstEffect(int id) const = 0;
+
+ virtual size_t numberOfEffects() const = 0;
+ virtual sp<IAfEffectModule> getEffectModule(size_t index) const = 0;
+
+ virtual void dump(int fd, const Vector<String16>& args) const = 0;
+};
+
+class IAfEffectHandle : public virtual RefBase {
+ friend class EffectBase;
+ friend class EffectChain;
+ friend class EffectModule;
+
+public:
+ static sp<IAfEffectHandle> create(
+ const sp<IAfEffectBase>& effect,
+ const sp<Client>& client,
+ const sp<media::IEffectClient>& effectClient,
+ int32_t priority, bool notifyFramesProcessed);
+
+ virtual status_t initCheck() const = 0;
+ virtual bool enabled() const = 0;
+ virtual int id() const = 0;
+ virtual wp<IAfEffectBase> effect() const = 0;
+ virtual sp<android::media::IEffect> asIEffect() = 0;
+ virtual const sp<Client>& client() const = 0;
+
+private:
+ virtual void setControl(bool hasControl, bool signal, bool enabled) = 0;
+ virtual bool hasControl() const = 0;
+ virtual void setEnabled(bool enabled) = 0;
+ virtual bool disconnected() const = 0;
+ virtual int priority() const = 0;
+
+ virtual void commandExecuted(uint32_t cmdCode,
+ const std::vector<uint8_t>& cmdData,
+ const std::vector<uint8_t>& replyData) = 0;
+ virtual void framesProcessed(int32_t frames) const = 0;
+
+ virtual void dumpToBuffer(char* buffer, size_t size) const = 0;
+};
+
+class IAfDeviceEffectProxy : public virtual IAfEffectBase {
+public:
+ static sp<IAfDeviceEffectProxy> create(const AudioDeviceTypeAddr& device,
+ const sp<DeviceEffectManagerCallback>& callback,
+ effect_descriptor_t *desc, int id, bool notifyFramesProcessed);
+
+ virtual status_t init(
+ const std::map<audio_patch_handle_t,
+ IAfPatchPanel::Patch>& patches) = 0;
+ virtual const AudioDeviceTypeAddr& device() const = 0;
+
+ virtual status_t onCreatePatch(
+ audio_patch_handle_t patchHandle,
+ const IAfPatchPanel::Patch& patch) = 0;
+ virtual void onReleasePatch(audio_patch_handle_t patchHandle) = 0;
+
+ virtual void dump2(int fd, int spaces) const = 0; // TODO(b/291319101) naming?
+
+private:
+ // used by DeviceEffectProxy
+ virtual bool isOutput() const = 0;
+ virtual uint32_t sampleRate() const = 0;
+ virtual audio_channel_mask_t channelMask() const = 0;
+ virtual uint32_t channelCount() const = 0;
+
+ virtual size_t removeEffect(const sp<IAfEffectModule>& effect) = 0;
+ virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+ virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
+};
+
+} // namespace android
diff --git a/services/audioflinger/IAfPatchPanel.h b/services/audioflinger/IAfPatchPanel.h
new file mode 100644
index 0000000..5a6621e
--- /dev/null
+++ b/services/audioflinger/IAfPatchPanel.h
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// The following includes are required because we have class definitions below
+// for EndPoint and Patch, which precludes using a forward declaration only.
+#include "IAfThread.h" // IAfThreadBase IAfMmapThread IAfPlaybackThread IAfRecordThread
+#include "IAfTrack.h" // IAfPatchRecord IAfPatchTrack
+
+#include <datapath/AudioHwDevice.h>
+#include <media/DeviceDescriptorBase.h>
+#include <utils/Log.h> // ALOG used in this file
+#include <utils/RefBase.h> // avoid transitive dependency
+#include <utils/Thread.h>
+
+namespace android {
+
+class IAfPatchPanel;
+class PatchCommandThread;
+
+class SoftwarePatch {
+public:
+ SoftwarePatch(
+ const sp<const IAfPatchPanel>& patchPanel,
+ audio_patch_handle_t patchHandle,
+ audio_io_handle_t playbackThreadHandle,
+ audio_io_handle_t recordThreadHandle)
+ : mPatchPanel(patchPanel),
+ mPatchHandle(patchHandle),
+ mPlaybackThreadHandle(playbackThreadHandle),
+ mRecordThreadHandle(recordThreadHandle) {}
+ SoftwarePatch(const SoftwarePatch&) = default;
+
+ status_t getLatencyMs_l(double* latencyMs) const REQUIRES(audio_utils::AudioFlinger_Mutex);
+ audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
+ audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
+ audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
+
+private:
+ const sp<const IAfPatchPanel> mPatchPanel;
+ const audio_patch_handle_t mPatchHandle;
+ const audio_io_handle_t mPlaybackThreadHandle;
+ const audio_io_handle_t mRecordThreadHandle;
+};
+
+class IAfPatchPanelCallback : public virtual RefBase {
+public:
+ virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) REQUIRES(mutex()) = 0;
+ virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) REQUIRES(mutex()) = 0;
+ virtual IAfPlaybackThread* primaryPlaybackThread_l() const REQUIRES(mutex()) = 0;
+ virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const
+ REQUIRES(mutex()) = 0;
+ virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const
+ REQUIRES(mutex()) = 0;
+ virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const REQUIRES(mutex()) = 0;
+ virtual sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
+ audio_io_handle_t* input,
+ audio_config_t* config,
+ audio_devices_t device,
+ const char* address,
+ audio_source_t source,
+ audio_input_flags_t flags,
+ audio_devices_t outputDevice,
+ const String8& outputDeviceAddress) REQUIRES(mutex()) = 0;
+ virtual sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
+ audio_io_handle_t* output,
+ audio_config_t* halConfig,
+ audio_config_base_t* mixerConfig,
+ audio_devices_t deviceType,
+ const String8& address,
+ audio_output_flags_t flags) REQUIRES(mutex()) = 0;
+ virtual audio_utils::mutex& mutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
+ virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+ getAudioHwDevs_l() const REQUIRES(mutex()) = 0;
+ virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
+ virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+ virtual void updateDownStreamPatches_l(
+ const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams)
+ REQUIRES(mutex()) = 0;
+ virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices)
+ REQUIRES(mutex()) = 0;
+};
+
+class IAfPatchPanel : public virtual RefBase {
+public:
+ static sp<IAfPatchPanel> create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback);
+
+ // Extraction of inner Endpoint and Patch classes would require interfaces
+ // (in the Endpoint case a templated interface) but that seems
+ // excessive for now. We keep them as inner classes until extraction
+ // is needed.
+ template <typename ThreadType, typename TrackType>
+ class Endpoint final {
+ public:
+ Endpoint() = default;
+ Endpoint(const Endpoint&) = delete;
+ Endpoint& operator=(const Endpoint& other) noexcept {
+ mThread = other.mThread;
+ mCloseThread = other.mCloseThread;
+ mHandle = other.mHandle;
+ mTrack = other.mTrack;
+ return *this;
+ }
+ Endpoint(Endpoint&& other) noexcept { swap(other); }
+ Endpoint& operator=(Endpoint&& other) noexcept {
+ swap(other);
+ return *this;
+ }
+ ~Endpoint() {
+ ALOGE_IF(
+ mHandle != AUDIO_PATCH_HANDLE_NONE,
+ "A non empty Patch Endpoint leaked, handle %d", mHandle);
+ }
+
+ status_t checkTrack(TrackType* trackOrNull) const {
+ if (trackOrNull == nullptr) return NO_MEMORY;
+ return trackOrNull->initCheck();
+ }
+ audio_patch_handle_t handle() const { return mHandle; }
+ sp<ThreadType> thread() const { return mThread; }
+ sp<TrackType> track() const { return mTrack; }
+ sp<const ThreadType> const_thread() const { return mThread; }
+ sp<const TrackType> const_track() const { return mTrack; }
+
+ void closeConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex)
+ NO_THREAD_SAFETY_ANALYSIS // this is broken in clang
+ {
+ if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
+ panel->releaseAudioPatch_l(mHandle);
+ mHandle = AUDIO_PATCH_HANDLE_NONE;
+ }
+ if (mThread != nullptr) {
+ if (mTrack != nullptr) {
+ mThread->deletePatchTrack(mTrack);
+ }
+ if (mCloseThread) {
+ panel->closeThreadInternal_l(mThread);
+ }
+ }
+ }
+ audio_patch_handle_t* handlePtr() { return &mHandle; }
+ void setThread(const sp<ThreadType>& thread, bool closeThread = true) {
+ mThread = thread;
+ mCloseThread = closeThread;
+ }
+ template <typename T>
+ void setTrackAndPeer(const sp<TrackType>& track, const sp<T>& peer, bool holdReference) {
+ mTrack = track;
+ mThread->addPatchTrack(mTrack);
+ mTrack->setPeerProxy(peer, holdReference);
+ mClearPeerProxy = holdReference;
+ }
+ void clearTrackPeer() {
+ if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy();
+ }
+ void stopTrack() {
+ if (mTrack) mTrack->stop();
+ }
+
+ void swap(Endpoint& other) noexcept {
+ using std::swap;
+ swap(mThread, other.mThread);
+ swap(mCloseThread, other.mCloseThread);
+ swap(mClearPeerProxy, other.mClearPeerProxy);
+ swap(mHandle, other.mHandle);
+ swap(mTrack, other.mTrack);
+ }
+
+ friend void swap(Endpoint& a, Endpoint& b) noexcept { a.swap(b); }
+
+ private:
+ sp<ThreadType> mThread;
+ bool mCloseThread = true;
+ bool mClearPeerProxy = true;
+ audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE;
+ sp<TrackType> mTrack;
+ };
+
+ class Patch final {
+ public:
+ Patch(const struct audio_patch& patch, bool endpointPatch)
+ : mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {}
+ Patch() = default;
+ ~Patch();
+ Patch(const Patch& other) noexcept {
+ mAudioPatch = other.mAudioPatch;
+ mHalHandle = other.mHalHandle;
+ mPlayback = other.mPlayback;
+ mRecord = other.mRecord;
+ mThread = other.mThread;
+ mIsEndpointPatch = other.mIsEndpointPatch;
+ }
+ Patch(Patch&& other) noexcept { swap(other); }
+ Patch& operator=(Patch&& other) noexcept {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Patch& other) noexcept {
+ using std::swap;
+ swap(mAudioPatch, other.mAudioPatch);
+ swap(mHalHandle, other.mHalHandle);
+ swap(mPlayback, other.mPlayback);
+ swap(mRecord, other.mRecord);
+ swap(mThread, other.mThread);
+ swap(mIsEndpointPatch, other.mIsEndpointPatch);
+ }
+
+ friend void swap(Patch& a, Patch& b) noexcept { a.swap(b); }
+
+ status_t createConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void clearConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ bool isSoftware() const {
+ return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
+ mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE;
+ }
+
+ void setThread(const sp<IAfThreadBase>& thread) { mThread = thread; }
+ wp<IAfThreadBase> thread() const { return mThread; }
+
+ // returns the latency of the patch (from record to playback).
+ status_t getLatencyMs(double* latencyMs) const;
+
+ String8 dump(audio_patch_handle_t myHandle) const;
+
+ // Note that audio_patch::id is only unique within a HAL module
+ struct audio_patch mAudioPatch;
+ // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0
+ audio_patch_handle_t mHalHandle = AUDIO_PATCH_HANDLE_NONE;
+ // below members are used by a software audio patch connecting a source device from a
+ // given audio HW module to a sink device on an other audio HW module.
+ // the objects are created by createConnections() and released by clearConnections()
+ // playback thread is created if no existing playback thread can be used
+ // connects playback thread output to sink device
+ Endpoint<IAfPlaybackThread, IAfPatchTrack> mPlayback;
+ // connects source device to record thread input
+ Endpoint<IAfRecordThread, IAfPatchRecord> mRecord;
+
+ wp<IAfThreadBase> mThread;
+ bool mIsEndpointPatch;
+ };
+
+ /* List connected audio ports and their attributes */
+ virtual status_t listAudioPorts_l(unsigned int* num_ports, struct audio_port* ports)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ /* Get supported attributes for a given audio port */
+ virtual status_t getAudioPort_l(struct audio_port_v7* port)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ /* Create a patch between several source and sink ports */
+ virtual status_t createAudioPatch_l(
+ const struct audio_patch* patch,
+ audio_patch_handle_t* handle,
+ bool endpointPatch = false)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ /* Release a patch */
+ virtual status_t releaseAudioPatch_l(audio_patch_handle_t handle)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ /* List connected audio devices and they attributes */
+ virtual status_t listAudioPatches_l(unsigned int* num_patches, struct audio_patch* patches)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ // Retrieves all currently estrablished software patches for a stream
+ // opened on an intermediate module.
+ virtual status_t getDownstreamSoftwarePatches(
+ audio_io_handle_t stream, std::vector<SoftwarePatch>* patches) const = 0;
+
+ // Notifies patch panel about all opened and closed streams.
+ virtual void notifyStreamOpened(
+ AudioHwDevice* audioHwDevice, audio_io_handle_t stream, struct audio_patch* patch) = 0;
+
+ virtual void notifyStreamClosed(audio_io_handle_t stream) = 0;
+
+ virtual void dump(int fd) const = 0;
+
+ virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+};
+
+} // namespace android
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
new file mode 100644
index 0000000..fc2f805
--- /dev/null
+++ b/services/audioflinger/IAfThread.h
@@ -0,0 +1,621 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/media/IAudioTrackCallback.h>
+#include <android/media/IEffectClient.h>
+#include <audiomanager/IAudioManager.h>
+#include <audio_utils/mutex.h>
+#include <audio_utils/MelProcessor.h>
+#include <binder/MemoryDealer.h>
+#include <datapath/AudioStreamIn.h>
+#include <datapath/AudioStreamOut.h>
+#include <datapath/VolumeInterface.h>
+#include <fastpath/FastMixerDumpState.h>
+#include <media/DeviceDescriptorBase.h>
+#include <media/MmapStreamInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+#include <media/nblog/NBLog.h>
+#include <timing/SyncEvent.h>
+#include <utils/RefBase.h>
+#include <vibrator/ExternalVibration.h>
+
+#include <optional>
+
+namespace android {
+
+class IAfDirectOutputThread;
+class IAfDuplicatingThread;
+class IAfMmapCaptureThread;
+class IAfMmapPlaybackThread;
+class IAfPlaybackThread;
+class IAfRecordThread;
+
+class IAfEffectChain;
+class IAfEffectHandle;
+class IAfEffectModule;
+class IAfPatchPanel;
+class IAfPatchRecord;
+class IAfPatchTrack;
+class IAfRecordTrack;
+class IAfTrack;
+class IAfTrackBase;
+class Client;
+class MelReporter;
+
+// Used internally for Threads.cpp and AudioFlinger.cpp
+struct stream_type_t {
+ float volume = 1.f;
+ bool mute = false;
+};
+
+// Note this is exposed through IAfThreadBase::afThreadCallback()
+// and hence may be used by the Effect / Track framework.
+class IAfThreadCallback : public virtual RefBase {
+public:
+ virtual audio_utils::mutex& mutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
+ virtual bool isNonOffloadableGlobalEffectEnabled_l() const
+ REQUIRES(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
+ REQUIRES(mutex()) = 0;
+ virtual bool masterMute_l() const
+ REQUIRES(mutex()) = 0;
+ virtual float getMasterBalance_l() const
+ REQUIRES(mutex()) = 0;
+ virtual bool streamMute_l(audio_stream_type_t stream) const
+ REQUIRES(mutex()) = 0;
+ virtual audio_mode_t getMode() const = 0;
+ virtual bool isLowRamDevice() const = 0;
+ virtual bool isAudioPolicyReady() const = 0; // Effects
+ virtual uint32_t getScreenState() const = 0;
+ virtual std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const
+ REQUIRES(mutex()) = 0;
+ virtual const sp<IAfPatchPanel>& getPatchPanel() const = 0;
+ virtual const sp<MelReporter>& getMelReporter() const = 0;
+ virtual const sp<EffectsFactoryHalInterface>& getEffectsFactoryHal() const = 0;
+ virtual sp<IAudioManager> getOrCreateAudioManager() = 0; // Tracks
+
+ virtual bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect)
+ EXCLUDES_AudioFlinger_Mutex = 0;
+ virtual status_t moveEffectChain_ll(audio_session_t sessionId,
+ IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
+ REQUIRES(mutex(), audio_utils::ThreadBase_Mutex) = 0;
+
+ virtual void requestLogMerge() = 0;
+ virtual sp<NBLog::Writer> newWriter_l(size_t size, const char *name)
+ REQUIRES(mutex()) = 0;
+ virtual void unregisterWriter(const sp<NBLog::Writer>& writer) = 0;
+
+ virtual sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
+ audio_session_t triggerSession,
+ audio_session_t listenerSession,
+ const audioflinger::SyncEventCallback& callBack,
+ const wp<IAfTrackBase>& cookie)
+ EXCLUDES_AudioFlinger_Mutex = 0;
+
+ virtual void ioConfigChanged(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;
+ virtual void onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes)
+ EXCLUDES_AudioFlinger_ClientMutex = 0;
+};
+
+class IAfThreadBase : public virtual RefBase {
+public:
+ enum type_t {
+ MIXER, // Thread class is MixerThread
+ DIRECT, // Thread class is DirectOutputThread
+ DUPLICATING, // Thread class is DuplicatingThread
+ RECORD, // Thread class is RecordThread
+ OFFLOAD, // Thread class is OffloadThread
+ MMAP_PLAYBACK, // Thread class for MMAP playback stream
+ MMAP_CAPTURE, // Thread class for MMAP capture stream
+ SPATIALIZER, //
+ BIT_PERFECT, // Thread class for BitPerfectThread
+ // When adding a value, also update IAfThreadBase::threadTypeToString()
+ };
+
+ static const char* threadTypeToString(type_t type);
+ static std::string formatToString(audio_format_t format); // compliant for MediaMetrics
+ static bool isValidPcmSinkChannelMask(audio_channel_mask_t channelMask);
+ static bool isValidPcmSinkFormat(audio_format_t format);
+
+ virtual status_t readyToRun() = 0;
+ virtual void clearPowerManager() = 0;
+ virtual status_t initCheck() const = 0;
+ virtual type_t type() const = 0;
+ virtual bool isDuplicating() const = 0;
+ virtual audio_io_handle_t id() const = 0;
+ virtual uint32_t sampleRate() const = 0;
+ virtual audio_channel_mask_t channelMask() const = 0;
+ virtual audio_channel_mask_t mixerChannelMask() const = 0;
+ virtual audio_format_t format() const = 0;
+ virtual uint32_t channelCount() const = 0;
+
+ // Called by AudioFlinger::frameCount(audio_io_handle_t output) and effects,
+ // and returns the [normal mix] buffer's frame count.
+ 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;
+
+ // 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(
+ audio_io_config_event_t event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+
+ // sendConfigEvent_l() must be called with ThreadBase::mLock held
+ // Can temporarily release the lock if waiting for a reply from
+ // processConfigEvents_l().
+ // 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;
+ 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;
+ 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;
+ 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;
+
+ virtual void processConfigEvents_l() = 0;
+ virtual void setCheckOutputStageEffects() = 0;
+ virtual void cacheParameters_l() = 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;
+
+ // 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 AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const = 0;
+ virtual const AudioDeviceTypeAddr& inDeviceTypeAddr() const = 0;
+ virtual bool isOutput() const = 0;
+ virtual bool isOffloadOrMmap() const = 0;
+ virtual sp<StreamHalInterface> stream() const = 0;
+ virtual sp<IAfEffectHandle> createEffect_l(
+ const sp<Client>& client,
+ const sp<media::IEffectClient>& effectClient,
+ int32_t priority,
+ audio_session_t sessionId,
+ effect_descriptor_t* desc,
+ int* enabled,
+ status_t* status /*non-NULL*/,
+ bool pinned,
+ bool probe,
+ bool notifyFramesProcessed)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ // return values for hasAudioSession (bit field)
+ enum effect_state {
+ EFFECT_SESSION = 0x1, // the audio session corresponds to at least one
+ // effect
+ TRACK_SESSION = 0x2, // the audio session corresponds to at least one
+ // track
+ FAST_SESSION = 0x4, // the audio session corresponds to at least one
+ // fast track
+ SPATIALIZED_SESSION = 0x8, // the audio session corresponds to at least one
+ // spatialized track
+ BIT_PERFECT_SESSION = 0x10 // the audio session corresponds to at least one
+ // bit-perfect track
+ };
+
+ // get effect chain corresponding to session Id.
+ virtual sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const = 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;
+ // add an effect chain to the chain list (mEffectChains)
+ virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
+ // remove an effect chain from the chain list (mEffectChains)
+ virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) = 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;
+ // unlock effect chains after process
+ virtual void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) = 0;
+ // get a copy of mEffectChains vector
+ virtual Vector<sp<IAfEffectChain>> getEffectChains_l() const = 0;
+ // set audio mode to all effect chains
+ virtual void setMode(audio_mode_t mode) = 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;
+ // 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
+ virtual status_t addEffect_ll(const sp<IAfEffectModule>& effect)
+ 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;
+ // disconnect an effect handle from module and destroy module if last handle
+ virtual void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast) = 0;
+ // detach all tracks connected to an auxiliary effect
+ virtual void detachAuxEffect_l(int effectId) = 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;
+
+ // 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;
+
+ // 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;
+
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+ 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
+ // objects that will be read-only to client processes, read/write to mediaserver,
+ // and shared by all client processes of the thread.
+ // The heap is per-thread rather than common across all threads, because
+ // clients can't be trusted not to modify the offset of the IMemory they receive.
+ // If a thread does not have such a heap, this method returns 0.
+ virtual sp<MemoryDealer> readOnlyHeap() const = 0;
+
+ virtual sp<IMemory> pipeMemory() const = 0;
+
+ virtual void systemReady() = 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;
+
+ virtual void broadcast_l() = 0;
+
+ virtual bool isTimestampCorrectionEnabled() const = 0;
+
+ virtual bool isMsdDevice() const = 0;
+
+ virtual void dump(int fd, const Vector<String16>& args) = 0;
+
+ // deliver stats to mediametrics.
+ virtual void sendStatistics(bool force) = 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;
+
+ // invalidateTracksForAudioSession_l must be called with holding mLock.
+ virtual void invalidateTracksForAudioSession_l(audio_session_t sessionId) const = 0;
+ // Invalidate all the tracks with the given audio session.
+ virtual void invalidateTracksForAudioSession(audio_session_t sessionId) const = 0;
+
+ virtual bool isStreamInitialized() const = 0;
+ virtual void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+ virtual void stopMelComputation_l()
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+ virtual product_strategy_t getStrategyForStream(audio_stream_type_t stream) const = 0;
+
+ virtual void setEffectSuspended_l(
+ const effect_uuid_t* type, bool suspend, audio_session_t sessionId) = 0;
+
+ // Dynamic cast to derived interface
+ virtual sp<IAfDirectOutputThread> asIAfDirectOutputThread() { return nullptr; }
+ virtual sp<IAfDuplicatingThread> asIAfDuplicatingThread() { return nullptr; }
+ virtual sp<IAfPlaybackThread> asIAfPlaybackThread() { return nullptr; }
+ virtual sp<IAfRecordThread> asIAfRecordThread() { return nullptr; }
+ virtual IAfThreadCallback* afThreadCallback() const = 0;
+};
+
+class IAfPlaybackThread : public virtual IAfThreadBase, public virtual VolumeInterface {
+public:
+ static sp<IAfPlaybackThread> createBitPerfectThread(
+ const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+ audio_io_handle_t id, bool systemReady);
+
+ static sp<IAfPlaybackThread> createDirectOutputThread(
+ const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+ audio_io_handle_t id, bool systemReady, const audio_offload_info_t& offloadInfo);
+
+ static sp<IAfPlaybackThread> createMixerThread(
+ const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+ audio_io_handle_t id, bool systemReady, type_t type = MIXER,
+ audio_config_base_t* mixerConfig = nullptr);
+
+ static sp<IAfPlaybackThread> createOffloadThread(
+ const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+ audio_io_handle_t id, bool systemReady, const audio_offload_info_t& offloadInfo);
+
+ static sp<IAfPlaybackThread> createSpatializerThread(
+ const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+ audio_io_handle_t id, bool systemReady, audio_config_base_t* mixerConfig);
+
+ static constexpr int8_t kMaxTrackStopRetriesOffload = 2;
+
+ enum mixer_state {
+ MIXER_IDLE, // no active tracks
+ MIXER_TRACKS_ENABLED, // at least one active track, but no track has any data ready
+ MIXER_TRACKS_READY, // at least one active track, and at least one track has data
+ MIXER_DRAIN_TRACK, // drain currently playing track
+ MIXER_DRAIN_ALL, // fully drain the hardware
+ // standby mode does not have an enum value
+ // suspend by audio policy manager is orthogonal to mixer state
+ };
+
+ // 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 sp<IAfTrack> createTrack_l(
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ const audio_attributes_t& attr,
+ uint32_t* sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t* pFrameCount,
+ size_t* pNotificationFrameCount,
+ uint32_t notificationsPerBuffer,
+ float speed,
+ const sp<IMemory>& sharedBuffer,
+ audio_session_t sessionId,
+ audio_output_flags_t* flags,
+ pid_t creatorPid,
+ const AttributionSourceState& attributionSource,
+ pid_t tid,
+ status_t* status /*non-NULL*/,
+ audio_port_handle_t portId,
+ const sp<media::IAudioTrackCallback>& callback,
+ bool isSpatialized,
+ 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 AudioStreamOut* getOutput_l() const = 0;
+ virtual AudioStreamOut* getOutput() const = 0;
+ virtual AudioStreamOut* clearOutput() = 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;
+ // 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;
+
+ // 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;
+ // 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 status_t getTimestamp_l(AudioTimestamp& timestamp) = 0;
+ virtual void addPatchTrack(const sp<IAfPatchTrack>& track) = 0;
+ virtual void deletePatchTrack(const sp<IAfPatchTrack>& track) = 0;
+
+ // Return the asynchronous signal wait time.
+ virtual int64_t computeWaitTimeNs_l() const = 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;
+
+ virtual bool supportsHapticPlayback() const = 0;
+
+ virtual void setDownStreamPatch(const struct audio_patch* patch) = 0;
+
+ virtual IAfTrack* getTrackById_l(audio_port_handle_t trackId) = 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 setBluetoothVariableLatencyEnabled(bool enabled) = 0;
+
+ virtual void setStandby() = 0;
+ virtual void setStandby_l() = 0;
+ virtual bool waitForHalStart() = 0;
+
+ virtual bool hasFastMixer() const = 0;
+ virtual FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex) const = 0;
+ virtual const std::atomic<int64_t>& framesWritten() const = 0;
+
+ virtual bool usesHwAvSync() const = 0;
+};
+
+class IAfDirectOutputThread : public virtual IAfPlaybackThread {
+public:
+ virtual status_t selectPresentation(int presentationId, int programId) = 0;
+};
+
+class IAfDuplicatingThread : public virtual IAfPlaybackThread {
+public:
+ static sp<IAfDuplicatingThread> create(
+ const sp<IAfThreadCallback>& afThreadCallback, IAfPlaybackThread* mainThread,
+ audio_io_handle_t id, bool systemReady);
+
+ virtual void addOutputTrack(IAfPlaybackThread* thread) = 0;
+ virtual uint32_t waitTimeMs() const = 0;
+ virtual void removeOutputTrack(IAfPlaybackThread* thread) = 0;
+};
+
+class IAfRecordThread : public virtual IAfThreadBase {
+public:
+ static sp<IAfRecordThread> create(
+ const sp<IAfThreadCallback>& afThreadCallback, AudioStreamIn* input,
+ audio_io_handle_t id, bool systemReady);
+
+ virtual sp<IAfRecordTrack> createRecordTrack_l(
+ const sp<Client>& client,
+ const audio_attributes_t& attr,
+ uint32_t* pSampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t* pFrameCount,
+ audio_session_t sessionId,
+ size_t* pNotificationFrameCount,
+ pid_t creatorPid,
+ const AttributionSourceState& attributionSource,
+ audio_input_flags_t* flags,
+ pid_t tid,
+ 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;
+
+ virtual status_t start(
+ IAfRecordTrack* recordTrack, AudioSystem::sync_event_t event,
+ audio_session_t triggerSession) = 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 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;
+
+ virtual void addPatchTrack(const sp<IAfPatchRecord>& record) = 0;
+ virtual void deletePatchTrack(const sp<IAfPatchRecord>& record) = 0;
+ virtual bool fastTrackAvailable() const = 0;
+ virtual void setFastTrackAvailable(bool available) = 0;
+
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
+ virtual bool hasFastCapture() const = 0;
+
+ virtual void checkBtNrec() = 0;
+ virtual uint32_t getInputFramesLost() const = 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;
+};
+
+class IAfMmapThread : public virtual IAfThreadBase {
+public:
+ // createIAudioTrackAdapter() is a static constructor which creates an
+ // MmapStreamInterface AIDL interface adapter from the MmapThread object that
+ // may be passed back to the client.
+ //
+ // Only one AIDL MmapStreamInterface interface adapter should be created per MmapThread.
+ static sp<MmapStreamInterface> createMmapStreamInterfaceAdapter(
+ const sp<IAfMmapThread>& mmapThread);
+
+ virtual void configure(
+ 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) = 0;
+ virtual void disconnect() = 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;
+ 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;
+
+ // TODO(b/291317898) move to IAfThreadBase?
+ virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds) = 0;
+
+ // Sets the UID records silence - TODO(b/291317898) move to IAfMmapCaptureThread
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
+
+ virtual sp<IAfMmapPlaybackThread> asIAfMmapPlaybackThread() { return nullptr; }
+ virtual sp<IAfMmapCaptureThread> asIAfMmapCaptureThread() { return nullptr; }
+};
+
+class IAfMmapPlaybackThread : public virtual IAfMmapThread, public virtual VolumeInterface {
+public:
+ static sp<IAfMmapPlaybackThread> create(
+ const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
+ AudioHwDevice* hwDev, AudioStreamOut* output, bool systemReady);
+
+ virtual AudioStreamOut* clearOutput() = 0;
+};
+
+class IAfMmapCaptureThread : public virtual IAfMmapThread {
+public:
+ static sp<IAfMmapCaptureThread> create(
+ const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
+ AudioHwDevice* hwDev, AudioStreamIn* input, bool systemReady);
+
+ virtual AudioStreamIn* clearInput() = 0;
+};
+
+} // namespace android
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
new file mode 100644
index 0000000..cf30ded
--- /dev/null
+++ b/services/audioflinger/IAfTrack.h
@@ -0,0 +1,595 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/media/BnAudioRecord.h>
+#include <android/media/BnAudioTrack.h>
+#include <audiomanager/IAudioManager.h>
+#include <binder/IMemory.h>
+#include <fastpath/FastMixerDumpState.h>
+#include <media/AudioSystem.h>
+#include <media/VolumeShaper.h>
+#include <private/media/AudioTrackShared.h>
+#include <timing/SyncEvent.h>
+#include <timing/SynchronizedRecordState.h>
+#include <utils/RefBase.h>
+#include <vibrator/ExternalVibration.h>
+
+#include <vector>
+
+namespace android {
+
+class Client;
+class ResamplerBufferProvider;
+struct Source;
+
+class IAfDuplicatingThread;
+class IAfPatchRecord;
+class IAfPatchTrack;
+class IAfPlaybackThread;
+class IAfRecordThread;
+class IAfThreadBase;
+
+struct TeePatch {
+ sp<IAfPatchRecord> patchRecord;
+ sp<IAfPatchTrack> patchTrack;
+};
+
+using TeePatches = std::vector<TeePatch>;
+
+// Common interface to all Playback and Record tracks.
+class IAfTrackBase : public virtual RefBase {
+public:
+ enum track_state : int32_t {
+ IDLE,
+ FLUSHED, // for PlaybackTracks only
+ STOPPED,
+ // next 2 states are currently used for fast tracks
+ // and offloaded tracks only
+ STOPPING_1, // waiting for first underrun
+ STOPPING_2, // waiting for presentation complete
+ RESUMING, // for PlaybackTracks only
+ ACTIVE,
+ PAUSING,
+ PAUSED,
+ STARTING_1, // for RecordTrack only
+ STARTING_2, // for RecordTrack only
+ };
+
+ // where to allocate the data buffer
+ enum alloc_type {
+ ALLOC_CBLK, // allocate immediately after control block
+ ALLOC_READONLY, // allocate from a separate read-only heap per thread
+ ALLOC_PIPE, // do not allocate; use the pipe buffer
+ ALLOC_LOCAL, // allocate a local buffer
+ ALLOC_NONE, // do not allocate:use the buffer passed to TrackBase constructor
+ };
+
+ enum track_type {
+ TYPE_DEFAULT,
+ TYPE_OUTPUT,
+ TYPE_PATCH,
+ };
+
+ virtual status_t initCheck() const = 0;
+ virtual status_t start(
+ AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+ audio_session_t triggerSession = AUDIO_SESSION_NONE) = 0;
+ virtual void stop() = 0;
+ virtual sp<IMemory> getCblk() const = 0;
+ virtual audio_track_cblk_t* cblk() const = 0;
+ virtual audio_session_t sessionId() const = 0;
+ virtual uid_t uid() const = 0;
+ virtual pid_t creatorPid() const = 0;
+ virtual uint32_t sampleRate() const = 0;
+ virtual size_t frameSize() const = 0;
+ virtual audio_port_handle_t portId() const = 0;
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+ virtual track_state state() const = 0;
+ virtual void setState(track_state state) = 0;
+ virtual sp<IMemory> getBuffers() const = 0;
+ virtual void* buffer() const = 0;
+ virtual size_t bufferSize() const = 0;
+ virtual bool isFastTrack() const = 0;
+ virtual bool isDirect() const = 0;
+ virtual bool isOutputTrack() const = 0;
+ virtual bool isPatchTrack() const = 0;
+ virtual bool isExternalTrack() const = 0;
+
+ virtual void invalidate() = 0;
+ virtual bool isInvalid() const = 0;
+
+ virtual void terminate() = 0;
+ virtual bool isTerminated() const = 0;
+
+ virtual audio_attributes_t attributes() const = 0;
+ virtual bool isSpatialized() const = 0;
+ virtual bool isBitPerfect() const = 0;
+
+ // not currently implemented in TrackBase, but overridden.
+ virtual void destroy() {}; // MmapTrack doesn't implement.
+ virtual void appendDumpHeader(String8& result) const = 0;
+ virtual void appendDump(String8& result, bool active) const = 0;
+
+ // Dup with AudioBufferProvider interface
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
+ virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer) = 0;
+
+ // Added for RecordTrack and OutputTrack
+ virtual wp<IAfThreadBase> thread() const = 0;
+ virtual const sp<ServerProxy>& serverProxy() const = 0;
+
+ // TEE_SINK
+ virtual void dumpTee(int fd __unused, const std::string& reason __unused) const {};
+
+ /** returns the buffer contents size converted to time in milliseconds
+ * for PCM Playback or Record streaming tracks. The return value is zero for
+ * PCM static tracks and not defined for non-PCM tracks.
+ *
+ * This may be called without the thread lock.
+ */
+ virtual double bufferLatencyMs() const = 0;
+
+ /** returns whether the track supports server latency computation.
+ * This is set in the constructor and constant throughout the track lifetime.
+ */
+ virtual bool isServerLatencySupported() const = 0;
+
+ /** computes the server latency for PCM Playback or Record track
+ * to the device sink/source. This is the time for the next frame in the track buffer
+ * written or read from the server thread to the device source or sink.
+ *
+ * This may be called without the thread lock, but latencyMs and fromTrack
+ * may be not be synchronized. For example PatchPanel may not obtain the
+ * thread lock before calling.
+ *
+ * \param latencyMs on success is set to the latency in milliseconds of the
+ * next frame written/read by the server thread to/from the track buffer
+ * from the device source/sink.
+ * \param fromTrack on success is set to true if latency was computed directly
+ * from the track timestamp; otherwise set to false if latency was
+ * estimated from the server timestamp.
+ * fromTrack may be nullptr or omitted if not required.
+ *
+ * \returns OK or INVALID_OPERATION on failure.
+ */
+ virtual status_t getServerLatencyMs(double* latencyMs, bool* fromTrack = nullptr) const = 0;
+
+ /** computes the total client latency for PCM Playback or Record tracks
+ * for the next client app access to the device sink/source; i.e. the
+ * server latency plus the buffer latency.
+ *
+ * This may be called without the thread lock, but latencyMs and fromTrack
+ * may be not be synchronized. For example PatchPanel may not obtain the
+ * thread lock before calling.
+ *
+ * \param latencyMs on success is set to the latency in milliseconds of the
+ * next frame written/read by the client app to/from the track buffer
+ * from the device sink/source.
+ * \param fromTrack on success is set to true if latency was computed directly
+ * from the track timestamp; otherwise set to false if latency was
+ * estimated from the server timestamp.
+ * fromTrack may be nullptr or omitted if not required.
+ *
+ * \returns OK or INVALID_OPERATION on failure.
+ */
+ virtual status_t getTrackLatencyMs(double* latencyMs, bool* fromTrack = nullptr) const = 0;
+
+ // TODO: Consider making this external.
+ struct FrameTime {
+ int64_t frames;
+ int64_t timeNs;
+ };
+
+ // KernelFrameTime is updated per "mix" period even for non-pcm tracks.
+ virtual void getKernelFrameTime(FrameTime* ft) const = 0;
+
+ virtual audio_format_t format() const = 0;
+ virtual int id() const = 0;
+
+ virtual const char* getTrackStateAsString() const = 0;
+
+ // Called by the PlaybackThread to indicate that the track is becoming active
+ // and a new interval should start with a given device list.
+ virtual void logBeginInterval(const std::string& devices) = 0;
+
+ // Called by the PlaybackThread to indicate the track is no longer active.
+ virtual void logEndInterval() = 0;
+
+ // Called to tally underrun frames in playback.
+ virtual void tallyUnderrunFrames(size_t frames) = 0;
+
+ virtual audio_channel_mask_t channelMask() const = 0;
+
+ /** @return true if the track has changed (metadata or volume) since
+ * the last time this function was called,
+ * true if this function was never called since the track creation,
+ * false otherwise.
+ * Thread safe.
+ */
+ virtual bool readAndClearHasChanged() = 0;
+
+ /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
+ virtual void setMetadataHasChanged() = 0;
+
+ /**
+ * For RecordTrack
+ * TODO(b/291317964) either use this or add asRecordTrack or asTrack etc.
+ */
+ virtual void handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event __unused){};
+
+ // For Thread use, fast tracks and offloaded tracks only
+ // TODO(b/291317964) rearrange to IAfTrack.
+ virtual bool isStopped() const = 0;
+ virtual bool isStopping() const = 0;
+ virtual bool isStopping_1() const = 0;
+ virtual bool isStopping_2() const = 0;
+};
+
+// Common interface for Playback tracks.
+class IAfTrack : public virtual IAfTrackBase {
+public:
+ // FillingStatus is used for suppressing volume ramp at begin of playing
+ enum FillingStatus { FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE };
+
+ // createIAudioTrackAdapter() is a static constructor which creates an
+ // IAudioTrack AIDL interface adapter from the Track object that
+ // may be passed back to the client (if needed).
+ //
+ // Only one AIDL IAudioTrack interface adapter should be created per Track.
+ static sp<media::IAudioTrack> createIAudioTrackAdapter(const sp<IAfTrack>& track);
+
+ static sp<IAfTrack> create(
+ IAfPlaybackThread* thread,
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ const audio_attributes_t& attr,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount,
+ void* buffer,
+ size_t bufferSize,
+ const sp<IMemory>& sharedBuffer,
+ audio_session_t sessionId,
+ pid_t creatorPid,
+ const AttributionSourceState& attributionSource,
+ audio_output_flags_t flags,
+ track_type type,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+ /** default behaviour is to start when there are as many frames
+ * ready as possible (aka. Buffer is full). */
+ size_t frameCountToBeReady = SIZE_MAX,
+ float speed = 1.0f,
+ bool isSpatialized = false,
+ bool isBitPerfect = false);
+
+ virtual void pause() = 0;
+ virtual void flush() = 0;
+ virtual audio_stream_type_t streamType() const = 0;
+ virtual bool isOffloaded() const = 0;
+ virtual bool isOffloadedOrDirect() const = 0;
+ virtual bool isStatic() const = 0;
+ virtual status_t setParameters(const String8& keyValuePairs) = 0;
+ virtual status_t selectPresentation(int presentationId, int programId) = 0;
+ virtual status_t attachAuxEffect(int EffectId) = 0;
+ virtual void setAuxBuffer(int EffectId, int32_t* buffer) = 0;
+ virtual int32_t* auxBuffer() const = 0;
+ virtual void setMainBuffer(float* buffer) = 0;
+ virtual float* mainBuffer() const = 0;
+ virtual int auxEffectId() const = 0;
+ virtual status_t getTimestamp(AudioTimestamp& timestamp) = 0;
+ virtual void signal() = 0;
+ virtual status_t getDualMonoMode(audio_dual_mono_mode_t* mode) const = 0;
+ virtual status_t setDualMonoMode(audio_dual_mono_mode_t mode) = 0;
+ virtual status_t getAudioDescriptionMixLevel(float* leveldB) const = 0;
+ virtual status_t setAudioDescriptionMixLevel(float leveldB) = 0;
+ virtual status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) const = 0;
+ virtual status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) = 0;
+
+ // implement FastMixerState::VolumeProvider interface
+ virtual gain_minifloat_packed_t getVolumeLR() const = 0;
+
+ // implement volume handling.
+ virtual media::VolumeShaper::Status applyVolumeShaper(
+ const sp<media::VolumeShaper::Configuration>& configuration,
+ const sp<media::VolumeShaper::Operation>& operation) = 0;
+ virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) const = 0;
+ virtual sp<media::VolumeHandler> getVolumeHandler() const = 0;
+ /** Set the computed normalized final volume of the track.
+ * !masterMute * masterVolume * streamVolume * averageLRVolume */
+ virtual void setFinalVolume(float volumeLeft, float volumeRight) = 0;
+ virtual float getFinalVolume() const = 0;
+ virtual void getFinalVolume(float* left, float* right) const = 0;
+
+ using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
+ using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
+ /** Copy the track metadata in the provided iterator. Thread safe. */
+ virtual void copyMetadataTo(MetadataInserter& backInserter) const = 0;
+
+ /** Return haptic playback of the track is enabled or not, used in mixer. */
+ virtual bool getHapticPlaybackEnabled() const = 0;
+ /** Set haptic playback of the track is enabled or not, should be
+ * set after query or get callback from vibrator service */
+ virtual void setHapticPlaybackEnabled(bool hapticPlaybackEnabled) = 0;
+ /** Return at what intensity to play haptics, used in mixer. */
+ virtual os::HapticScale getHapticIntensity() const = 0;
+ /** Return the maximum amplitude allowed for haptics data, used in mixer. */
+ virtual float getHapticMaxAmplitude() const = 0;
+ /** Set intensity of haptic playback, should be set after querying vibrator service. */
+ virtual void setHapticIntensity(os::HapticScale hapticIntensity) = 0;
+ /** Set maximum amplitude allowed for haptic data, should be set after querying
+ * vibrator service.
+ */
+ virtual void setHapticMaxAmplitude(float maxAmplitude) = 0;
+ virtual sp<os::ExternalVibration> getExternalVibration() const = 0;
+
+ // This function should be called with holding thread lock.
+ virtual void updateTeePatches() = 0;
+
+ // Argument teePatchesToUpdate is by value, use std::move to optimize.
+ virtual void setTeePatchesToUpdate(TeePatches teePatchesToUpdate) = 0;
+
+ static bool checkServerLatencySupported(audio_format_t format, audio_output_flags_t flags) {
+ return audio_is_linear_pcm(format) && (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) == 0;
+ }
+
+ virtual audio_output_flags_t getOutputFlags() const = 0;
+ virtual float getSpeed() const = 0;
+
+ /**
+ * Updates the mute state and notifies the audio service. Call this only when holding player
+ * thread lock.
+ */
+ virtual void processMuteEvent_l(
+ const sp<IAudioManager>& audioManager, mute_state_t muteState) = 0;
+
+ virtual void triggerEvents(AudioSystem::sync_event_t type) = 0;
+
+ virtual void disable() = 0;
+ virtual int& fastIndex() = 0;
+ virtual bool isPlaybackRestricted() const = 0;
+
+ // Used by thread only
+
+ virtual bool isPausing() const = 0;
+ virtual bool isPaused() const = 0;
+ virtual bool isResuming() const = 0;
+ virtual bool isReady() const = 0;
+ virtual void setPaused() = 0;
+ virtual void reset() = 0;
+ virtual bool isFlushPending() const = 0;
+ virtual void flushAck() = 0;
+ virtual bool isResumePending() const = 0;
+ virtual void resumeAck() = 0;
+ // For direct or offloaded tracks ensure that the pause state is acknowledged
+ // by the playback thread in case of an immediate flush.
+ virtual bool isPausePending() const = 0;
+ virtual void pauseAck() = 0;
+ virtual void updateTrackFrameInfo(
+ int64_t trackFramesReleased, int64_t sinkFramesWritten, uint32_t halSampleRate,
+ const ExtendedTimestamp& timeStamp) = 0;
+ virtual sp<IMemory> sharedBuffer() const = 0;
+
+ // Dup with ExtendedAudioBufferProvider
+ virtual size_t framesReady() const = 0;
+
+ // presentationComplete checked by frames. (Mixed Tracks).
+ // framesWritten is cumulative, never reset, and is shared all tracks
+ // audioHalFrames is derived from output latency
+ virtual bool presentationComplete(int64_t framesWritten, size_t audioHalFrames) = 0;
+
+ // presentationComplete checked by time. (Direct Tracks).
+ virtual bool presentationComplete(uint32_t latencyMs) = 0;
+
+ virtual void resetPresentationComplete() = 0;
+
+ virtual bool hasVolumeController() const = 0;
+ virtual void setHasVolumeController(bool hasVolumeController) = 0;
+ virtual const sp<AudioTrackServerProxy>& audioTrackServerProxy() const = 0;
+ virtual void setCachedVolume(float volume) = 0;
+ virtual void setResetDone(bool resetDone) = 0;
+
+ virtual ExtendedAudioBufferProvider* asExtendedAudioBufferProvider() = 0;
+ virtual VolumeProvider* asVolumeProvider() = 0;
+
+ // TODO(b/291317964) split into getter/setter
+ virtual FillingStatus& fillingStatus() = 0;
+ virtual int8_t& retryCount() = 0;
+ virtual FastTrackUnderruns& fastTrackUnderruns() = 0;
+};
+
+// playback track, used by DuplicatingThread
+class IAfOutputTrack : public virtual IAfTrack {
+public:
+ static sp<IAfOutputTrack> create(
+ IAfPlaybackThread* playbackThread,
+ IAfDuplicatingThread* sourceThread, uint32_t sampleRate,
+ audio_format_t format, audio_channel_mask_t channelMask, size_t frameCount,
+ const AttributionSourceState& attributionSource);
+
+ virtual ssize_t write(void* data, uint32_t frames) = 0;
+ virtual bool bufferQueueEmpty() const = 0;
+ virtual bool isActive() const = 0;
+
+ /** Set the metadatas of the upstream tracks. Thread safe. */
+ virtual void setMetadatas(const SourceMetadatas& metadatas) = 0;
+ /** returns client timestamp to the upstream duplicating thread. */
+ virtual ExtendedTimestamp getClientProxyTimestamp() const = 0;
+};
+
+class IAfMmapTrack : public virtual IAfTrackBase {
+public:
+ static sp<IAfMmapTrack> create(IAfThreadBase* thread,
+ const audio_attributes_t& attr,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_session_t sessionId,
+ bool isOut,
+ const android::content::AttributionSourceState& attributionSource,
+ pid_t creatorPid,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+
+ // protected by MMapThread::mLock
+ virtual void setSilenced_l(bool silenced) = 0;
+ // protected by MMapThread::mLock
+ virtual bool isSilenced_l() const = 0;
+ // protected by MMapThread::mLock
+ virtual bool getAndSetSilencedNotified_l() = 0;
+
+ /**
+ * Updates the mute state and notifies the audio service. Call this only when holding player
+ * thread lock.
+ */
+ virtual void processMuteEvent_l( // see IAfTrack
+ const sp<IAudioManager>& audioManager, mute_state_t muteState) = 0;
+};
+
+class RecordBufferConverter;
+
+class IAfRecordTrack : public virtual IAfTrackBase {
+public:
+ // createIAudioRecordAdapter() is a static constructor which creates an
+ // IAudioRecord AIDL interface adapter from the RecordTrack object that
+ // may be passed back to the client (if needed).
+ //
+ // Only one AIDL IAudioRecord interface adapter should be created per RecordTrack.
+ static sp<media::IAudioRecord> createIAudioRecordAdapter(const sp<IAfRecordTrack>& recordTrack);
+
+ static sp<IAfRecordTrack> create(IAfRecordThread* thread,
+ const sp<Client>& client,
+ const audio_attributes_t& attr,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount,
+ void* buffer,
+ size_t bufferSize,
+ audio_session_t sessionId,
+ pid_t creatorPid,
+ const AttributionSourceState& attributionSource,
+ audio_input_flags_t flags,
+ track_type type,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+ int32_t startFrames = -1);
+
+ // clear the buffer overflow flag
+ virtual void clearOverflow() = 0;
+ // set the buffer overflow flag and return previous value
+ virtual bool setOverflow() = 0;
+
+ // TODO(b/291317964) handleSyncStartEvent in IAfTrackBase should move here.
+ virtual void clearSyncStartEvent() = 0;
+ virtual void updateTrackFrameInfo(
+ int64_t trackFramesReleased, int64_t sourceFramesRead, uint32_t halSampleRate,
+ const ExtendedTimestamp& timestamp) = 0;
+
+ virtual void setSilenced(bool silenced) = 0;
+ virtual bool isSilenced() const = 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;
+ virtual status_t shareAudioHistory(
+ const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) = 0;
+ virtual int32_t startFrames() const = 0;
+
+ static bool checkServerLatencySupported(audio_format_t format, audio_input_flags_t flags) {
+ return audio_is_linear_pcm(format) && (flags & AUDIO_INPUT_FLAG_HW_AV_SYNC) == 0;
+ }
+
+ using SinkMetadatas = std::vector<record_track_metadata_v7_t>;
+ using MetadataInserter = std::back_insert_iterator<SinkMetadatas>;
+ virtual void copyMetadataTo(MetadataInserter& backInserter) const = 0; // see IAfTrack
+
+ // private to Threads
+ virtual AudioBufferProvider::Buffer& sinkBuffer() = 0;
+ virtual audioflinger::SynchronizedRecordState& synchronizedRecordState() = 0;
+ virtual RecordBufferConverter* recordBufferConverter() const = 0;
+ virtual ResamplerBufferProvider* resamplerBufferProvider() const = 0;
+};
+
+// PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord.
+// it provides buffer access methods that map those of a ClientProxy (see AudioTrackShared.h)
+class PatchProxyBufferProvider {
+public:
+ virtual ~PatchProxyBufferProvider() = default;
+ virtual bool producesBufferOnDemand() const = 0;
+ virtual status_t obtainBuffer(
+ Proxy::Buffer* buffer, const struct timespec* requested = nullptr) = 0;
+ virtual void releaseBuffer(Proxy::Buffer* buffer) = 0;
+};
+
+class IAfPatchTrackBase : public virtual RefBase {
+public:
+ using Timeout = std::optional<std::chrono::nanoseconds>;
+
+ virtual void setPeerTimeout(std::chrono::nanoseconds timeout) = 0;
+ virtual void setPeerProxy(const sp<IAfPatchTrackBase>& proxy, bool holdReference) = 0;
+ virtual void clearPeerProxy() = 0;
+ virtual PatchProxyBufferProvider* asPatchProxyBufferProvider() = 0;
+};
+
+class IAfPatchTrack : public virtual IAfTrack, public virtual IAfPatchTrackBase {
+public:
+ static sp<IAfPatchTrack> create(
+ IAfPlaybackThread* playbackThread,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_channel_mask_t channelMask,
+ audio_format_t format,
+ size_t frameCount,
+ void *buffer,
+ size_t bufferSize,
+ audio_output_flags_t flags,
+ const Timeout& timeout = {},
+ size_t frameCountToBeReady = 1 /** Default behaviour is to start
+ * as soon as possible to have
+ * the lowest possible latency
+ * even if it might glitch. */);
+};
+
+class IAfPatchRecord : public virtual IAfRecordTrack, public virtual IAfPatchTrackBase {
+public:
+ static sp<IAfPatchRecord> create(
+ IAfRecordThread* recordThread,
+ uint32_t sampleRate,
+ audio_channel_mask_t channelMask,
+ audio_format_t format,
+ size_t frameCount,
+ void* buffer,
+ size_t bufferSize,
+ audio_input_flags_t flags,
+ const Timeout& timeout = {},
+ audio_source_t source = AUDIO_SOURCE_DEFAULT);
+
+ static sp<IAfPatchRecord> createPassThru(
+ IAfRecordThread* recordThread,
+ uint32_t sampleRate,
+ audio_channel_mask_t channelMask,
+ audio_format_t format,
+ size_t frameCount,
+ audio_input_flags_t flags,
+ audio_source_t source = AUDIO_SOURCE_DEFAULT);
+
+ virtual Source* getSource() = 0;
+ virtual size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) = 0;
+};
+
+} // namespace android
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 39f772b..add453f 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -16,9 +16,9 @@
*/
// #define LOG_NDEBUG 0
-#define LOG_TAG "AudioFlinger::MelReporter"
+#define LOG_TAG "MelReporter"
-#include "AudioFlinger.h"
+#include "MelReporter.h"
#include <android/media/ISoundDoseCallback.h>
#include <audio_utils/power.h>
@@ -28,7 +28,7 @@
namespace android {
-bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module,
+bool MelReporter::activateHalSoundDoseComputation(const std::string& module,
const sp<DeviceHalInterface>& device) {
if (mSoundDoseManager->forceUseFrameworkMel()) {
ALOGD("%s: Forcing use of internal MEL computation.", __func__);
@@ -63,9 +63,9 @@
return true;
}
-void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
+void MelReporter::activateInternalSoundDoseComputation() {
{
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!mUseHalSoundDoseInterface) {
// no need to start internal MEL on active patches
return;
@@ -76,11 +76,11 @@
mSoundDoseManager->setHalSoundDoseInterface(nullptr);
}
-void AudioFlinger::MelReporter::onFirstRef() {
- mAudioFlinger.mPatchCommandThread->addListener(this);
+void MelReporter::onFirstRef() {
+ mAfMelReporterCallback->getPatchCommandThread()->addListener(this);
}
-bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
+bool MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return false;
@@ -104,15 +104,15 @@
}
}
-void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
+void MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
const std::vector<playback_track_metadata_v7_t>& metadataVec) {
if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return;
}
- std::lock_guard _laf(mAudioFlinger.mLock);
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
+ audio_utils::lock_guard _l(mutex());
auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
if (!activeMelPatchId) {
ALOGV("%s stream handle %d does not have an active patch", __func__, streamHandle);
@@ -140,8 +140,8 @@
}
}
-void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
- const PatchPanel::Patch& patch) {
+void MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
+ const IAfPatchPanel::Patch& patch) {
if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return;
@@ -171,8 +171,8 @@
}
if (!newPatch.deviceHandles.empty()) {
- std::lock_guard _afl(mAudioFlinger.mLock);
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
+ audio_utils::lock_guard _l(mutex());
ALOGV("%s add patch handle %d to active devices", __func__, handle);
startMelComputationForActivePatch_l(newPatch);
newPatch.csdActive = true;
@@ -180,10 +180,10 @@
}
}
-void AudioFlinger::MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch)
+void MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch)
NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
{
- auto outputThread = mAudioFlinger.checkOutputThread_l(patch.streamHandle);
+ auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
if (outputThread == nullptr) {
ALOGE("%s cannot find thread for stream handle %d", __func__, patch.streamHandle);
return;
@@ -198,14 +198,14 @@
outputThread->startMelComputation_l(mSoundDoseManager->getOrCreateProcessorForDevice(
deviceHandle,
patch.streamHandle,
- outputThread->mSampleRate,
- outputThread->mChannelCount,
- outputThread->mFormat));
+ outputThread->sampleRate(),
+ outputThread->channelCount(),
+ outputThread->format()));
}
}
}
-void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
+void MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return;
@@ -213,7 +213,7 @@
ActiveMelPatch melPatch;
{
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
auto patchIt = mActiveMelPatches.find(handle);
if (patchIt == mActiveMelPatches.end()) {
@@ -226,25 +226,25 @@
mActiveMelPatches.erase(patchIt);
}
- std::lock_guard _afl(mAudioFlinger.mLock);
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
+ audio_utils::lock_guard _l(mutex());
stopMelComputationForPatch_l(melPatch);
}
-sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
+sp<media::ISoundDose> MelReporter::getSoundDoseInterface(
const sp<media::ISoundDoseCallback>& callback) {
// no need to lock since getSoundDoseInterface is synchronized
return mSoundDoseManager->getSoundDoseInterface(callback);
}
-void AudioFlinger::MelReporter::stopInternalMelComputation() {
+void MelReporter::stopInternalMelComputation() {
ALOGV("%s", __func__);
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mActiveMelPatches.clear();
mUseHalSoundDoseInterface = true;
}
-void AudioFlinger::MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
+void MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
{
if (!patch.csdActive) {
@@ -252,7 +252,7 @@
return;
}
- auto outputThread = mAudioFlinger.checkOutputThread_l(patch.streamHandle);
+ auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
for (const auto& deviceId : patch.deviceHandles) {
@@ -271,8 +271,7 @@
}
}
-
-std::optional<audio_patch_handle_t> AudioFlinger::MelReporter::activePatchStreamHandle_l(
+std::optional<audio_patch_handle_t> MelReporter::activePatchStreamHandle_l(
audio_io_handle_t streamHandle) {
for(const auto& patchIt : mActiveMelPatches) {
if (patchIt.second.streamHandle == streamHandle) {
@@ -282,12 +281,12 @@
return std::nullopt;
}
-bool AudioFlinger::MelReporter::useHalSoundDoseInterface_l() {
+bool MelReporter::useHalSoundDoseInterface_l() {
return !mSoundDoseManager->forceUseFrameworkMel() & mUseHalSoundDoseInterface;
}
-std::string AudioFlinger::MelReporter::dump() {
- std::lock_guard _l(mLock);
+std::string MelReporter::dump() {
+ audio_utils::lock_guard _l(mutex());
std::string output("\nSound Dose:\n");
output.append(mSoundDoseManager->dump());
return output;
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index 2bc33f2..07ab94d 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -15,25 +15,38 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
-#include <mutex>
+#include "IAfPatchPanel.h"
+#include "PatchCommandThread.h"
+
+#include <audio_utils/mutex.h>
#include <sounddose/SoundDoseManager.h>
+
#include <unordered_map>
+namespace android {
+
constexpr static int kMaxTimestampDeltaInSec = 120;
+class IAfMelReporterCallback : public virtual RefBase {
+public:
+ virtual audio_utils::mutex& mutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
+ virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+ virtual sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const
+ REQUIRES(mutex()) = 0;
+};
+
/**
* Class for listening to new patches and starting the MEL computation. MelReporter is
* concealed within AudioFlinger, their lifetimes are the same.
*/
class MelReporter : public PatchCommandThread::PatchCommandListener {
public:
- explicit MelReporter(AudioFlinger& audioFlinger)
- : mAudioFlinger(audioFlinger),
- mSoundDoseManager(sp<SoundDoseManager>::make()) {}
+ explicit MelReporter(const sp<IAfMelReporterCallback>& afMelReporterCallback)
+ : mAfMelReporterCallback(afMelReporterCallback),
+ mSoundDoseManager(sp<SoundDoseManager>::make()) {}
void onFirstRef() override;
@@ -51,7 +64,7 @@
* implementation, false otherwise.
*/
bool activateHalSoundDoseComputation(const std::string& module,
- const sp<DeviceHalInterface>& device);
+ const sp<DeviceHalInterface>& device) EXCLUDES_MelReporter_Mutex;
/**
* Activates the MEL reporting from internal framework values. These are used
@@ -59,7 +72,7 @@
* Note: the internal CSD computation does not guarantee a certification with
* IEC62368-1 3rd edition or EN50332-3
*/
- void activateInternalSoundDoseComputation();
+ void activateInternalSoundDoseComputation() EXCLUDES_MelReporter_Mutex;
sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
@@ -67,8 +80,9 @@
// PatchCommandListener methods
void onCreateAudioPatch(audio_patch_handle_t handle,
- const PatchPanel::Patch& patch) override;
- void onReleaseAudioPatch(audio_patch_handle_t handle) override;
+ const IAfPatchPanel::Patch& patch) final
+ EXCLUDES_AudioFlinger_Mutex;
+ void onReleaseAudioPatch(audio_patch_handle_t handle) final EXCLUDES_AudioFlinger_Mutex;
/**
* The new metadata can determine whether we should compute MEL for the given thread.
@@ -76,7 +90,9 @@
* Otherwise, this method will disable CSD.
**/
void updateMetadataForCsd(audio_io_handle_t streamHandle,
- const std::vector<playback_track_metadata_v7_t>& metadataVec);
+ const std::vector<playback_track_metadata_v7_t>& metadataVec)
+ EXCLUDES_AudioFlinger_Mutex;
+
private:
struct ActiveMelPatch {
audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
@@ -88,30 +104,34 @@
bool shouldComputeMelForDeviceType(audio_devices_t device);
void stopInternalMelComputation();
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::MelReporter_Mutex) {
+ return mMutex;
+ }
- /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
- void stopMelComputationForPatch_l(const ActiveMelPatch& patch) REQUIRES(mLock);
+ /** Should be called with the following order of locks: mAudioFlinger.mutex() -> mutex(). */
+ void stopMelComputationForPatch_l(const ActiveMelPatch& patch) REQUIRES(mutex());
- /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
- void startMelComputationForActivePatch_l(const ActiveMelPatch& patch) REQUIRES(mLock);
+ /** Should be called with the following order of locks: mAudioFlinger.mutex() -> mutex(). */
+ void startMelComputationForActivePatch_l(const ActiveMelPatch& patch) REQUIRES(mutex());
std::optional<audio_patch_handle_t>
- activePatchStreamHandle_l(audio_io_handle_t streamHandle) REQUIRES(mLock);
+ activePatchStreamHandle_l(audio_io_handle_t streamHandle) REQUIRES(mutex());
- bool useHalSoundDoseInterface_l() REQUIRES(mLock);
+ bool useHalSoundDoseInterface_l() REQUIRES(mutex());
- AudioFlinger& mAudioFlinger; // does not own the object
+ const sp<IAfMelReporterCallback> mAfMelReporterCallback;
- sp<SoundDoseManager> mSoundDoseManager;
+ /* const */ sp<SoundDoseManager> mSoundDoseManager; // set onFirstRef
/**
* Lock for protecting the active mel patches. Do not mix with the AudioFlinger lock.
- * Locking order AudioFlinger::mLock -> PatchCommandThread::mLock -> MelReporter::mLock.
+ * Locking order AudioFlinger::mutex() -> PatchCommandThread::mutex() -> MelReporter::mutex().
*/
- std::mutex mLock;
- std::unordered_map<audio_patch_handle_t, ActiveMelPatch>
- mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock);
- std::unordered_map<audio_port_handle_t, int>
- mActiveDevices GUARDED_BY(AudioFlinger::MelReporter::mLock);
- bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false;
+ mutable audio_utils::mutex mMutex;
+ std::unordered_map<audio_patch_handle_t, ActiveMelPatch> mActiveMelPatches
+ GUARDED_BY(mutex());
+ std::unordered_map<audio_port_handle_t, int> mActiveDevices GUARDED_BY(mutex());
+ bool mUseHalSoundDoseInterface GUARDED_BY(mutex()) = false;
};
+
+} // namespace android
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index cb46c52..85ce142 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -15,14 +15,18 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "TrackBase.h"
+
+#include <android/content/AttributionSourceState.h>
+
+namespace android {
// playback track
-class MmapTrack : public TrackBase {
+class MmapTrack : public TrackBase, public IAfMmapTrack {
public:
- MmapTrack(ThreadBase *thread,
+ MmapTrack(IAfThreadBase* thread,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
@@ -32,26 +36,25 @@
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
- virtual ~MmapTrack();
+ ~MmapTrack() override;
- // TrackBase virtual
- virtual status_t initCheck() const;
- virtual status_t start(AudioSystem::sync_event_t event,
- audio_session_t triggerSession);
- virtual void stop();
- virtual bool isFastTrack() const { return false; }
- bool isDirect() const override { return true; }
+ status_t initCheck() const final;
+ status_t start(
+ AudioSystem::sync_event_t event, audio_session_t triggerSession) final;
+ void stop() final;
+ bool isFastTrack() const final { return false; }
+ bool isDirect() const final { return true; }
- void appendDumpHeader(String8& result);
- void appendDump(String8& result, bool active);
+ void appendDumpHeader(String8& result) const final;
+ void appendDump(String8& result, bool active) const final;
// protected by MMapThread::mLock
- void setSilenced_l(bool silenced) { mSilenced = silenced;
+ void setSilenced_l(bool silenced) final { mSilenced = silenced;
mSilencedNotified = false;}
// protected by MMapThread::mLock
- bool isSilenced_l() const { return mSilenced; }
+ bool isSilenced_l() const final { return mSilenced; }
// protected by MMapThread::mLock
- bool getAndSetSilencedNotified_l() { bool silencedNotified = mSilencedNotified;
+ bool getAndSetSilencedNotified_l() final { bool silencedNotified = mSilencedNotified;
mSilencedNotified = true;
return silencedNotified; }
@@ -61,10 +64,8 @@
*/
void processMuteEvent_l(const sp<IAudioManager>& audioManager,
mute_state_t muteState)
- REQUIRES(AudioFlinger::MmapPlaybackThread::mLock);
+ /* REQUIRES(MmapPlaybackThread::mLock) */ final;
private:
- friend class MmapThread;
-
DISALLOW_COPY_AND_ASSIGN(MmapTrack);
// AudioBufferProvider interface
@@ -72,19 +73,20 @@
// releaseBuffer() not overridden
// ExtendedAudioBufferProvider interface
- virtual size_t framesReady() const;
- virtual int64_t framesReleased() const;
- virtual void onTimestamp(const ExtendedTimestamp ×tamp);
+ size_t framesReady() const final;
+ int64_t framesReleased() const final;
+ void onTimestamp(const ExtendedTimestamp ×tamp) final;
- pid_t mPid;
+ const pid_t mPid;
bool mSilenced; // protected by MMapThread::mLock
bool mSilencedNotified; // protected by MMapThread::mLock
// TODO: replace PersistableBundle with own struct
// access these two variables only when holding player thread lock.
std::unique_ptr<os::PersistableBundle> mMuteEventExtras
- GUARDED_BY(AudioFlinger::MmapPlaybackThread::mLock);
+ /* GUARDED_BY(MmapPlaybackThread::mLock) */;
mute_state_t mMuteState
- GUARDED_BY(AudioFlinger::MmapPlaybackThread::mLock);
+ /* GUARDED_BY(MmapPlaybackThread::mLock) */;
}; // end of Track
+} // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/PatchCommandThread.cpp b/services/audioflinger/PatchCommandThread.cpp
index f4aab1f..f4c76d6 100644
--- a/services/audioflinger/PatchCommandThread.cpp
+++ b/services/audioflinger/PatchCommandThread.cpp
@@ -18,31 +18,33 @@
#define LOG_TAG "AudioFlinger::PatchCommandThread"
//#define LOG_NDEBUG 0
-#include "AudioFlinger.h"
+#include "PatchCommandThread.h"
+
+#include <utils/Log.h>
namespace android {
constexpr char kPatchCommandThreadName[] = "AudioFlinger_PatchCommandThread";
-AudioFlinger::PatchCommandThread::~PatchCommandThread() {
+PatchCommandThread::~PatchCommandThread() {
exit();
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mCommands.clear();
}
-void AudioFlinger::PatchCommandThread::onFirstRef() {
+void PatchCommandThread::onFirstRef() {
run(kPatchCommandThreadName, ANDROID_PRIORITY_AUDIO);
}
-void AudioFlinger::PatchCommandThread::addListener(const sp<PatchCommandListener>& listener) {
+void PatchCommandThread::addListener(const sp<PatchCommandListener>& listener) {
ALOGV("%s add listener %p", __func__, static_cast<void*>(listener.get()));
- std::lock_guard _l(mListenerLock);
+ audio_utils::lock_guard _l(listenerMutex());
mListeners.emplace_back(listener);
}
-void AudioFlinger::PatchCommandThread::createAudioPatch(audio_patch_handle_t handle,
- const PatchPanel::Patch& patch) {
+void PatchCommandThread::createAudioPatch(audio_patch_handle_t handle,
+ const IAfPatchPanel::Patch& patch) {
ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
__func__, handle, patch.mHalHandle,
patch.mAudioPatch.num_sinks,
@@ -51,15 +53,14 @@
createAudioPatchCommand(handle, patch);
}
-void AudioFlinger::PatchCommandThread::releaseAudioPatch(audio_patch_handle_t handle) {
+void PatchCommandThread::releaseAudioPatch(audio_patch_handle_t handle) {
ALOGV("%s", __func__);
releaseAudioPatchCommand(handle);
}
-bool AudioFlinger::PatchCommandThread::threadLoop()
-NO_THREAD_SAFETY_ANALYSIS // bug in clang compiler.
+bool PatchCommandThread::threadLoop()
{
- std::unique_lock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
while (!exitPending()) {
while (!mCommands.empty() && !exitPending()) {
@@ -69,7 +70,7 @@
std::vector<wp<PatchCommandListener>> listenersCopy;
{
- std::lock_guard _ll(mListenerLock);
+ audio_utils::lock_guard _ll(listenerMutex());
listenersCopy = mListeners;
}
@@ -119,14 +120,14 @@
return false;
}
-void AudioFlinger::PatchCommandThread::sendCommand(const sp<Command>& command) {
- std::lock_guard _l(mLock);
+void PatchCommandThread::sendCommand(const sp<Command>& command) {
+ audio_utils::lock_guard _l(mutex());
mCommands.emplace_back(command);
mWaitWorkCV.notify_one();
}
-void AudioFlinger::PatchCommandThread::createAudioPatchCommand(
- audio_patch_handle_t handle, const PatchPanel::Patch& patch) {
+void PatchCommandThread::createAudioPatchCommand(
+ audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) {
auto command = sp<Command>::make(CREATE_AUDIO_PATCH,
new CreateAudioPatchData(handle, patch));
ALOGV("%s adding create patch handle %d mHalHandle %d.",
@@ -136,17 +137,17 @@
sendCommand(command);
}
-void AudioFlinger::PatchCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle) {
+void PatchCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle) {
sp<Command> command =
sp<Command>::make(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle));
ALOGV("%s adding release patch", __func__);
sendCommand(command);
}
-void AudioFlinger::PatchCommandThread::exit() {
+void PatchCommandThread::exit() {
ALOGV("%s", __func__);
{
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
requestExit();
mWaitWorkCV.notify_one();
}
diff --git a/services/audioflinger/PatchCommandThread.h b/services/audioflinger/PatchCommandThread.h
index b52e0a9..8ca96f1 100644
--- a/services/audioflinger/PatchCommandThread.h
+++ b/services/audioflinger/PatchCommandThread.h
@@ -15,14 +15,22 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "IAfPatchPanel.h"
+
+#include <utils/RefBase.h> // avoid transitive dependency
+#include <utils/Thread.h> // avoid transitive dependency
+
+#include <deque>
+#include <mutex> // avoid transitive dependency
+
+namespace android {
class Command;
// Thread to execute create and release patch commands asynchronously. This is needed because
-// PatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service
+// IAfPatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service
// with mutex locked and effect management requires to call back into audio policy service
class PatchCommandThread : public Thread {
public:
@@ -35,17 +43,19 @@
class PatchCommandListener : public virtual RefBase {
public:
virtual void onCreateAudioPatch(audio_patch_handle_t handle,
- const PatchPanel::Patch& patch) = 0;
+ const IAfPatchPanel::Patch& patch) = 0;
virtual void onReleaseAudioPatch(audio_patch_handle_t handle) = 0;
};
PatchCommandThread() : Thread(false /* canCallJava */) {}
~PatchCommandThread() override;
- void addListener(const sp<PatchCommandListener>& listener);
+ void addListener(const sp<PatchCommandListener>& listener)
+ EXCLUDES_PatchCommandThread_ListenerMutex;
- void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
- void releaseAudioPatch(audio_patch_handle_t handle);
+ void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch)
+ EXCLUDES_PatchCommandThread_Mutex;
+ void releaseAudioPatch(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex;
// Thread virtuals
void onFirstRef() override;
@@ -54,9 +64,8 @@
void exit();
void createAudioPatchCommand(audio_patch_handle_t handle,
- const PatchPanel::Patch& patch);
- void releaseAudioPatchCommand(audio_patch_handle_t handle);
-
+ const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex;
+ void releaseAudioPatchCommand(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex;
private:
class CommandData;
@@ -75,11 +84,11 @@
class CreateAudioPatchData : public CommandData {
public:
- CreateAudioPatchData(audio_patch_handle_t handle, const PatchPanel::Patch& patch)
+ CreateAudioPatchData(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch)
: mHandle(handle), mPatch(patch) {}
const audio_patch_handle_t mHandle;
- const PatchPanel::Patch mPatch;
+ const IAfPatchPanel::Patch mPatch;
};
class ReleaseAudioPatchData : public CommandData {
@@ -90,13 +99,22 @@
audio_patch_handle_t mHandle;
};
- void sendCommand(const sp<Command>& command);
+ void sendCommand(const sp<Command>& command) EXCLUDES_PatchCommandThread_Mutex;
- std::string mThreadName;
- std::mutex mLock;
- std::condition_variable mWaitWorkCV;
- std::deque<sp<Command>> mCommands GUARDED_BY(mLock); // list of pending commands
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::PatchCommandThread_Mutex) {
+ return mMutex;
+ }
+ audio_utils::mutex& listenerMutex() const
+ RETURN_CAPABILITY(audio_utils::PatchCommandThread_ListenerMutex) {
+ return mListenerMutex;
+ }
- std::mutex mListenerLock;
- std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(mListenerLock);
+ mutable audio_utils::mutex mMutex;
+ audio_utils::condition_variable mWaitWorkCV;
+ std::deque<sp<Command>> mCommands GUARDED_BY(mutex()); // list of pending commands
+
+ mutable audio_utils::mutex mListenerMutex;
+ std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(listenerMutex());
};
+
+} // namespace android
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 837d045..7d3900b 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -19,16 +19,16 @@
#define LOG_TAG "AudioFlinger::PatchPanel"
//#define LOG_NDEBUG 0
-#include "Configuration.h"
-#include <utils/Log.h>
-#include <audio_utils/primitives.h>
+#include "PatchPanel.h"
+#include "PatchCommandThread.h"
-#include "AudioFlinger.h"
+#include <audio_utils/primitives.h>
#include <media/AudioParameter.h>
#include <media/AudioValidator.h>
#include <media/DeviceDescriptorBase.h>
#include <media/PatchBuilder.h>
#include <mediautils/ServiceUtilities.h>
+#include <utils/Log.h>
// ----------------------------------------------------------------------------
@@ -47,65 +47,43 @@
namespace android {
-/* List connected audio ports and their attributes */
-status_t AudioFlinger::listAudioPorts(unsigned int *num_ports,
- struct audio_port *ports)
-{
- Mutex::Autolock _l(mLock);
- return mPatchPanel.listAudioPorts(num_ports, ports);
+/* static */
+sp<IAfPatchPanel> IAfPatchPanel::create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback) {
+ return sp<PatchPanel>::make(afPatchPanelCallback);
}
-/* Get supported attributes for a given audio port */
-status_t AudioFlinger::getAudioPort(struct audio_port_v7 *port) {
- status_t status = AudioValidator::validateAudioPort(*port);
- if (status != NO_ERROR) {
- return status;
- }
-
- Mutex::Autolock _l(mLock);
- return mPatchPanel.getAudioPort(port);
+status_t SoftwarePatch::getLatencyMs_l(double* latencyMs) const {
+ return mPatchPanel->getLatencyMs_l(mPatchHandle, latencyMs);
}
-/* Connect a patch between several source and sink ports */
-status_t AudioFlinger::createAudioPatch(const struct audio_patch *patch,
- audio_patch_handle_t *handle)
+status_t PatchPanel::getLatencyMs_l(
+ audio_patch_handle_t patchHandle, double* latencyMs) const
{
- status_t status = AudioValidator::validateAudioPatch(*patch);
- if (status != NO_ERROR) {
- return status;
- }
-
- Mutex::Autolock _l(mLock);
- return mPatchPanel.createAudioPatch(patch, handle);
-}
-
-/* Disconnect a patch */
-status_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle)
-{
- Mutex::Autolock _l(mLock);
- return mPatchPanel.releaseAudioPatch(handle);
-}
-
-/* List connected audio ports and they attributes */
-status_t AudioFlinger::listAudioPatches(unsigned int *num_patches,
- struct audio_patch *patches)
-{
- Mutex::Autolock _l(mLock);
- return mPatchPanel.listAudioPatches(num_patches, patches);
-}
-
-status_t AudioFlinger::PatchPanel::SoftwarePatch::getLatencyMs_l(double *latencyMs) const
-{
- const auto& iter = mPatchPanel.mPatches.find(mPatchHandle);
- if (iter != mPatchPanel.mPatches.end()) {
+ const auto& iter = mPatches.find(patchHandle);
+ if (iter != mPatches.end()) {
return iter->second.getLatencyMs(latencyMs);
} else {
return BAD_VALUE;
}
}
+void PatchPanel::closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
+{
+ if (const auto recordThread = thread->asIAfRecordThread();
+ recordThread) {
+ mAfPatchPanelCallback->closeThreadInternal_l(recordThread);
+ } else if (const auto playbackThread = thread->asIAfPlaybackThread();
+ playbackThread) {
+ mAfPatchPanelCallback->closeThreadInternal_l(playbackThread);
+ } else {
+ LOG_ALWAYS_FATAL("%s: Endpoints only accept IAfPlayback and IAfRecord threads, "
+ "invalid thread, id: %d type: %d",
+ __func__, thread->id(), thread->type());
+ }
+}
+
/* List connected audio ports and their attributes */
-status_t AudioFlinger::PatchPanel::listAudioPorts(unsigned int *num_ports __unused,
+status_t PatchPanel::listAudioPorts_l(unsigned int* /* num_ports */,
struct audio_port *ports __unused)
{
ALOGV(__func__);
@@ -113,14 +91,14 @@
}
/* Get supported attributes for a given audio port */
-status_t AudioFlinger::PatchPanel::getAudioPort(struct audio_port_v7 *port)
+status_t PatchPanel::getAudioPort_l(struct audio_port_v7* port)
{
if (port->type != AUDIO_PORT_TYPE_DEVICE) {
// Only query the HAL when the port is a device.
// TODO: implement getAudioPort for mix.
return INVALID_OPERATION;
}
- AudioHwDevice* hwDevice = findAudioHwDeviceByModule(port->ext.device.hw_module);
+ AudioHwDevice* hwDevice = findAudioHwDeviceByModule_l(port->ext.device.hw_module);
if (hwDevice == nullptr) {
ALOGW("%s cannot find hw module %d", __func__, port->ext.device.hw_module);
return BAD_VALUE;
@@ -132,10 +110,10 @@
}
/* Connect a patch between several source and sink ports */
-status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch,
+status_t PatchPanel::createAudioPatch_l(const struct audio_patch* patch,
audio_patch_handle_t *handle,
bool endpointPatch)
- //unlocks AudioFlinger::mLock when calling ThreadBase::sendCreateAudioPatchConfigEvent
+ //unlocks AudioFlinger::mLock when calling IAfThreadBase::sendCreateAudioPatchConfigEvent
//to avoid deadlocks if the thread loop needs to acquire AudioFlinger::mLock
//before processing the create patch request.
NO_THREAD_SAFETY_ANALYSIS
@@ -166,7 +144,7 @@
// 1) if a software patch is present, release the playback and capture threads and
// tracks created. This will also release the corresponding audio HAL patches
if (removedPatch.isSoftware()) {
- removedPatch.clearConnections(this);
+ removedPatch.clearConnections_l(this);
}
// 2) if the new patch and old patch source or sink are devices from different
// hw modules, clear the audio HAL patches now because they will not be updated
@@ -191,7 +169,7 @@
// removedPatch.mHalHandle would be AUDIO_PATCH_HANDLE_NONE in this case.
hwModule = oldPatch.sinks[0].ext.device.hw_module;
}
- sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(hwModule);
+ sp<DeviceHalInterface> hwDevice = findHwDeviceByModule_l(hwModule);
if (hwDevice != 0) {
hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
}
@@ -207,7 +185,7 @@
switch (patch->sources[0].type) {
case AUDIO_PORT_TYPE_DEVICE: {
audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module;
- AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(srcModule);
+ AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule_l(srcModule);
if (!audioHwDevice) {
status = BAD_VALUE;
goto exit;
@@ -249,8 +227,8 @@
status = INVALID_OPERATION;
goto exit;
}
- sp<ThreadBase> thread =
- mAudioFlinger.checkPlaybackThread_l(patch->sources[1].ext.mix.handle);
+ const sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(
+ patch->sources[1].ext.mix.handle);
if (thread == 0) {
ALOGW("%s() cannot get playback thread", __func__);
status = INVALID_OPERATION;
@@ -258,7 +236,7 @@
}
// existing playback thread is reused, so it is not closed when patch is cleared
newPatch.mPlayback.setThread(
- reinterpret_cast<PlaybackThread*>(thread.get()), false /*closeThread*/);
+ thread->asIAfPlaybackThread().get(), false /*closeThread*/);
} else {
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
audio_config_base_t mixerConfig = AUDIO_CONFIG_BASE_INITIALIZER;
@@ -276,7 +254,7 @@
if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS) {
flags = patch->sinks[0].flags.output;
}
- sp<ThreadBase> thread = mAudioFlinger.openOutput_l(
+ const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openOutput_l(
patch->sinks[0].ext.device.hw_module,
&output,
&config,
@@ -284,12 +262,12 @@
outputDevice,
outputDeviceAddress,
flags);
- ALOGV("mAudioFlinger.openOutput_l() returned %p", thread.get());
+ ALOGV("mAfPatchPanelCallback->openOutput_l() returned %p", thread.get());
if (thread == 0) {
status = NO_MEMORY;
goto exit;
}
- newPatch.mPlayback.setThread(reinterpret_cast<PlaybackThread*>(thread.get()));
+ newPatch.mPlayback.setThread(thread->asIAfPlaybackThread().get());
}
audio_devices_t device = patch->sources[0].ext.device.type;
String8 address = String8(patch->sources[0].ext.device.address);
@@ -323,7 +301,7 @@
== AUDIO_STREAM_VOICE_CALL) {
source = AUDIO_SOURCE_VOICE_COMMUNICATION;
}
- sp<ThreadBase> thread = mAudioFlinger.openInput_l(srcModule,
+ const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openInput_l(srcModule,
&input,
&config,
device,
@@ -332,14 +310,14 @@
flags,
outputDevice,
outputDeviceAddress);
- ALOGV("mAudioFlinger.openInput_l() returned %p inChannelMask %08x",
+ ALOGV("mAfPatchPanelCallback->openInput_l() returned %p inChannelMask %08x",
thread.get(), config.channel_mask);
if (thread == 0) {
status = NO_MEMORY;
goto exit;
}
- newPatch.mRecord.setThread(reinterpret_cast<RecordThread*>(thread.get()));
- status = newPatch.createConnections(this);
+ newPatch.mRecord.setThread(thread->asIAfRecordThread().get());
+ status = newPatch.createConnections_l(this);
if (status != NO_ERROR) {
goto exit;
}
@@ -348,10 +326,11 @@
}
} else {
if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
- sp<ThreadBase> thread = mAudioFlinger.checkRecordThread_l(
+ sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkRecordThread_l(
patch->sinks[0].ext.mix.handle);
if (thread == 0) {
- thread = mAudioFlinger.checkMmapThread_l(patch->sinks[0].ext.mix.handle);
+ thread = mAfPatchPanelCallback->checkMmapThread_l(
+ patch->sinks[0].ext.mix.handle);
if (thread == 0) {
ALOGW("%s() bad capture I/O handle %d",
__func__, patch->sinks[0].ext.mix.handle);
@@ -359,9 +338,9 @@
goto exit;
}
}
- mAudioFlinger.unlock();
+ mAfPatchPanelCallback->mutex().unlock();
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
- mAudioFlinger.lock();
+ mAfPatchPanelCallback->mutex().lock();
if (status == NO_ERROR) {
newPatch.setThread(thread);
}
@@ -385,7 +364,7 @@
} break;
case AUDIO_PORT_TYPE_MIX: {
audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module;
- ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(srcModule);
+ ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(srcModule);
if (index < 0) {
ALOGW("%s() bad src hw module %d", __func__, srcModule);
status = BAD_VALUE;
@@ -411,10 +390,11 @@
device->applyAudioPortConfig(&patch->sinks[i]);
devices.push_back(device);
}
- sp<ThreadBase> thread =
- mAudioFlinger.checkPlaybackThread_l(patch->sources[0].ext.mix.handle);
+ sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(
+ patch->sources[0].ext.mix.handle);
if (thread == 0) {
- thread = mAudioFlinger.checkMmapThread_l(patch->sources[0].ext.mix.handle);
+ thread = mAfPatchPanelCallback->checkMmapThread_l(
+ patch->sources[0].ext.mix.handle);
if (thread == 0) {
ALOGW("%s() bad playback I/O handle %d",
__func__, patch->sources[0].ext.mix.handle);
@@ -422,13 +402,13 @@
goto exit;
}
}
- if (thread == mAudioFlinger.primaryPlaybackThread_l()) {
- mAudioFlinger.updateOutDevicesForRecordThreads_l(devices);
+ if (thread == mAfPatchPanelCallback->primaryPlaybackThread_l()) {
+ mAfPatchPanelCallback->updateOutDevicesForRecordThreads_l(devices);
}
- mAudioFlinger.unlock();
+ mAfPatchPanelCallback->mutex().unlock();
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
- mAudioFlinger.lock();
+ mAfPatchPanelCallback->mutex().lock();
if (status == NO_ERROR) {
newPatch.setThread(thread);
}
@@ -453,29 +433,30 @@
exit:
ALOGV("%s() status %d", __func__, status);
if (status == NO_ERROR) {
- *handle = (audio_patch_handle_t) mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
+ *handle = static_cast<audio_patch_handle_t>(
+ mAfPatchPanelCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH));
newPatch.mHalHandle = halHandle;
- mAudioFlinger.mPatchCommandThread->createAudioPatch(*handle, newPatch);
+ mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(*handle, newPatch);
if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
- addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
+ addSoftwarePatchToInsertedModules_l(insertedModule, *handle, &newPatch.mAudioPatch);
}
mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
} else {
- newPatch.clearConnections(this);
+ newPatch.clearConnections_l(this);
}
return status;
}
-AudioFlinger::PatchPanel::Patch::~Patch()
+PatchPanel::Patch::~Patch()
{
ALOGE_IF(isSoftware(), "Software patch connections leaked %d %d",
mRecord.handle(), mPlayback.handle());
}
-status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel)
+status_t PatchPanel::Patch::createConnections_l(const sp<IAfPatchPanel>& panel)
{
// create patch from source device to record thread input
- status_t status = panel->createAudioPatch(
+ status_t status = panel->createAudioPatch_l(
PatchBuilder().addSource(mAudioPatch.sources[0]).
addSink(mRecord.thread(), { .source = AUDIO_SOURCE_MIC }).patch(),
mRecord.handlePtr(),
@@ -487,7 +468,7 @@
// create patch from playback thread output to sink device
if (mAudioPatch.num_sinks != 0) {
- status = panel->createAudioPatch(
+ status = panel->createAudioPatch_l(
PatchBuilder().addSource(mPlayback.thread()).addSink(mAudioPatch.sinks[0]).patch(),
mPlayback.handlePtr(),
true /*endpointPatch*/);
@@ -546,7 +527,7 @@
outputFlags = (audio_output_flags_t) (outputFlags & ~AUDIO_OUTPUT_FLAG_FAST);
}
- sp<RecordThread::PatchRecord> tempRecordTrack;
+ sp<IAfPatchRecord> tempRecordTrack;
const bool usePassthruPatchRecord =
(inputFlags & AUDIO_INPUT_FLAG_DIRECT) && (outputFlags & AUDIO_OUTPUT_FLAG_DIRECT);
const size_t playbackFrameCount = mPlayback.thread()->frameCount();
@@ -558,7 +539,7 @@
frameCount = std::max(playbackFrameCount, recordFrameCount);
ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu",
__func__, playbackFrameCount, recordFrameCount, frameCount);
- tempRecordTrack = new RecordThread::PassthruPatchRecord(
+ tempRecordTrack = IAfPatchRecord::createPassThru(
mRecord.thread().get(),
sampleRate,
inChannelMask,
@@ -577,7 +558,7 @@
ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu",
__func__, playbackFrameCount, recordFrameCount, frameCount);
- tempRecordTrack = new RecordThread::PatchRecord(
+ tempRecordTrack = IAfPatchRecord::create(
mRecord.thread().get(),
sampleRate,
inChannelMask,
@@ -602,7 +583,7 @@
// Disable this behavior for FM Tuner source if no fast capture/mixer available.
const bool isFmBridge = mAudioPatch.sources[0].ext.device.type == AUDIO_DEVICE_IN_FM_TUNER;
const size_t frameCountToBeReady = isFmBridge && !usePassthruPatchRecord ? frameCount / 4 : 1;
- sp<PlaybackThread::PatchTrack> tempPatchTrack = new PlaybackThread::PatchTrack(
+ sp<IAfPatchTrack> tempPatchTrack = IAfPatchTrack::create(
mPlayback.thread().get(),
streamType,
sampleRate,
@@ -636,18 +617,18 @@
return status;
}
-void AudioFlinger::PatchPanel::Patch::clearConnections(PatchPanel *panel)
+void PatchPanel::Patch::clearConnections_l(const sp<IAfPatchPanel>& panel)
{
ALOGV("%s() mRecord.handle %d mPlayback.handle %d",
__func__, mRecord.handle(), mPlayback.handle());
mRecord.stopTrack();
mPlayback.stopTrack();
mRecord.clearTrackPeer(); // mRecord stop is synchronous. Break PeerProxy sp<> cycle.
- mRecord.closeConnections(panel);
- mPlayback.closeConnections(panel);
+ mRecord.closeConnections_l(panel);
+ mPlayback.closeConnections_l(panel);
}
-status_t AudioFlinger::PatchPanel::Patch::getLatencyMs(double *latencyMs) const
+status_t PatchPanel::Patch::getLatencyMs(double* latencyMs) const
{
if (!isSoftware()) return INVALID_OPERATION;
@@ -679,7 +660,7 @@
// If so, do a frame diff and time difference computation to estimate
// the total patch latency. This requires that frame counts are reported by the
// HAL are matched properly in the case of record overruns and playback underruns.
- ThreadBase::TrackBase::FrameTime recordFT{}, playFT{};
+ IAfTrack::FrameTime recordFT{}, playFT{};
recordTrack->getKernelFrameTime(&recordFT);
playbackTrack->getKernelFrameTime(&playFT);
if (recordFT.timeNs > 0 && playFT.timeNs > 0) {
@@ -706,7 +687,7 @@
return INVALID_OPERATION;
}
-String8 AudioFlinger::PatchPanel::Patch::dump(audio_patch_handle_t myHandle) const
+String8 PatchPanel::Patch::dump(audio_patch_handle_t myHandle) const
{
// TODO: Consider table dump form for patches, just like tracks.
String8 result = String8::format("Patch %d: %s (thread %p => thread %p)",
@@ -734,8 +715,8 @@
}
/* Disconnect a patch */
-status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
- //unlocks AudioFlinger::mLock when calling ThreadBase::sendReleaseAudioPatchConfigEvent
+status_t PatchPanel::releaseAudioPatch_l(audio_patch_handle_t handle)
+ //unlocks AudioFlinger::mLock when calling IAfThreadBase::sendReleaseAudioPatchConfigEvent
//to avoid deadlocks if the thread loop needs to acquire AudioFlinger::mLock
//before processing the release patch request.
NO_THREAD_SAFETY_ANALYSIS
@@ -753,7 +734,7 @@
const struct audio_port_config &src = patch.sources[0];
switch (src.type) {
case AUDIO_PORT_TYPE_DEVICE: {
- sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(src.ext.device.hw_module);
+ sp<DeviceHalInterface> hwDevice = findHwDeviceByModule_l(src.ext.device.hw_module);
if (hwDevice == 0) {
ALOGW("%s() bad src hw module %d", __func__, src.ext.device.hw_module);
status = BAD_VALUE;
@@ -761,47 +742,47 @@
}
if (removedPatch.isSoftware()) {
- removedPatch.clearConnections(this);
+ removedPatch.clearConnections_l(this);
break;
}
if (patch.sinks[0].type == AUDIO_PORT_TYPE_MIX) {
audio_io_handle_t ioHandle = patch.sinks[0].ext.mix.handle;
- sp<ThreadBase> thread = mAudioFlinger.checkRecordThread_l(ioHandle);
+ sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkRecordThread_l(ioHandle);
if (thread == 0) {
- thread = mAudioFlinger.checkMmapThread_l(ioHandle);
+ thread = mAfPatchPanelCallback->checkMmapThread_l(ioHandle);
if (thread == 0) {
ALOGW("%s() bad capture I/O handle %d", __func__, ioHandle);
status = BAD_VALUE;
break;
}
}
- mAudioFlinger.unlock();
+ mAfPatchPanelCallback->mutex().unlock();
status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
- mAudioFlinger.lock();
+ mAfPatchPanelCallback->mutex().lock();
} else {
status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
}
} break;
case AUDIO_PORT_TYPE_MIX: {
- if (findHwDeviceByModule(src.ext.mix.hw_module) == 0) {
+ if (findHwDeviceByModule_l(src.ext.mix.hw_module) == 0) {
ALOGW("%s() bad src hw module %d", __func__, src.ext.mix.hw_module);
status = BAD_VALUE;
break;
}
audio_io_handle_t ioHandle = src.ext.mix.handle;
- sp<ThreadBase> thread = mAudioFlinger.checkPlaybackThread_l(ioHandle);
+ sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(ioHandle);
if (thread == 0) {
- thread = mAudioFlinger.checkMmapThread_l(ioHandle);
+ thread = mAfPatchPanelCallback->checkMmapThread_l(ioHandle);
if (thread == 0) {
ALOGW("%s() bad playback I/O handle %d", __func__, ioHandle);
status = BAD_VALUE;
break;
}
}
- mAudioFlinger.unlock();
+ mAfPatchPanelCallback->mutex().unlock();
status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
- mAudioFlinger.lock();
+ mAfPatchPanelCallback->mutex().lock();
} break;
default:
status = BAD_VALUE;
@@ -811,23 +792,23 @@
return status;
}
-void AudioFlinger::PatchPanel::erasePatch(audio_patch_handle_t handle) {
+void PatchPanel::erasePatch(audio_patch_handle_t handle) {
mPatches.erase(handle);
removeSoftwarePatchFromInsertedModules(handle);
- mAudioFlinger.mPatchCommandThread->releaseAudioPatch(handle);
+ mAfPatchPanelCallback->getPatchCommandThread()->releaseAudioPatch(handle);
}
/* List connected audio ports and they attributes */
-status_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused,
+status_t PatchPanel::listAudioPatches_l(unsigned int* /* num_patches */,
struct audio_patch *patches __unused)
{
ALOGV(__func__);
return NO_ERROR;
}
-status_t AudioFlinger::PatchPanel::getDownstreamSoftwarePatches(
+status_t PatchPanel::getDownstreamSoftwarePatches(
audio_io_handle_t stream,
- std::vector<AudioFlinger::PatchPanel::SoftwarePatch> *patches) const
+ std::vector<SoftwarePatch>* patches) const
{
for (const auto& module : mInsertedModules) {
if (module.second.streams.count(stream)) {
@@ -835,7 +816,8 @@
const auto& patch_iter = mPatches.find(patchHandle);
if (patch_iter != mPatches.end()) {
const Patch &patch = patch_iter->second;
- patches->emplace_back(*this, patchHandle,
+ patches->emplace_back(sp<const IAfPatchPanel>::fromExisting(this),
+ patchHandle,
patch.mPlayback.const_thread()->id(),
patch.mRecord.const_thread()->id());
} else {
@@ -849,7 +831,7 @@
return BAD_VALUE;
}
-void AudioFlinger::PatchPanel::notifyStreamOpened(
+void PatchPanel::notifyStreamOpened(
AudioHwDevice *audioHwDevice, audio_io_handle_t stream, struct audio_patch *patch)
{
if (audioHwDevice->isInsert()) {
@@ -867,41 +849,41 @@
}
}
-void AudioFlinger::PatchPanel::notifyStreamClosed(audio_io_handle_t stream)
+void PatchPanel::notifyStreamClosed(audio_io_handle_t stream)
{
for (auto& module : mInsertedModules) {
module.second.streams.erase(stream);
}
}
-AudioHwDevice* AudioFlinger::PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module)
+AudioHwDevice* PatchPanel::findAudioHwDeviceByModule_l(audio_module_handle_t module)
{
if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr;
- ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(module);
+ ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(module);
if (index < 0) {
ALOGW("%s() bad hw module %d", __func__, module);
return nullptr;
}
- return mAudioFlinger.mAudioHwDevs.valueAt(index);
+ return mAfPatchPanelCallback->getAudioHwDevs_l().valueAt(index);
}
-sp<DeviceHalInterface> AudioFlinger::PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
+sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule_l(audio_module_handle_t module)
{
- AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(module);
+ AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule_l(module);
return audioHwDevice ? audioHwDevice->hwDevice() : nullptr;
}
-void AudioFlinger::PatchPanel::addSoftwarePatchToInsertedModules(
+void PatchPanel::addSoftwarePatchToInsertedModules_l(
audio_module_handle_t module, audio_patch_handle_t handle,
const struct audio_patch *patch)
{
mInsertedModules[module].sw_patches.insert(handle);
if (!mInsertedModules[module].streams.empty()) {
- mAudioFlinger.updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
+ mAfPatchPanelCallback->updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
}
}
-void AudioFlinger::PatchPanel::removeSoftwarePatchFromInsertedModules(
+void PatchPanel::removeSoftwarePatchFromInsertedModules(
audio_patch_handle_t handle)
{
for (auto& module : mInsertedModules) {
@@ -909,7 +891,7 @@
}
}
-void AudioFlinger::PatchPanel::dump(int fd) const
+void PatchPanel::dump(int fd) const
{
String8 patchPanelDump;
const char *indent = " ";
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 5555766..1ff8fff 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -15,228 +15,77 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+#include "IAfPatchPanel.h"
-// PatchPanel is concealed within AudioFlinger, their lifetimes are the same.
-class PatchPanel {
+#include <map> // avoid transitive dependency
+#include <set> // avoid transitive dependency
+
+namespace android {
+
+class PatchPanel : public IAfPatchPanel {
public:
- class SoftwarePatch {
- public:
- SoftwarePatch(const PatchPanel &patchPanel, audio_patch_handle_t patchHandle,
- audio_io_handle_t playbackThreadHandle, audio_io_handle_t recordThreadHandle)
- : mPatchPanel(patchPanel), mPatchHandle(patchHandle),
- mPlaybackThreadHandle(playbackThreadHandle),
- mRecordThreadHandle(recordThreadHandle) {}
- SoftwarePatch(const SoftwarePatch&) = default;
-
- // Must be called under AudioFlinger::mLock
- status_t getLatencyMs_l(double *latencyMs) const;
- audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
- audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
- audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
- private:
- const PatchPanel &mPatchPanel;
- const audio_patch_handle_t mPatchHandle;
- const audio_io_handle_t mPlaybackThreadHandle;
- const audio_io_handle_t mRecordThreadHandle;
- };
-
- explicit PatchPanel(AudioFlinger* audioFlinger) : mAudioFlinger(*audioFlinger) {}
+ explicit PatchPanel(const sp<IAfPatchPanelCallback>& afPatchPanelCallback)
+ : mAfPatchPanelCallback(afPatchPanelCallback) {}
/* List connected audio ports and their attributes */
- status_t listAudioPorts(unsigned int *num_ports,
- struct audio_port *ports);
+ status_t listAudioPorts_l(unsigned int *num_ports,
+ struct audio_port* ports) final REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Get supported attributes for a given audio port */
- status_t getAudioPort(struct audio_port_v7 *port);
+ status_t getAudioPort_l(struct audio_port_v7* port) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Create a patch between several source and sink ports */
- status_t createAudioPatch(const struct audio_patch *patch,
+ status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle,
- bool endpointPatch = false);
+ bool endpointPatch = false) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Release a patch */
- status_t releaseAudioPatch(audio_patch_handle_t handle);
+ status_t releaseAudioPatch_l(audio_patch_handle_t handle) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* List connected audio devices and they attributes */
- status_t listAudioPatches(unsigned int *num_patches,
- struct audio_patch *patches);
+ status_t listAudioPatches_l(unsigned int *num_patches,
+ struct audio_patch* patches) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- // Retrieves all currently estrablished software patches for a stream
+ // Retrieves all currently established software patches for a stream
// opened on an intermediate module.
status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
- std::vector<SoftwarePatch> *patches) const;
+ std::vector<SoftwarePatch>* patches) const final;
// Notifies patch panel about all opened and closed streams.
void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
- struct audio_patch *patch);
- void notifyStreamClosed(audio_io_handle_t stream);
+ struct audio_patch* patch) final;
+ void notifyStreamClosed(audio_io_handle_t stream) final;
- void dump(int fd) const;
+ void dump(int fd) const final;
- template<typename ThreadType, typename TrackType>
- class Endpoint final {
- public:
- Endpoint() = default;
- Endpoint(const Endpoint&) = delete;
- Endpoint& operator=(const Endpoint& other) noexcept {
- mThread = other.mThread;
- mCloseThread = other.mCloseThread;
- mHandle = other.mHandle;
- mTrack = other.mTrack;
- return *this;
- }
- Endpoint(Endpoint&& other) noexcept { swap(other); }
- Endpoint& operator=(Endpoint&& other) noexcept {
- swap(other);
- return *this;
- }
- ~Endpoint() {
- ALOGE_IF(mHandle != AUDIO_PATCH_HANDLE_NONE,
- "A non empty Patch Endpoint leaked, handle %d", mHandle);
- }
+ const std::map<audio_patch_handle_t, Patch>& patches_l() const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex) { return mPatches; }
- status_t checkTrack(TrackType *trackOrNull) const {
- if (trackOrNull == nullptr) return NO_MEMORY;
- return trackOrNull->initCheck();
- }
- audio_patch_handle_t handle() const { return mHandle; }
- sp<ThreadType> thread() const { return mThread; }
- sp<TrackType> track() const { return mTrack; }
- sp<const ThreadType> const_thread() const { return mThread; }
- sp<const TrackType> const_track() const { return mTrack; }
+ status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- void closeConnections(PatchPanel *panel) {
- if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
- panel->releaseAudioPatch(mHandle);
- mHandle = AUDIO_PATCH_HANDLE_NONE;
- }
- if (mThread != 0) {
- if (mTrack != 0) {
- mThread->deletePatchTrack(mTrack);
- }
- if (mCloseThread) {
- panel->mAudioFlinger.closeThreadInternal_l(mThread);
- }
- }
- }
- audio_patch_handle_t* handlePtr() { return &mHandle; }
- void setThread(const sp<ThreadType>& thread, bool closeThread = true) {
- mThread = thread;
- mCloseThread = closeThread;
- }
- template <typename T>
- void setTrackAndPeer(const sp<TrackType>& track, const sp<T> &peer, bool holdReference) {
- mTrack = track;
- mThread->addPatchTrack(mTrack);
- mTrack->setPeerProxy(peer, holdReference);
- mClearPeerProxy = holdReference;
- }
- void clearTrackPeer() { if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy(); }
- void stopTrack() { if (mTrack) mTrack->stop(); }
-
- void swap(Endpoint &other) noexcept {
- using std::swap;
- swap(mThread, other.mThread);
- swap(mCloseThread, other.mCloseThread);
- swap(mClearPeerProxy, other.mClearPeerProxy);
- swap(mHandle, other.mHandle);
- swap(mTrack, other.mTrack);
- }
-
- friend void swap(Endpoint &a, Endpoint &b) noexcept {
- a.swap(b);
- }
-
- private:
- sp<ThreadType> mThread;
- bool mCloseThread = true;
- bool mClearPeerProxy = true;
- audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE;
- sp<TrackType> mTrack;
- };
-
- class Patch final {
- public:
- Patch(const struct audio_patch &patch, bool endpointPatch) :
- mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {}
- Patch() = default;
- ~Patch();
- Patch(const Patch& other) noexcept {
- mAudioPatch = other.mAudioPatch;
- mHalHandle = other.mHalHandle;
- mPlayback = other.mPlayback;
- mRecord = other.mRecord;
- mThread = other.mThread;
- mIsEndpointPatch = other.mIsEndpointPatch;
- }
- Patch(Patch&& other) noexcept { swap(other); }
- Patch& operator=(Patch&& other) noexcept {
- swap(other);
- return *this;
- }
-
- void swap(Patch &other) noexcept {
- using std::swap;
- swap(mAudioPatch, other.mAudioPatch);
- swap(mHalHandle, other.mHalHandle);
- swap(mPlayback, other.mPlayback);
- swap(mRecord, other.mRecord);
- swap(mThread, other.mThread);
- swap(mIsEndpointPatch, other.mIsEndpointPatch);
- }
-
- friend void swap(Patch &a, Patch &b) noexcept {
- a.swap(b);
- }
-
- status_t createConnections(PatchPanel *panel);
- void clearConnections(PatchPanel *panel);
- bool isSoftware() const {
- return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
- mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; }
-
- void setThread(const sp<ThreadBase>& thread) { mThread = thread; }
- wp<ThreadBase> thread() const { return mThread; }
-
- // returns the latency of the patch (from record to playback).
- status_t getLatencyMs(double *latencyMs) const;
-
- String8 dump(audio_patch_handle_t myHandle) const;
-
- // Note that audio_patch::id is only unique within a HAL module
- struct audio_patch mAudioPatch;
- // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0
- audio_patch_handle_t mHalHandle = AUDIO_PATCH_HANDLE_NONE;
- // below members are used by a software audio patch connecting a source device from a
- // given audio HW module to a sink device on an other audio HW module.
- // the objects are created by createConnections() and released by clearConnections()
- // playback thread is created if no existing playback thread can be used
- // connects playback thread output to sink device
- Endpoint<PlaybackThread, PlaybackThread::PatchTrack> mPlayback;
- // connects source device to record thread input
- Endpoint<RecordThread, RecordThread::PatchRecord> mRecord;
-
- wp<ThreadBase> mThread;
- bool mIsEndpointPatch;
- };
-
- // Call with AudioFlinger mLock held
- std::map<audio_patch_handle_t, Patch>& patches_l() { return mPatches; }
+ void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
private:
- AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
- sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
- void addSoftwarePatchToInsertedModules(
+ AudioHwDevice* findAudioHwDeviceByModule_l(audio_module_handle_t module)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ sp<DeviceHalInterface> findHwDeviceByModule_l(audio_module_handle_t module)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void addSoftwarePatchToInsertedModules_l(
audio_module_handle_t module, audio_patch_handle_t handle,
- const struct audio_patch *patch);
+ const struct audio_patch *patch)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
void erasePatch(audio_patch_handle_t handle);
- AudioFlinger &mAudioFlinger;
+ const sp<IAfPatchPanelCallback> mAfPatchPanelCallback;
std::map<audio_patch_handle_t, Patch> mPatches;
// This map allows going from a thread to "downstream" software patches
@@ -265,3 +114,5 @@
};
std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
};
+
+} // namespace android
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 464940e..15e85f9 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -15,12 +15,16 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
-#include <math.h>
-#include <sys/types.h>
+#include "TrackBase.h"
+
+#include <android/os/BnExternalVibrationController.h>
+#include <audio_utils/mutex.h>
+#include <audio_utils/LinearMap.h>
+#include <binder/AppOpsManager.h>
+
+namespace android {
// Checks and monitors OP_PLAY_AUDIO
class OpPlayAudioMonitor : public RefBase {
@@ -30,13 +34,13 @@
bool hasOpPlayAudio() const;
static sp<OpPlayAudioMonitor> createIfNeeded(
- AudioFlinger::ThreadBase* thread,
+ IAfThreadBase* thread,
const AttributionSourceState& attributionSource,
const audio_attributes_t& attr, int id,
audio_stream_type_t streamType);
private:
- OpPlayAudioMonitor(AudioFlinger::ThreadBase* thread,
+ OpPlayAudioMonitor(IAfThreadBase* thread,
const AttributionSourceState& attributionSource,
audio_usage_t usage, int id, uid_t uid);
void onFirstRef() override;
@@ -57,7 +61,7 @@
// called by PlayAudioOpCallback when OP_PLAY_AUDIO is updated in AppOp callback
void checkPlayAudioForUsage(bool doBroadcast);
- wp<AudioFlinger::ThreadBase> mThread;
+ wp<IAfThreadBase> mThread;
std::atomic_bool mHasOpPlayAudio;
const AttributionSourceState mAttributionSource;
const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as int32_t
@@ -67,9 +71,9 @@
};
// playback track
-class Track : public TrackBase, public VolumeProvider {
+class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider {
public:
- Track( PlaybackThread *thread,
+ Track(IAfPlaybackThread* thread,
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
@@ -92,72 +96,66 @@
float speed = 1.0f,
bool isSpatialized = false,
bool isBitPerfect = false);
- virtual ~Track();
- virtual status_t initCheck() const;
-
- void appendDumpHeader(String8& result);
- void appendDump(String8& result, bool active);
- virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
- audio_session_t triggerSession = AUDIO_SESSION_NONE);
- virtual void stop();
- void pause();
-
- void flush();
- void destroy();
-
- virtual uint32_t sampleRate() const;
-
- audio_stream_type_t streamType() const {
+ ~Track() override;
+ status_t initCheck() const final;
+ void appendDumpHeader(String8& result) const final;
+ void appendDump(String8& result, bool active) const final;
+ status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+ audio_session_t triggerSession = AUDIO_SESSION_NONE) override;
+ void stop() override;
+ void pause() final;
+ void flush() final;
+ void destroy() final;
+ uint32_t sampleRate() const final;
+ audio_stream_type_t streamType() const final {
return mStreamType;
}
- bool isOffloaded() const
+ bool isOffloaded() const final
{ return (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0; }
- bool isDirect() const override
+ bool isDirect() const final
{ return (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0; }
- bool isOffloadedOrDirect() const { return (mFlags
+ bool isOffloadedOrDirect() const final { return (mFlags
& (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
| AUDIO_OUTPUT_FLAG_DIRECT)) != 0; }
- bool isStatic() const { return mSharedBuffer.get() != nullptr; }
+ bool isStatic() const final { return mSharedBuffer.get() != nullptr; }
- status_t setParameters(const String8& keyValuePairs);
- status_t selectPresentation(int presentationId, int programId);
- status_t attachAuxEffect(int EffectId);
- void setAuxBuffer(int EffectId, int32_t *buffer);
- int32_t *auxBuffer() const { return mAuxBuffer; }
- void setMainBuffer(float *buffer) { mMainBuffer = buffer; }
- float *mainBuffer() const { return mMainBuffer; }
- int auxEffectId() const { return mAuxEffectId; }
- virtual status_t getTimestamp(AudioTimestamp& timestamp);
- void signal();
- status_t getDualMonoMode(audio_dual_mono_mode_t* mode);
- status_t setDualMonoMode(audio_dual_mono_mode_t mode);
- status_t getAudioDescriptionMixLevel(float* leveldB);
- status_t setAudioDescriptionMixLevel(float leveldB);
- status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate);
- status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate);
+ status_t setParameters(const String8& keyValuePairs) final;
+ status_t selectPresentation(int presentationId, int programId) final;
+ status_t attachAuxEffect(int EffectId) final;
+ void setAuxBuffer(int EffectId, int32_t* buffer) final;
+ int32_t* auxBuffer() const final { return mAuxBuffer; }
+ void setMainBuffer(float* buffer) final { mMainBuffer = buffer; }
+ float* mainBuffer() const final { return mMainBuffer; }
+ int auxEffectId() const final { return mAuxEffectId; }
+ status_t getTimestamp(AudioTimestamp& timestamp) final;
+ void signal() final;
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) const final;
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode) final;
+ status_t getAudioDescriptionMixLevel(float* leveldB) const final;
+ status_t setAudioDescriptionMixLevel(float leveldB) final;
+ status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) const final;
+ status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) final;
-// implement FastMixerState::VolumeProvider interface
- virtual gain_minifloat_packed_t getVolumeLR();
+ // implement FastMixerState::VolumeProvider interface
+ gain_minifloat_packed_t getVolumeLR() const final;
- status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
-
- virtual bool isFastTrack() const { return (mFlags & AUDIO_OUTPUT_FLAG_FAST) != 0; }
-
- double bufferLatencyMs() const override {
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
+ bool isFastTrack() const final { return (mFlags & AUDIO_OUTPUT_FLAG_FAST) != 0; }
+ double bufferLatencyMs() const final {
return isStatic() ? 0. : TrackBase::bufferLatencyMs();
}
-// implement volume handling.
+ // implement volume handling.
media::VolumeShaper::Status applyVolumeShaper(
const sp<media::VolumeShaper::Configuration>& configuration,
const sp<media::VolumeShaper::Operation>& operation);
- sp<media::VolumeShaper::State> getVolumeShaperState(int id);
- sp<media::VolumeHandler> getVolumeHandler() { return mVolumeHandler; }
+ sp<media::VolumeShaper::State> getVolumeShaperState(int id) const final;
+ sp<media::VolumeHandler> getVolumeHandler() const final{ return mVolumeHandler; }
/** Set the computed normalized final volume of the track.
* !masterMute * masterVolume * streamVolume * averageLRVolume */
- void setFinalVolume(float volumeLeft, float volumeRight);
- float getFinalVolume() const { return mFinalVolume; }
- void getFinalVolume(float* left, float* right) const {
+ void setFinalVolume(float volumeLeft, float volumeRight) final;
+ float getFinalVolume() const final { return mFinalVolume; }
+ void getFinalVolume(float* left, float* right) const final {
*left = mFinalVolumeLeft;
*right = mFinalVolumeRight;
}
@@ -165,21 +163,22 @@
using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
/** Copy the track metadata in the provided iterator. Thread safe. */
- virtual void copyMetadataTo(MetadataInserter& backInserter) const;
+ void copyMetadataTo(MetadataInserter& backInserter) const override;
+
/** Return haptic playback of the track is enabled or not, used in mixer. */
- bool getHapticPlaybackEnabled() const { return mHapticPlaybackEnabled; }
+ bool getHapticPlaybackEnabled() const final { return mHapticPlaybackEnabled; }
/** Set haptic playback of the track is enabled or not, should be
* set after query or get callback from vibrator service */
- void setHapticPlaybackEnabled(bool hapticPlaybackEnabled) {
+ void setHapticPlaybackEnabled(bool hapticPlaybackEnabled) final {
mHapticPlaybackEnabled = hapticPlaybackEnabled;
}
/** Return at what intensity to play haptics, used in mixer. */
- os::HapticScale getHapticIntensity() const { return mHapticIntensity; }
+ os::HapticScale getHapticIntensity() const final { return mHapticIntensity; }
/** Return the maximum amplitude allowed for haptics data, used in mixer. */
- float getHapticMaxAmplitude() const { return mHapticMaxAmplitude; }
+ float getHapticMaxAmplitude() const final { return mHapticMaxAmplitude; }
/** Set intensity of haptic playback, should be set after querying vibrator service. */
- void setHapticIntensity(os::HapticScale hapticIntensity) {
+ void setHapticIntensity(os::HapticScale hapticIntensity) final {
if (os::isValidHapticScale(hapticIntensity)) {
mHapticIntensity = hapticIntensity;
setHapticPlaybackEnabled(mHapticIntensity != os::HapticScale::MUTE);
@@ -188,16 +187,16 @@
/** Set maximum amplitude allowed for haptic data, should be set after querying
* vibrator service.
*/
- void setHapticMaxAmplitude(float maxAmplitude) {
+ void setHapticMaxAmplitude(float maxAmplitude) final {
mHapticMaxAmplitude = maxAmplitude;
}
- sp<os::ExternalVibration> getExternalVibration() const { return mExternalVibration; }
+ sp<os::ExternalVibration> getExternalVibration() const final { return mExternalVibration; }
// This function should be called with holding thread lock.
- void updateTeePatches();
- void setTeePatchesToUpdate(TeePatches teePatchesToUpdate);
+ void updateTeePatches() final;
+ void setTeePatchesToUpdate(TeePatches teePatchesToUpdate) final;
- void tallyUnderrunFrames(size_t frames) override {
+ void tallyUnderrunFrames(size_t frames) final {
if (isOut()) { // we expect this from output tracks only
mAudioTrackServerProxy->tallyUnderrunFrames(frames);
// Fetch absolute numbers from AudioTrackShared as it counts
@@ -208,29 +207,18 @@
}
}
- static bool checkServerLatencySupported(
- audio_format_t format, audio_output_flags_t flags) {
- return audio_is_linear_pcm(format)
- && (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) == 0;
- }
-
- audio_output_flags_t getOutputFlags() const { return mFlags; }
- float getSpeed() const { return mSpeed; }
- bool isSpatialized() const override { return mIsSpatialized; }
- bool isBitPerfect() const override { return mIsBitPerfect; }
+ audio_output_flags_t getOutputFlags() const final { return mFlags; }
+ float getSpeed() const final { return mSpeed; }
+ bool isSpatialized() const final { return mIsSpatialized; }
+ bool isBitPerfect() const final { return mIsBitPerfect; }
/**
* Updates the mute state and notifies the audio service. Call this only when holding player
* thread lock.
*/
- void processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState);
+ void processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState) final;
protected:
- // for numerous
- friend class PlaybackThread;
- friend class MixerThread;
- friend class DirectOutputThread;
- friend class OffloadThread;
DISALLOW_COPY_AND_ASSIGN(Track);
@@ -239,38 +227,39 @@
void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
// ExtendedAudioBufferProvider interface
- virtual size_t framesReady() const;
- virtual int64_t framesReleased() const;
- virtual void onTimestamp(const ExtendedTimestamp ×tamp);
+ size_t framesReady() const override;
+ int64_t framesReleased() const override;
+ void onTimestamp(const ExtendedTimestamp ×tamp) override;
- bool isPausing() const { return mState == PAUSING; }
- bool isPaused() const { return mState == PAUSED; }
- bool isResuming() const { return mState == RESUMING; }
- bool isReady() const;
- void setPaused() { mState = PAUSED; }
- void reset();
- bool isFlushPending() const { return mFlushHwPending; }
- void flushAck();
- bool isResumePending();
- void resumeAck();
+ // Used by thread
+ bool isPausing() const final { return mState == PAUSING; }
+ bool isPaused() const final { return mState == PAUSED; }
+ bool isResuming() const final { return mState == RESUMING; }
+ bool isReady() const final;
+ void setPaused() final { mState = PAUSED; }
+ void reset() final;
+ bool isFlushPending() const final { return mFlushHwPending; }
+ void flushAck() final;
+ bool isResumePending() const final;
+ void resumeAck() final;
// For direct or offloaded tracks ensure that the pause state is acknowledged
// by the playback thread in case of an immediate flush.
- bool isPausePending() const { return mPauseHwPending; }
- void pauseAck();
+ bool isPausePending() const final { return mPauseHwPending; }
+ void pauseAck() final;
void updateTrackFrameInfo(int64_t trackFramesReleased, int64_t sinkFramesWritten,
- uint32_t halSampleRate, const ExtendedTimestamp &timeStamp);
+ uint32_t halSampleRate, const ExtendedTimestamp& timeStamp) final;
- sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
+ sp<IMemory> sharedBuffer() const final { return mSharedBuffer; }
// presentationComplete checked by frames. (Mixed Tracks).
// framesWritten is cumulative, never reset, and is shared all tracks
// audioHalFrames is derived from output latency
- bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
+ bool presentationComplete(int64_t framesWritten, size_t audioHalFrames) final;
// presentationComplete checked by time. (Direct Tracks).
- bool presentationComplete(uint32_t latencyMs);
+ bool presentationComplete(uint32_t latencyMs) final;
- void resetPresentationComplete() {
+ void resetPresentationComplete() final {
mPresentationCompleteFrames = 0;
mPresentationCompleteTimeNs = 0;
}
@@ -281,25 +270,43 @@
void signalClientFlag(int32_t flag);
-public:
- void triggerEvents(AudioSystem::sync_event_t type);
- virtual void invalidate();
- void disable();
-
- int fastIndex() const { return mFastIndex; }
-
- bool isPlaybackRestricted() const {
+ void triggerEvents(AudioSystem::sync_event_t type) final;
+ void invalidate() final;
+ void disable() final;
+ int& fastIndex() final { return mFastIndex; }
+ bool isPlaybackRestricted() const final {
// The monitor is only created for tracks that can be silenced.
return mOpPlayAudioMonitor ? !mOpPlayAudioMonitor->hasOpPlayAudio() : false; }
-protected:
+ const sp<AudioTrackServerProxy>& audioTrackServerProxy() const final {
+ return mAudioTrackServerProxy;
+ }
+ bool hasVolumeController() const final { return mHasVolumeController; }
+ void setHasVolumeController(bool hasVolumeController) final {
+ mHasVolumeController = hasVolumeController;
+ }
+ void setCachedVolume(float volume) final {
+ mCachedVolume = volume;
+ }
+ void setResetDone(bool resetDone) final {
+ mResetDone = resetDone;
+ }
+ ExtendedAudioBufferProvider* asExtendedAudioBufferProvider() final {
+ return this;
+ }
+ VolumeProvider* asVolumeProvider() final {
+ return this;
+ }
- // FILLED state is used for suppressing volume ramp at begin of playing
- enum {FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE};
- mutable uint8_t mFillingUpStatus;
+ FillingStatus& fillingStatus() final { return mFillingStatus; }
+ int8_t& retryCount() final { return mRetryCount; }
+ FastTrackUnderruns& fastTrackUnderruns() final { return mObservedUnderruns; }
+
+protected:
+ mutable FillingStatus mFillingStatus;
int8_t mRetryCount;
- // see comment at AudioFlinger::PlaybackThread::Track::~Track for why this can't be const
+ // see comment at ~Track for why this can't be const
sp<IMemory> mSharedBuffer;
bool mResetDone;
@@ -377,7 +384,7 @@
bool mFlushHwPending; // track requests for thread flush
bool mPauseHwPending = false; // direct/offload track request for thread pause
audio_output_flags_t mFlags;
- TeePatches mTeePatches;
+ TeePatches mTeePatches;
std::optional<TeePatches> mTeePatchesToUpdate;
const float mSpeed;
const bool mIsSpatialized;
@@ -391,7 +398,7 @@
// playback track, used by DuplicatingThread
-class OutputTrack : public Track {
+class OutputTrack : public Track, public IAfOutputTrack {
public:
class Buffer : public AudioBufferProvider::Buffer {
@@ -399,29 +406,28 @@
void *mBuffer;
};
- OutputTrack(PlaybackThread *thread,
- DuplicatingThread *sourceThread,
+ OutputTrack(IAfPlaybackThread* thread,
+ IAfDuplicatingThread* sourceThread,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
const AttributionSourceState& attributionSource);
- virtual ~OutputTrack();
+ ~OutputTrack() override;
- virtual status_t start(AudioSystem::sync_event_t event =
+ status_t start(AudioSystem::sync_event_t event =
AudioSystem::SYNC_EVENT_NONE,
- audio_session_t triggerSession = AUDIO_SESSION_NONE);
- virtual void stop();
- ssize_t write(void* data, uint32_t frames);
- bool bufferQueueEmpty() const { return mBufferQueue.size() == 0; }
- bool isActive() const { return mActive; }
- const wp<ThreadBase>& thread() const { return mThread; }
+ audio_session_t triggerSession = AUDIO_SESSION_NONE) final;
+ void stop() final;
+ ssize_t write(void* data, uint32_t frames) final;
+ bool bufferQueueEmpty() const final { return mBufferQueue.size() == 0; }
+ bool isActive() const final { return mActive; }
- void copyMetadataTo(MetadataInserter& backInserter) const override;
+ void copyMetadataTo(MetadataInserter& backInserter) const final;
/** Set the metadatas of the upstream tracks. Thread safe. */
- void setMetadatas(const SourceMetadatas& metadatas);
+ void setMetadatas(const SourceMetadatas& metadatas) final;
/** returns client timestamp to the upstream duplicating thread. */
- ExtendedTimestamp getClientProxyTimestamp() const {
+ ExtendedTimestamp getClientProxyTimestamp() const final {
// server - kernel difference is not true latency when drained
// i.e. mServerProxy->isDrained().
ExtendedTimestamp timestamp;
@@ -432,7 +438,6 @@
// (with mTimeNs[] filled with -1's) is returned.
return timestamp;
}
-
private:
status_t obtainBuffer(AudioBufferProvider::Buffer* buffer,
uint32_t waitTimeMs);
@@ -447,7 +452,7 @@
Vector < Buffer* > mBufferQueue;
AudioBufferProvider::Buffer mOutBuffer;
bool mActive;
- DuplicatingThread* const mSourceThread; // for waitTimeMs() in write()
+ IAfDuplicatingThread* const mSourceThread; // for waitTimeMs() in write()
sp<AudioTrackClientProxy> mClientProxy;
/** Attributes of the source tracks.
@@ -463,14 +468,14 @@
*/
SourceMetadatas mTrackMetadatas;
/** Protects mTrackMetadatas against concurrent access. */
- mutable std::mutex mTrackMetadatasMutex;
+ audio_utils::mutex& trackMetadataMutex() const { return mTrackMetadataMutex; }
+ mutable audio_utils::mutex mTrackMetadataMutex;
}; // end of OutputTrack
// playback track, used by PatchPanel
-class PatchTrack : public Track, public PatchTrackBase {
+class PatchTrack : public Track, public PatchTrackBase, public IAfPatchTrack {
public:
-
- PatchTrack(PlaybackThread *playbackThread,
+ PatchTrack(IAfPlaybackThread* playbackThread,
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
@@ -484,23 +489,24 @@
* as soon as possible to have
* the lowest possible latency
* even if it might glitch. */);
- virtual ~PatchTrack();
+ ~PatchTrack() override;
- size_t framesReady() const override;
+ size_t framesReady() const final;
- virtual status_t start(AudioSystem::sync_event_t event =
+ status_t start(AudioSystem::sync_event_t event =
AudioSystem::SYNC_EVENT_NONE,
- audio_session_t triggerSession = AUDIO_SESSION_NONE);
+ audio_session_t triggerSession = AUDIO_SESSION_NONE) final;
// AudioBufferProvider interface
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
- virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+ status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) final;
+ void releaseBuffer(AudioBufferProvider::Buffer* buffer) final;
// PatchProxyBufferProvider interface
- virtual status_t obtainBuffer(Proxy::Buffer* buffer,
- const struct timespec *timeOut = NULL);
- virtual void releaseBuffer(Proxy::Buffer* buffer);
+ status_t obtainBuffer(Proxy::Buffer* buffer, const struct timespec* timeOut = nullptr) final;
+ void releaseBuffer(Proxy::Buffer* buffer) final;
private:
void restartIfDisabled();
}; // end of PatchTrack
+
+} // namespace android
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index d91a210..8d3de38 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -15,16 +15,20 @@
** limitations under the License.
*/
-#include <android/content/AttributionSourceState.h>
+#pragma once
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#include "TrackBase.h"
+
+#include <android/content/AttributionSourceState.h>
+#include <audio_utils/mutex.h>
+#include <datapath/AudioStreamIn.h> // struct Source
+
+namespace android {
// record track
-class RecordTrack : public TrackBase {
+class RecordTrack : public TrackBase, public virtual IAfRecordTrack {
public:
- RecordTrack(RecordThread *thread,
+ RecordTrack(IAfRecordThread* thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
@@ -40,67 +44,70 @@
track_type type,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
int32_t startFrames = -1);
- virtual ~RecordTrack();
- virtual status_t initCheck() const;
+ ~RecordTrack() override;
+ status_t initCheck() const final;
- virtual status_t start(AudioSystem::sync_event_t event, audio_session_t triggerSession);
- virtual void stop();
+ status_t start(AudioSystem::sync_event_t event, audio_session_t triggerSession) final;
+ void stop() final;
+ void destroy() final;
+ void invalidate() final;
- void destroy();
-
- virtual void invalidate();
// clear the buffer overflow flag
- void clearOverflow() { mOverflow = false; }
+ void clearOverflow() final { mOverflow = false; }
// set the buffer overflow flag and return previous value
- bool setOverflow() { bool tmp = mOverflow; mOverflow = true;
+ bool setOverflow() final { bool tmp = mOverflow; mOverflow = true;
return tmp; }
- void appendDumpHeader(String8& result);
- void appendDump(String8& result, bool active);
+ void appendDumpHeader(String8& result) const final;
+ void appendDump(String8& result, bool active) const final;
- void handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event);
- void clearSyncStartEvent();
+ void handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event) final;
+ void clearSyncStartEvent() final;
- void updateTrackFrameInfo(int64_t trackFramesReleased,
+ void updateTrackFrameInfo(int64_t trackFramesReleased,
int64_t sourceFramesRead,
uint32_t halSampleRate,
- const ExtendedTimestamp ×tamp);
+ const ExtendedTimestamp ×tamp) final;
- virtual bool isFastTrack() const { return (mFlags & AUDIO_INPUT_FLAG_FAST) != 0; }
- bool isDirect() const override
+ bool isFastTrack() const final { return (mFlags & AUDIO_INPUT_FLAG_FAST) != 0; }
+ bool isDirect() const final
{ return (mFlags & AUDIO_INPUT_FLAG_DIRECT) != 0; }
- void setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; }
- bool isSilenced() const { return mSilenced; }
+ void setSilenced(bool silenced) final { if (!isPatchTrack()) mSilenced = silenced; }
+ bool isSilenced() const final { return mSilenced; }
- status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones);
+ status_t getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) const final;
- status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
- status_t setPreferredMicrophoneFieldDimension(float zoom);
- status_t shareAudioHistory(const std::string& sharedAudioPackageName,
- int64_t sharedAudioStartMs);
- int32_t startFrames() { return mStartFrames; }
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) final;
+ status_t setPreferredMicrophoneFieldDimension(float zoom) final;
+ status_t shareAudioHistory(const std::string& sharedAudioPackageName,
+ int64_t sharedAudioStartMs) final;
+ int32_t startFrames() const final { return mStartFrames; }
- static bool checkServerLatencySupported(
- audio_format_t format, audio_input_flags_t flags) {
- return audio_is_linear_pcm(format)
- && (flags & AUDIO_INPUT_FLAG_HW_AV_SYNC) == 0;
- }
+ using SinkMetadatas = std::vector<record_track_metadata_v7_t>;
+ using MetadataInserter = std::back_insert_iterator<SinkMetadatas>;
+ void copyMetadataTo(MetadataInserter& backInserter) const final;
- using SinkMetadatas = std::vector<record_track_metadata_v7_t>;
- using MetadataInserter = std::back_insert_iterator<SinkMetadatas>;
- virtual void copyMetadataTo(MetadataInserter& backInserter) const;
+ AudioBufferProvider::Buffer& sinkBuffer() final { return mSink; }
+ audioflinger::SynchronizedRecordState& synchronizedRecordState() final {
+ return mSynchronizedRecordState;
+ }
+ RecordBufferConverter* recordBufferConverter() const final { return mRecordBufferConverter; }
+ ResamplerBufferProvider* resamplerBufferProvider() const final {
+ return mResamplerBufferProvider;
+ }
private:
- friend class AudioFlinger; // for mState
-
DISALLOW_COPY_AND_ASSIGN(RecordTrack);
+protected:
// AudioBufferProvider interface
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+ status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
// releaseBuffer() not overridden
+private:
+
bool mOverflow; // overflow on most recent attempt to fill client buffer
AudioBufferProvider::Buffer mSink; // references client's buffer sink in shared memory
@@ -113,7 +120,7 @@
mSynchronizedRecordState{mSampleRate}; // sampleRate defined in base
// used by resampler to find source frames
- ResamplerBufferProvider *mResamplerBufferProvider;
+ ResamplerBufferProvider* mResamplerBufferProvider;
// used by the record thread to convert frames to proper destination format
RecordBufferConverter *mRecordBufferConverter;
@@ -126,10 +133,9 @@
};
// playback track, used by PatchPanel
-class PatchRecord : public RecordTrack, public PatchTrackBase {
+class PatchRecord : public RecordTrack, public PatchTrackBase, public IAfPatchRecord {
public:
-
- PatchRecord(RecordThread *recordThread,
+ PatchRecord(IAfRecordThread* recordThread,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
audio_format_t format,
@@ -139,20 +145,20 @@
audio_input_flags_t flags,
const Timeout& timeout = {},
audio_source_t source = AUDIO_SOURCE_DEFAULT);
- virtual ~PatchRecord();
+ ~PatchRecord() override;
- virtual Source* getSource() { return nullptr; }
+ Source* getSource() override { return nullptr; }
// AudioBufferProvider interface
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
- virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+ status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
+ void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
// PatchProxyBufferProvider interface
- virtual status_t obtainBuffer(Proxy::Buffer *buffer,
- const struct timespec *timeOut = NULL);
- virtual void releaseBuffer(Proxy::Buffer *buffer);
+ status_t obtainBuffer(Proxy::Buffer* buffer,
+ const struct timespec* timeOut = nullptr) override;
+ void releaseBuffer(Proxy::Buffer* buffer) override;
- size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) {
+ size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) final {
return writeFrames(this, src, frameCount, frameSize);
}
@@ -165,7 +171,7 @@
class PassthruPatchRecord : public PatchRecord, public Source {
public:
- PassthruPatchRecord(RecordThread *recordThread,
+ PassthruPatchRecord(IAfRecordThread* recordThread,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
audio_format_t format,
@@ -173,25 +179,25 @@
audio_input_flags_t flags,
audio_source_t source = AUDIO_SOURCE_DEFAULT);
- Source* getSource() override { return static_cast<Source*>(this); }
+ Source* getSource() final { return static_cast<Source*>(this); }
// Source interface
- status_t read(void *buffer, size_t bytes, size_t *read) override;
- status_t getCapturePosition(int64_t *frames, int64_t *time) override;
- status_t standby() override;
+ status_t read(void* buffer, size_t bytes, size_t* read) final;
+ status_t getCapturePosition(int64_t* frames, int64_t* time) final;
+ status_t standby() final;
// AudioBufferProvider interface
// This interface is used by RecordThread to pass the data obtained
// from HAL or other source to the client. PassthruPatchRecord receives
// the data in 'obtainBuffer' so these calls are stubbed out.
- status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
- void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
+ status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) final;
+ void releaseBuffer(AudioBufferProvider::Buffer* buffer) final;
// PatchProxyBufferProvider interface
// This interface is used from DirectOutputThread to acquire data from HAL.
- bool producesBufferOnDemand() const override { return true; }
- status_t obtainBuffer(Proxy::Buffer *buffer, const struct timespec *timeOut = nullptr) override;
- void releaseBuffer(Proxy::Buffer *buffer) override;
+ bool producesBufferOnDemand() const final { return true; }
+ status_t obtainBuffer(Proxy::Buffer* buffer, const struct timespec* timeOut = nullptr) final;
+ void releaseBuffer(Proxy::Buffer* buffer) final;
private:
// This is to use with PatchRecord::writeFrames
@@ -208,15 +214,18 @@
PassthruPatchRecord& mPassthru;
};
- sp<StreamInHalInterface> obtainStream(sp<ThreadBase>* thread);
+ sp<StreamInHalInterface> obtainStream(sp<IAfThreadBase>* thread);
+ audio_utils::mutex& readMutex() const { return mReadMutex; }
PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
std::unique_ptr<void, decltype(free)*> mSinkBuffer; // frame size aligned continuous buffer
std::unique_ptr<void, decltype(free)*> mStubBuffer; // buffer used for AudioBufferProvider
size_t mUnconsumedFrames = 0;
- std::mutex mReadLock;
- std::condition_variable mReadCV;
- size_t mReadBytes = 0; // GUARDED_BY(mReadLock)
- status_t mReadError = NO_ERROR; // GUARDED_BY(mReadLock)
+ mutable audio_utils::mutex mReadMutex;
+ audio_utils::condition_variable mReadCV;
+ size_t mReadBytes = 0; // GUARDED_BY(readMutex())
+ status_t mReadError = NO_ERROR; // GUARDED_BY(readMutex())
int64_t mLastReadFrames = 0; // accessed on RecordThread only
};
+
+} // namespace android
diff --git a/services/audioflinger/ResamplerBufferProvider.h b/services/audioflinger/ResamplerBufferProvider.h
new file mode 100644
index 0000000..b697743
--- /dev/null
+++ b/services/audioflinger/ResamplerBufferProvider.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android {
+
+class IAfRecordTrack;
+
+/* The ResamplerBufferProvider is used to retrieve recorded input data from the
+ * RecordThread. It maintains local state on the relative position of the read
+ * position of the RecordTrack compared with the RecordThread.
+ */
+class ResamplerBufferProvider : public AudioBufferProvider
+{
+public:
+ explicit ResamplerBufferProvider(IAfRecordTrack* recordTrack) :
+ mRecordTrack(recordTrack) {}
+
+ // called to set the ResamplerBufferProvider to head of the RecordThread data buffer,
+ // skipping any previous data read from the hal.
+ void reset();
+
+ /* Synchronizes RecordTrack position with the RecordThread.
+ * Calculates available frames and handle overruns if the RecordThread
+ * has advanced faster than the ResamplerBufferProvider has retrieved data.
+ * TODO: why not do this for every getNextBuffer?
+ *
+ * Parameters
+ * framesAvailable: pointer to optional output size_t to store record track
+ * frames available.
+ * hasOverrun: pointer to optional boolean, returns true if track has overrun.
+ */
+
+ void sync(size_t* framesAvailable = nullptr, bool* hasOverrun = nullptr);
+
+ // AudioBufferProvider interface
+ status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) final;
+ void releaseBuffer(AudioBufferProvider::Buffer* buffer) final;
+
+ int32_t getFront() const { return mRsmpInFront; }
+ void setFront(int32_t front) { mRsmpInFront = front; }
+
+private:
+ IAfRecordTrack* const mRecordTrack;
+ size_t mRsmpInUnrel = 0; // unreleased frames remaining from
+ // most recent getNextBuffer
+ // for debug only
+ int32_t mRsmpInFront = 0; // next available frame
+ // rolling counter that is never cleared
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 1530697..0b73fba 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -20,45 +20,49 @@
// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_AUDIO
-#include "Configuration.h"
-#include <math.h>
-#include <fcntl.h>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <linux/futex.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
+#include "Threads.h"
+
+#include "Client.h"
+#include "IAfEffect.h"
+#include "MelReporter.h"
+#include "ResamplerBufferProvider.h"
+
+#include <afutils/DumpTryLock.h>
+#include <afutils/Permission.h>
+#include <afutils/TypedLogger.h>
+#include <afutils/Vibrator.h>
+#include <audio_utils/MelProcessor.h>
+#include <audio_utils/Metadata.h>
+#ifdef DEBUG_CPU_USAGE
+#include <audio_utils/Statistics.h>
+#include <cpustats/ThreadCpuUsage.h>
+#endif
+#include <audio_utils/channels.h>
+#include <audio_utils/format.h>
+#include <audio_utils/minifloat.h>
+#include <audio_utils/mono_blend.h>
+#include <audio_utils/primitives.h>
+#include <audio_utils/safe_math.h>
+#include <audiomanager/AudioManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/PersistableBundle.h>
#include <cutils/bitops.h>
#include <cutils/properties.h>
-#include <binder/PersistableBundle.h>
+#include <fastpath/AutoPark.h>
#include <media/AudioContainers.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioParameter.h>
#include <media/AudioResamplerPublic.h>
+#ifdef ADD_BATTERY_DATA
+#include <media/IMediaPlayerService.h>
+#include <media/IMediaDeathNotifier.h>
+#endif
+#include <media/MmapStreamCallback.h>
#include <media/RecordBufferConverter.h>
#include <media/TypeConverter.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
-
-#include <private/media/AudioTrackShared.h>
-#include <private/android_filesystem_config.h>
-#include <audio_utils/Balance.h>
-#include <audio_utils/MelProcessor.h>
-#include <audio_utils/Metadata.h>
-#include <audio_utils/channels.h>
-#include <audio_utils/mono_blend.h>
-#include <audio_utils/primitives.h>
-#include <audio_utils/format.h>
-#include <audio_utils/minifloat.h>
-#include <audio_utils/safe_math.h>
-#include <system/audio_effects/effect_aec.h>
-#include <system/audio_effects/effect_downmix.h>
-#include <system/audio_effects/effect_ns.h>
-#include <system/audio_effects/effect_spatializer.h>
-#include <system/audio.h>
-
-// NBAIO implementations
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
#include <media/nbaio/AudioStreamInSource.h>
#include <media/nbaio/AudioStreamOutSink.h>
#include <media/nbaio/MonoPipe.h>
@@ -68,31 +72,27 @@
#include <media/nbaio/SourceAudioBufferProvider.h>
#include <mediautils/BatteryNotifier.h>
#include <mediautils/Process.h>
-
-#include <audiomanager/AudioManager.h>
-#include <powermanager/PowerManager.h>
-
-#include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <media/audiohal/StreamHalInterface.h>
-
-#include "AudioFlinger.h"
#include <mediautils/SchedulingPolicyService.h>
#include <mediautils/ServiceUtilities.h>
+#include <powermanager/PowerManager.h>
+#include <private/android_filesystem_config.h>
+#include <private/media/AudioTrackShared.h>
+#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_downmix.h>
+#include <system/audio_effects/effect_ns.h>
+#include <system/audio_effects/effect_spatializer.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
-#ifdef ADD_BATTERY_DATA
-#include <media/IMediaPlayerService.h>
-#include <media/IMediaDeathNotifier.h>
-#endif
-
-#ifdef DEBUG_CPU_USAGE
-#include <audio_utils/Statistics.h>
-#include <cpustats/ThreadCpuUsage.h>
-#endif
-
-#include <fastpath/AutoPark.h>
-
+#include <fcntl.h>
+#include <linux/futex.h>
+#include <math.h>
+#include <memory>
#include <pthread.h>
-#include <afutils/TypedLogger.h>
+#include <sstream>
+#include <string>
+#include <sys/stat.h>
+#include <sys/syscall.h>
// ----------------------------------------------------------------------------
@@ -120,9 +120,13 @@
namespace android {
+using audioflinger::SyncEvent;
using media::IEffectClient;
using content::AttributionSourceState;
+// Keep in sync with java definition in media/java/android/media/AudioRecord.java
+static constexpr int32_t kMaxSharedAudioHistoryMs = 5000;
+
// retry counts for buffer fill timeout
// 50 * ~20msecs = 1 second
static const int8_t kMaxTrackRetries = 50;
@@ -239,8 +243,84 @@
// and that all "fast" AudioRecord clients read from. In either case, the size can be small.
static const size_t kRecordThreadReadOnlyHeapSize = 0xD000;
+static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
+
+static nsecs_t getStandbyTimeInNanos() {
+ static nsecs_t standbyTimeInNanos = []() {
+ const int ms = property_get_int32("ro.audio.flinger_standbytime_ms",
+ kDefaultStandbyTimeInNsecs / NANOS_PER_MILLISECOND);
+ ALOGI("%s: Using %d ms as standby time", __func__, ms);
+ return milliseconds(ms);
+ }();
+ return standbyTimeInNanos;
+}
+
+// Set kEnableExtendedChannels to true to enable greater than stereo output
+// for the MixerThread and device sink. Number of channels allowed is
+// FCC_2 <= channels <= FCC_LIMIT.
+constexpr bool kEnableExtendedChannels = true;
+
+// Returns true if channel mask is permitted for the PCM sink in the MixerThread
+/* static */
+bool IAfThreadBase::isValidPcmSinkChannelMask(audio_channel_mask_t channelMask) {
+ switch (audio_channel_mask_get_representation(channelMask)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION: {
+ // Haptic channel mask is only applicable for channel position mask.
+ const uint32_t channelCount = audio_channel_count_from_out_mask(
+ static_cast<audio_channel_mask_t>(channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL));
+ const uint32_t maxChannelCount = kEnableExtendedChannels
+ ? FCC_LIMIT : FCC_2;
+ if (channelCount < FCC_2 // mono is not supported at this time
+ || channelCount > maxChannelCount) {
+ return false;
+ }
+ // check that channelMask is the "canonical" one we expect for the channelCount.
+ return audio_channel_position_mask_is_out_canonical(channelMask);
+ }
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ if (kEnableExtendedChannels) {
+ const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
+ if (channelCount >= FCC_2 // mono is not supported at this time
+ && channelCount <= FCC_LIMIT) {
+ return true;
+ }
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+// Set kEnableExtendedPrecision to true to use extended precision in MixerThread
+constexpr bool kEnableExtendedPrecision = true;
+
+// Returns true if format is permitted for the PCM sink in the MixerThread
+/* static */
+bool IAfThreadBase::isValidPcmSinkFormat(audio_format_t format) {
+ switch (format) {
+ case AUDIO_FORMAT_PCM_16_BIT:
+ return true;
+ case AUDIO_FORMAT_PCM_FLOAT:
+ case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ case AUDIO_FORMAT_PCM_32_BIT:
+ case AUDIO_FORMAT_PCM_8_24_BIT:
+ return kEnableExtendedPrecision;
+ default:
+ return false;
+ }
+}
+
// ----------------------------------------------------------------------------
+// formatToString() needs to be exact for MediaMetrics purposes.
+// Do not use media/TypeConverter.h toString().
+/* static */
+std::string IAfThreadBase::formatToString(audio_format_t format) {
+ std::string result;
+ FormatConverter::toString(format, result);
+ return result;
+}
+
// TODO: move all toString helpers to audio.h
// under #ifdef __cplusplus #endif
static std::string patchSinksToString(const struct audio_patch *patch)
@@ -515,7 +595,7 @@
// ----------------------------------------------------------------------------
// static
-const char *AudioFlinger::ThreadBase::threadTypeToString(AudioFlinger::ThreadBase::type_t type)
+const char* ThreadBase::threadTypeToString(ThreadBase::type_t type)
{
switch (type) {
case MIXER:
@@ -541,11 +621,11 @@
}
}
-AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+ThreadBase::ThreadBase(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
type_t type, bool systemReady, bool isOut)
: Thread(false /*canCallJava*/),
mType(type),
- mAudioFlinger(audioFlinger),
+ mAfThreadCallback(afThreadCallback),
mThreadMetrics(std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(id),
isOut),
mIsOut(isOut),
@@ -564,7 +644,7 @@
memset(&mPatch, 0, sizeof(struct audio_patch));
}
-AudioFlinger::ThreadBase::~ThreadBase()
+ThreadBase::~ThreadBase()
{
// mConfigEvents should be empty, but just in case it isn't, free the memory it owns
mConfigEvents.clear();
@@ -579,7 +659,7 @@
sendStatistics(true /* force */);
}
-status_t AudioFlinger::ThreadBase::readyToRun()
+status_t ThreadBase::readyToRun()
{
status_t status = initCheck();
if (status == NO_ERROR) {
@@ -590,7 +670,7 @@
return status;
}
-void AudioFlinger::ThreadBase::exit()
+void ThreadBase::exit()
{
ALOGV("ThreadBase::exit");
// do any cleanup required for exit to succeed
@@ -605,26 +685,26 @@
// mWaitWorkCV.wait(...);
// // now thread is hung
// }
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
requestExit();
- mWaitWorkCV.broadcast();
+ mWaitWorkCV.notify_all();
}
// When Thread::requestExitAndWait is made virtual and this method is renamed to
// "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
requestExitAndWait();
}
-status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
+status_t ThreadBase::setParameters(const String8& keyValuePairs)
{
ALOGV("ThreadBase::setParameters() %s", keyValuePairs.c_str());
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return sendSetParameterConfigEvent_l(keyValuePairs);
}
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from processConfigEvents_l().
-status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
+status_t ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
NO_THREAD_SAFETY_ANALYSIS // condition variable
{
status_t status = NO_ERROR;
@@ -636,31 +716,32 @@
}
mConfigEvents.add(event);
ALOGV("sendConfigEvent_l() num events %zu event %d", mConfigEvents.size(), event->mType);
- mWaitWorkCV.signal();
- mLock.unlock();
+ mWaitWorkCV.notify_one();
+ mutex().unlock();
{
- Mutex::Autolock _l(event->mLock);
+ audio_utils::unique_lock _l(event->mutex());
while (event->mWaitStatus) {
- if (event->mCond.waitRelative(event->mLock, kConfigEventTimeoutNs) != NO_ERROR) {
+ if (event->mCondition.wait_for(_l, std::chrono::nanoseconds(kConfigEventTimeoutNs))
+ == std::cv_status::timeout) {
event->mStatus = TIMED_OUT;
event->mWaitStatus = false;
}
}
status = event->mStatus;
}
- mLock.lock();
+ mutex().lock();
return status;
}
-void AudioFlinger::ThreadBase::sendIoConfigEvent(audio_io_config_event_t event, pid_t pid,
+void ThreadBase::sendIoConfigEvent(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sendIoConfigEvent_l(event, pid, portId);
}
-// sendIoConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid,
+// sendIoConfigEvent_l() must be called with ThreadBase::mutex() held
+void ThreadBase::sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId)
{
// The audio statistics history is exponentially weighted to forget events
@@ -677,22 +758,22 @@
sendConfigEvent_l(configEvent);
}
-void AudioFlinger::ThreadBase::sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp)
+void ThreadBase::sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sendPrioConfigEvent_l(pid, tid, prio, forApp);
}
-// sendPrioConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(
+// sendPrioConfigEvent_l() must be called with ThreadBase::mutex() held
+void ThreadBase::sendPrioConfigEvent_l(
pid_t pid, pid_t tid, int32_t prio, bool forApp)
{
sp<ConfigEvent> configEvent = (ConfigEvent *)new PrioConfigEvent(pid, tid, prio, forApp);
sendConfigEvent_l(configEvent);
}
-// sendSetParameterConfigEvent_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
+// sendSetParameterConfigEvent_l() must be called with ThreadBase::mutex() held
+status_t ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
{
sp<ConfigEvent> configEvent;
AudioParameter param(keyValuePair);
@@ -710,11 +791,11 @@
return sendConfigEvent_l(configEvent);
}
-status_t AudioFlinger::ThreadBase::sendCreateAudioPatchConfigEvent(
+status_t ThreadBase::sendCreateAudioPatchConfigEvent(
const struct audio_patch *patch,
audio_patch_handle_t *handle)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<ConfigEvent> configEvent = (ConfigEvent *)new CreateAudioPatchConfigEvent(*patch, *handle);
status_t status = sendConfigEvent_l(configEvent);
if (status == NO_ERROR) {
@@ -725,27 +806,27 @@
return status;
}
-status_t AudioFlinger::ThreadBase::sendReleaseAudioPatchConfigEvent(
+status_t ThreadBase::sendReleaseAudioPatchConfigEvent(
const audio_patch_handle_t handle)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<ConfigEvent> configEvent = (ConfigEvent *)new ReleaseAudioPatchConfigEvent(handle);
return sendConfigEvent_l(configEvent);
}
-status_t AudioFlinger::ThreadBase::sendUpdateOutDeviceConfigEvent(
+status_t ThreadBase::sendUpdateOutDeviceConfigEvent(
const DeviceDescriptorBaseVector& outDevices)
{
if (type() != RECORD) {
// The update out device operation is only for record thread.
return INVALID_OPERATION;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<ConfigEvent> configEvent = (ConfigEvent *)new UpdateOutDevicesConfigEvent(outDevices);
return sendConfigEvent_l(configEvent);
}
-void AudioFlinger::ThreadBase::sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs)
+void ThreadBase::sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs)
{
ALOG_ASSERT(type() == RECORD, "sendResizeBufferConfigEvent_l() called on non record thread");
sp<ConfigEvent> configEvent =
@@ -753,27 +834,27 @@
sendConfigEvent_l(configEvent);
}
-void AudioFlinger::ThreadBase::sendCheckOutputStageEffectsEvent()
+void ThreadBase::sendCheckOutputStageEffectsEvent()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sendCheckOutputStageEffectsEvent_l();
}
-void AudioFlinger::ThreadBase::sendCheckOutputStageEffectsEvent_l()
+void ThreadBase::sendCheckOutputStageEffectsEvent_l()
{
sp<ConfigEvent> configEvent =
(ConfigEvent *)new CheckOutputStageEffectsEvent();
sendConfigEvent_l(configEvent);
}
-void AudioFlinger::ThreadBase::sendHalLatencyModesChangedEvent_l()
+void ThreadBase::sendHalLatencyModesChangedEvent_l()
{
sp<ConfigEvent> configEvent = sp<HalLatencyModesChangedEvent>::make();
sendConfigEvent_l(configEvent);
}
// post condition: mConfigEvents.isEmpty()
-void AudioFlinger::ThreadBase::processConfigEvents_l()
+void ThreadBase::processConfigEvents_l()
{
bool configChanged = false;
@@ -850,10 +931,10 @@
break;
}
{
- Mutex::Autolock _l(event->mLock);
+ audio_utils::lock_guard _l(event->mutex());
if (event->mWaitStatus) {
event->mWaitStatus = false;
- event->mCond.signal();
+ event->mCondition.notify_one();
}
}
ALOGV_IF(mConfigEvents.isEmpty(), "processConfigEvents_l() DONE thread %p", this);
@@ -940,13 +1021,13 @@
}
}
-void AudioFlinger::ThreadBase::dump(int fd, const Vector<String16>& args)
+void ThreadBase::dump(int fd, const Vector<String16>& args)
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
dprintf(fd, "\n%s thread %p, name %s, tid %d, type %d (%s):\n", isOutput() ? "Output" : "Input",
this, mThreadName, getTid(), type(), threadTypeToString(type()));
- bool locked = AudioFlinger::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
if (!locked) {
dprintf(fd, " Thread may be deadlocked\n");
}
@@ -957,7 +1038,7 @@
dumpEffectChains_l(fd, args);
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
dprintf(fd, " Local log:\n");
@@ -978,18 +1059,20 @@
}
}
-void AudioFlinger::ThreadBase::dumpBase_l(int fd, const Vector<String16>& args __unused)
+void ThreadBase::dumpBase_l(int fd, const Vector<String16>& /* args */)
{
dprintf(fd, " I/O handle: %d\n", mId);
dprintf(fd, " Standby: %s\n", mStandby ? "yes" : "no");
dprintf(fd, " Sample rate: %u Hz\n", mSampleRate);
dprintf(fd, " HAL frame count: %zu\n", mFrameCount);
- dprintf(fd, " HAL format: 0x%x (%s)\n", mHALFormat, formatToString(mHALFormat).c_str());
+ dprintf(fd, " HAL format: 0x%x (%s)\n", mHALFormat,
+ IAfThreadBase::formatToString(mHALFormat).c_str());
dprintf(fd, " HAL buffer size: %zu bytes\n", mBufferSize);
dprintf(fd, " Channel count: %u\n", mChannelCount);
dprintf(fd, " Channel mask: 0x%08x (%s)\n", mChannelMask,
channelMaskToString(mChannelMask, mType != RECORD).c_str());
- dprintf(fd, " Processing format: 0x%x (%s)\n", mFormat, formatToString(mFormat).c_str());
+ dprintf(fd, " Processing format: 0x%x (%s)\n", mFormat,
+ IAfThreadBase::formatToString(mFormat).c_str());
dprintf(fd, " Processing frame size: %zu bytes\n", mFrameSize);
dprintf(fd, " Pending config events:");
size_t numConfig = mConfigEvents.size();
@@ -1051,7 +1134,7 @@
}
}
-void AudioFlinger::ThreadBase::dumpEffectChains_l(int fd, const Vector<String16>& args)
+void ThreadBase::dumpEffectChains_l(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
char buffer[SIZE];
@@ -1061,20 +1144,20 @@
write(fd, buffer, strlen(buffer));
for (size_t i = 0; i < numEffectChains; ++i) {
- sp<EffectChain> chain = mEffectChains[i];
+ sp<IAfEffectChain> chain = mEffectChains[i];
if (chain != 0) {
chain->dump(fd, args);
}
}
}
-void AudioFlinger::ThreadBase::acquireWakeLock()
+void ThreadBase::acquireWakeLock()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
acquireWakeLock_l();
}
-String16 AudioFlinger::ThreadBase::getWakeLockTag()
+String16 ThreadBase::getWakeLockTag()
{
switch (mType) {
case MIXER:
@@ -1099,7 +1182,7 @@
}
}
-void AudioFlinger::ThreadBase::acquireWakeLock_l()
+void ThreadBase::acquireWakeLock_l()
{
getPowerManager_l();
if (mPowerManager != 0) {
@@ -1122,13 +1205,13 @@
gBoottime.getBoottimeOffset();
}
-void AudioFlinger::ThreadBase::releaseWakeLock()
+void ThreadBase::releaseWakeLock()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
releaseWakeLock_l();
}
-void AudioFlinger::ThreadBase::releaseWakeLock_l()
+void ThreadBase::releaseWakeLock_l()
{
gBoottime.release(mWakeLockToken);
if (mWakeLockToken != 0) {
@@ -1140,7 +1223,7 @@
}
}
-void AudioFlinger::ThreadBase::getPowerManager_l() {
+void ThreadBase::getPowerManager_l() {
if (mSystemReady && mPowerManager == 0) {
// use checkService() to avoid blocking if power service is not up yet
sp<IBinder> binder =
@@ -1154,7 +1237,7 @@
}
}
-void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<uid_t> &uids) {
+void ThreadBase::updateWakeLockUids_l(const SortedVector<uid_t>& uids) {
getPowerManager_l();
#if !LOG_NDEBUG
@@ -1181,25 +1264,25 @@
}
}
-void AudioFlinger::ThreadBase::clearPowerManager()
+void ThreadBase::clearPowerManager()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
releaseWakeLock_l();
mPowerManager.clear();
}
-void AudioFlinger::ThreadBase::updateOutDevices(
+void ThreadBase::updateOutDevices(
const DeviceDescriptorBaseVector& outDevices __unused)
{
ALOGE("%s should only be called in RecordThread", __func__);
}
-void AudioFlinger::ThreadBase::resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs __unused)
+void ThreadBase::resizeInputBuffer_l(int32_t /* maxSharedAudioHistoryMs */)
{
ALOGE("%s should only be called in RecordThread", __func__);
}
-void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused)
+void ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& /* who */)
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
@@ -1208,10 +1291,10 @@
ALOGW("power manager service died !!!");
}
-void AudioFlinger::ThreadBase::setEffectSuspended_l(
+void ThreadBase::setEffectSuspended_l(
const effect_uuid_t *type, bool suspend, audio_session_t sessionId)
{
- sp<EffectChain> chain = getEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
if (chain != 0) {
if (type != NULL) {
chain->setEffectSuspended_l(type, suspend);
@@ -1223,7 +1306,7 @@
updateSuspendedSessions_l(type, suspend, sessionId);
}
-void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
+void ThreadBase::checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain)
{
ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
if (index < 0) {
@@ -1236,7 +1319,7 @@
for (size_t i = 0; i < sessionEffects.size(); i++) {
const sp<SuspendedSessionDesc>& desc = sessionEffects.valueAt(i);
for (int j = 0; j < desc->mRefCount; j++) {
- if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
+ if (sessionEffects.keyAt(i) == IAfEffectChain::kKeyForSuspendAll) {
chain->setEffectSuspendedAll_l(true);
} else {
ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
@@ -1247,7 +1330,7 @@
}
}
-void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
+void ThreadBase::updateSuspendedSessions_l(const effect_uuid_t* type,
bool suspend,
audio_session_t sessionId)
{
@@ -1269,7 +1352,7 @@
}
- int key = EffectChain::kKeyForSuspendAll;
+ int key = IAfEffectChain::kKeyForSuspendAll;
if (type != NULL) {
key = type->timeLow;
}
@@ -1308,13 +1391,13 @@
}
}
-void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
+void ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
audio_session_t sessionId,
bool threadLocked)
NO_THREAD_SAFETY_ANALYSIS // manual locking
{
if (!threadLocked) {
- mLock.lock();
+ mutex().lock();
}
if (mType != RECORD) {
@@ -1329,12 +1412,12 @@
}
if (!threadLocked) {
- mLock.unlock();
+ mutex().unlock();
}
}
-// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::RecordThread::checkEffectCompatibility_l(
+// checkEffectCompatibility_l() must be called with ThreadBase::mutex() held
+status_t RecordThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
// No global output effect sessions on record threads
@@ -1370,15 +1453,15 @@
}
}
- if (EffectModule::isHapticGenerator(&desc->type)) {
+ if (IAfEffectModule::isHapticGenerator(&desc->type)) {
ALOGE("%s(): HapticGenerator is not supported in RecordThread", __func__);
return BAD_VALUE;
}
return NO_ERROR;
}
-// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::PlaybackThread::checkEffectCompatibility_l(
+// checkEffectCompatibility_l() must be called with ThreadBase::mutex() held
+status_t PlaybackThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
// no preprocessing on playback threads
@@ -1393,7 +1476,7 @@
return NO_ERROR;
}
- if (EffectModule::isHapticGenerator(&desc->type) && mHapticChannelCount == 0) {
+ if (IAfEffectModule::isHapticGenerator(&desc->type) && mHapticChannelCount == 0) {
ALOGW("%s: thread doesn't support haptic playback while the effect is HapticGenerator",
__func__);
return BAD_VALUE;
@@ -1532,9 +1615,9 @@
return NO_ERROR;
}
-// ThreadBase::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
- const sp<AudioFlinger::Client>& client,
+// ThreadBase::createEffect_l() must be called with AudioFlinger::mutex() held
+sp<IAfEffectHandle> ThreadBase::createEffect_l(
+ const sp<Client>& client,
const sp<IEffectClient>& effectClient,
int32_t priority,
audio_session_t sessionId,
@@ -1545,10 +1628,10 @@
bool probe,
bool notifyFramesProcessed)
{
- sp<EffectModule> effect;
- sp<EffectHandle> handle;
+ sp<IAfEffectModule> effect;
+ sp<IAfEffectHandle> handle;
status_t lStatus;
- sp<EffectChain> chain;
+ sp<IAfEffectChain> chain;
bool chainCreated = false;
bool effectCreated = false;
audio_unique_id_t effectId = AUDIO_UNIQUE_ID_USE_UNSPECIFIED;
@@ -1561,8 +1644,8 @@
ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::lock_guard _l(mutex());
lStatus = checkEffectCompatibility_l(desc, sessionId);
if (probe || lStatus != NO_ERROR) {
@@ -1574,7 +1657,7 @@
if (chain == 0) {
// create a new chain for this session
ALOGV("createEffect_l() new effect chain for session %d", sessionId);
- chain = new EffectChain(this, sessionId);
+ chain = IAfEffectChain::create(this, sessionId);
addEffectChain_l(chain);
chain->setStrategy(getStrategyForSession_l(sessionId));
chainCreated = true;
@@ -1585,7 +1668,7 @@
ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
if (effect == 0) {
- effectId = mAudioFlinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
+ effectId = mAfThreadCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
// create a new effect module if none present in the chain
lStatus = chain->createEffect_l(effect, desc, effectId, sessionId, pinned);
if (lStatus != NO_ERROR) {
@@ -1596,21 +1679,22 @@
// FIXME: use vector of device and address when effect interface is ready.
effect->setDevices(outDeviceTypeAddrs());
effect->setInputDevice(inDeviceTypeAddr());
- effect->setMode(mAudioFlinger->getMode());
+ effect->setMode(mAfThreadCallback->getMode());
effect->setAudioSource(mAudioSource);
}
if (effect->isHapticGenerator()) {
// TODO(b/184194057): Use the vibrator information from the vibrator that will be used
// for the HapticGenerator.
const std::optional<media::AudioVibratorInfo> defaultVibratorInfo =
- std::move(mAudioFlinger->getDefaultVibratorInfo_l());
+ std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
if (defaultVibratorInfo) {
// Only set the vibrator info when it is a valid one.
effect->setVibratorInfo(*defaultVibratorInfo);
}
}
// create effect handle and connect it to effect module
- handle = new EffectHandle(effect, client, effectClient, priority, notifyFramesProcessed);
+ handle = IAfEffectHandle::create(
+ effect, client, effectClient, priority, notifyFramesProcessed);
lStatus = handle->initCheck();
if (lStatus == OK) {
lStatus = effect->addHandle(handle.get());
@@ -1623,7 +1707,7 @@
Exit:
if (!probe && lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (effectCreated) {
chain->removeEffect_l(effect);
}
@@ -1637,14 +1721,14 @@
return handle;
}
-void AudioFlinger::ThreadBase::disconnectEffectHandle(EffectHandle *handle,
+void ThreadBase::disconnectEffectHandle(IAfEffectHandle* handle,
bool unpinIfLast)
{
bool remove = false;
- sp<EffectModule> effect;
+ sp<IAfEffectModule> effect;
{
- Mutex::Autolock _l(mLock);
- sp<EffectBase> effectBase = handle->effect().promote();
+ audio_utils::lock_guard _l(mutex());
+ sp<IAfEffectBase> effectBase = handle->effect().promote();
if (effectBase == nullptr) {
return;
}
@@ -1660,16 +1744,16 @@
sendCheckOutputStageEffectsEvent_l();
}
if (remove) {
- mAudioFlinger->updateOrphanEffectChains(effect);
+ mAfThreadCallback->updateOrphanEffectChains(effect);
if (handle->enabled()) {
effect->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
}
}
}
-void AudioFlinger::ThreadBase::onEffectEnable(const sp<EffectModule>& effect) {
+void ThreadBase::onEffectEnable(const sp<IAfEffectModule>& effect) {
if (isOffloadOrMmap()) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
broadcast_l();
}
if (!effect->isOffloadable()) {
@@ -1678,64 +1762,64 @@
t->invalidateTracks(AUDIO_STREAM_MUSIC);
}
if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
- mAudioFlinger->onNonOffloadableGlobalEffectEnable();
+ mAfThreadCallback->onNonOffloadableGlobalEffectEnable();
}
}
}
-void AudioFlinger::ThreadBase::onEffectDisable() {
+void ThreadBase::onEffectDisable() {
if (isOffloadOrMmap()) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
broadcast_l();
}
}
-sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
- int effectId)
+sp<IAfEffectModule> ThreadBase::getEffect(audio_session_t sessionId,
+ int effectId) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return getEffect_l(sessionId, effectId);
}
-sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(audio_session_t sessionId,
- int effectId)
+sp<IAfEffectModule> ThreadBase::getEffect_l(audio_session_t sessionId,
+ int effectId) const
{
- sp<EffectChain> chain = getEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
}
-std::vector<int> AudioFlinger::ThreadBase::getEffectIds_l(audio_session_t sessionId)
+std::vector<int> ThreadBase::getEffectIds_l(audio_session_t sessionId) const
{
- sp<EffectChain> chain = getEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
}
-// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
-// PlaybackThread::mLock held
-status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
+// PlaybackThread::addEffect_ll() must be called with AudioFlinger::mutex() and
+// ThreadBase::mutex() held
+status_t ThreadBase::addEffect_ll(const sp<IAfEffectModule>& effect)
{
// check for existing effect chain with the requested audio session
audio_session_t sessionId = effect->sessionId();
- sp<EffectChain> chain = getEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
bool chainCreated = false;
ALOGD_IF((mType == OFFLOAD) && !effect->isOffloadable(),
- "addEffect_l() on offloaded thread %p: effect %s does not support offload flags %#x",
- this, effect->desc().name, effect->desc().flags);
+ "%s: on offloaded thread %p: effect %s does not support offload flags %#x",
+ __func__, this, effect->desc().name, effect->desc().flags);
if (chain == 0) {
// create a new chain for this session
- ALOGV("addEffect_l() new effect chain for session %d", sessionId);
- chain = new EffectChain(this, sessionId);
+ ALOGV("%s: new effect chain for session %d", __func__, sessionId);
+ chain = IAfEffectChain::create(this, sessionId);
addEffectChain_l(chain);
chain->setStrategy(getStrategyForSession_l(sessionId));
chainCreated = true;
}
- ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
+ ALOGV("%s: %p chain %p effect %p", __func__, this, chain.get(), effect.get());
if (chain->getEffectFromId_l(effect->id()) != 0) {
- ALOGW("addEffect_l() %p effect %s already present in chain %p",
- this, effect->desc().name, chain.get());
+ ALOGW("%s: %p effect %s already present in chain %p",
+ __func__, this, effect->desc().name, chain.get());
return BAD_VALUE;
}
@@ -1751,13 +1835,13 @@
effect->setDevices(outDeviceTypeAddrs());
effect->setInputDevice(inDeviceTypeAddr());
- effect->setMode(mAudioFlinger->getMode());
+ effect->setMode(mAfThreadCallback->getMode());
effect->setAudioSource(mAudioSource);
return NO_ERROR;
}
-void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect, bool release) {
+void ThreadBase::removeEffect_l(const sp<IAfEffectModule>& effect, bool release) {
ALOGV("%s %p effect %p", __FUNCTION__, this, effect.get());
effect_descriptor_t desc = effect->desc();
@@ -1765,7 +1849,7 @@
detachAuxEffect_l(effect->id());
}
- sp<EffectChain> chain = effect->getCallback()->chain().promote();
+ sp<IAfEffectChain> chain = effect->getCallback()->chain().promote();
if (chain != 0) {
// remove effect chain if removing last effect
if (chain->removeEffect_l(effect, release) == 0) {
@@ -1776,32 +1860,32 @@
}
}
-void AudioFlinger::ThreadBase::lockEffectChains_l(
- Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+void ThreadBase::lockEffectChains_l(
+ Vector<sp<IAfEffectChain>>& effectChains)
NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::lock()
{
effectChains = mEffectChains;
for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->lock();
+ mEffectChains[i]->mutex().lock();
}
}
-void AudioFlinger::ThreadBase::unlockEffectChains(
- const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+void ThreadBase::unlockEffectChains(
+ const Vector<sp<IAfEffectChain>>& effectChains)
NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::unlock()
{
for (size_t i = 0; i < effectChains.size(); i++) {
- effectChains[i]->unlock();
+ effectChains[i]->mutex().unlock();
}
}
-sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(audio_session_t sessionId)
+sp<IAfEffectChain> ThreadBase::getEffectChain(audio_session_t sessionId) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return getEffectChain_l(sessionId);
}
-sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(audio_session_t sessionId)
+sp<IAfEffectChain> ThreadBase::getEffectChain_l(audio_session_t sessionId)
const
{
size_t size = mEffectChains.size();
@@ -1813,16 +1897,16 @@
return 0;
}
-void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
+void ThreadBase::setMode(audio_mode_t mode)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffectChains.size();
for (size_t i = 0; i < size; i++) {
mEffectChains[i]->setMode_l(mode);
}
}
-void AudioFlinger::ThreadBase::toAudioPortConfig(struct audio_port_config *config)
+void ThreadBase::toAudioPortConfig(struct audio_port_config* config)
{
config->type = AUDIO_PORT_TYPE_MIX;
config->ext.mix.handle = mId;
@@ -1833,9 +1917,9 @@
AUDIO_PORT_CONFIG_FORMAT;
}
-void AudioFlinger::ThreadBase::systemReady()
+void ThreadBase::systemReady()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mSystemReady) {
return;
}
@@ -1848,7 +1932,7 @@
}
template <typename T>
-ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) {
+ssize_t ThreadBase::ActiveTracks<T>::add(const sp<T>& track) {
ssize_t index = mActiveTracks.indexOf(track);
if (index >= 0) {
ALOGW("ActiveTracks<T>::add track %p already there", track.get());
@@ -1863,7 +1947,7 @@
}
template <typename T>
-ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) {
+ssize_t ThreadBase::ActiveTracks<T>::remove(const sp<T>& track) {
ssize_t index = mActiveTracks.remove(track);
if (index < 0) {
ALOGW("ActiveTracks<T>::remove nonexistent track %p", track.get());
@@ -1882,7 +1966,7 @@
}
template <typename T>
-void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() {
+void ThreadBase::ActiveTracks<T>::clear() {
for (const sp<T> &track : mActiveTracks) {
BatteryNotifier::getInstance().noteStopAudio(track->uid());
logTrack("clear", track);
@@ -1895,7 +1979,7 @@
}
template <typename T>
-void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState(
+void ThreadBase::ActiveTracks<T>::updatePowerState(
const sp<ThreadBase>& thread, bool force) {
// Updates ActiveTracks client uids to the thread wakelock.
if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
@@ -1926,7 +2010,7 @@
}
template <typename T>
-bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
+bool ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
bool hasChanged = mHasChanged;
mHasChanged = false;
@@ -1939,7 +2023,7 @@
}
template <typename T>
-void AudioFlinger::ThreadBase::ActiveTracks<T>::logTrack(
+void ThreadBase::ActiveTracks<T>::logTrack(
const char *funcName, const sp<T> &track) const {
if (mLocalLog != nullptr) {
String8 result;
@@ -1948,19 +2032,19 @@
}
}
-void AudioFlinger::ThreadBase::broadcast_l()
+void ThreadBase::broadcast_l()
{
// Thread could be blocked waiting for async
// so signal it to handle state changes immediately
// If threadLoop is currently unlocked a signal of mWaitWorkCV will
// be lost so we also flag to prevent it blocking on mWaitWorkCV
mSignalPending = true;
- mWaitWorkCV.broadcast();
+ mWaitWorkCV.notify_all();
}
// 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 AudioFlinger::ThreadBase::sendStatistics(bool force)
+void ThreadBase::sendStatistics(bool force)
{
// Do not log if we have no stats.
// We choose the timestamp verifier because it is the most likely item to be present.
@@ -2023,24 +2107,24 @@
item->selfrecord();
}
-product_strategy_t AudioFlinger::ThreadBase::getStrategyForStream(audio_stream_type_t stream) const
+product_strategy_t ThreadBase::getStrategyForStream(audio_stream_type_t stream) const
{
- if (!mAudioFlinger->isAudioPolicyReady()) {
+ if (!mAfThreadCallback->isAudioPolicyReady()) {
return PRODUCT_STRATEGY_NONE;
}
return AudioSystem::getStrategyForStream(stream);
}
-// startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::ThreadBase::startMelComputation_l(
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
+void ThreadBase::startMelComputation_l(
const sp<audio_utils::MelProcessor>& /*processor*/)
{
// Do nothing
ALOGW("%s: ThreadBase does not support CSD", __func__);
}
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::ThreadBase::stopMelComputation_l()
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
+void ThreadBase::stopMelComputation_l()
{
// Do nothing
ALOGW("%s: ThreadBase does not support CSD", __func__);
@@ -2050,20 +2134,20 @@
// Playback
// ----------------------------------------------------------------------------
-AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
+PlaybackThread::PlaybackThread(const sp<IAfThreadCallback>& afThreadCallback,
AudioStreamOut* output,
audio_io_handle_t id,
type_t type,
bool systemReady,
audio_config_base_t *mixerConfig)
- : ThreadBase(audioFlinger, id, type, systemReady, true /* isOut */),
+ : ThreadBase(afThreadCallback, id, type, systemReady, true /* isOut */),
mNormalFrameCount(0), mSinkBuffer(NULL),
- mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision || type == SPATIALIZER),
+ mMixerBufferEnabled(kEnableExtendedPrecision || type == SPATIALIZER),
mMixerBuffer(NULL),
mMixerBufferSize(0),
mMixerBufferFormat(AUDIO_FORMAT_INVALID),
mMixerBufferValid(false),
- mEffectBufferEnabled(AudioFlinger::kEnableExtendedPrecision || type == SPATIALIZER),
+ mEffectBufferEnabled(kEnableExtendedPrecision || type == SPATIALIZER),
mEffectBuffer(NULL),
mEffectBufferSize(0),
mEffectBufferFormat(AUDIO_FORMAT_INVALID),
@@ -2078,13 +2162,13 @@
mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
mMixerStatus(MIXER_IDLE),
mMixerStatusIgnoringFastTracks(MIXER_IDLE),
- mStandbyDelayNs(AudioFlinger::mStandbyTimeInNsecs),
+ mStandbyDelayNs(getStandbyTimeInNanos()),
mBytesRemaining(0),
mCurrentWriteLength(0),
mUseAsyncWrite(false),
mWriteAckSequence(0),
mDrainSequence(0),
- mScreenState(AudioFlinger::mScreenState),
+ mScreenState(mAfThreadCallback->getScreenState()),
// index 0 is reserved for normal mixer's submix
mFastTrackAvailMask(((1 << FastMixerState::sMaxFastTracks) - 1) & ~1),
mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
@@ -2093,17 +2177,17 @@
mIsTimestampAdvancing(kMinimumTimeBetweenTimestampChecksNs)
{
snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
- mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
+ mNBLogWriter = afThreadCallback->newWriter_l(kLogSize, mThreadName);
- // Assumes constructor is called by AudioFlinger with it's mLock held, but
+ // Assumes constructor is called by AudioFlinger with its mutex() held, but
// it would be safer to explicitly pass initial masterVolume/masterMute as
// parameter.
//
// If the HAL we are using has support for master volume or master mute,
// then do not attenuate or mute during mixing (just leave the volume at 1.0
// and the mute set to false).
- mMasterVolume = audioFlinger->masterVolume_l();
- mMasterMute = audioFlinger->masterMute_l();
+ mMasterVolume = afThreadCallback->masterVolume_l();
+ mMasterMute = afThreadCallback->masterMute_l();
if (mOutput->audioHwDev) {
if (mOutput->audioHwDev->canSetMasterVolume()) {
mMasterVolume = 1.0;
@@ -2141,7 +2225,7 @@
for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
mStreamTypes[stream].volume = 0.0f;
- mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
+ mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
}
// Audio patch and call assistant volume are always max
mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
@@ -2150,9 +2234,9 @@
mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
}
-AudioFlinger::PlaybackThread::~PlaybackThread()
+PlaybackThread::~PlaybackThread()
{
- mAudioFlinger->unregisterWriter(mNBLogWriter);
+ mAfThreadCallback->unregisterWriter(mNBLogWriter);
free(mSinkBuffer);
free(mMixerBuffer);
free(mEffectBuffer);
@@ -2161,7 +2245,7 @@
// Thread virtuals
-void AudioFlinger::PlaybackThread::onFirstRef()
+void PlaybackThread::onFirstRef()
{
if (!isStreamInitialized()) {
ALOGE("The stream is not open yet"); // This should not happen.
@@ -2176,7 +2260,7 @@
if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING &&
mOutput->stream->setCallback(this) == OK) {
mUseAsyncWrite = true;
- mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
+ mCallbackThread = sp<AsyncCallbackThread>::make(this);
}
if (mOutput->stream->setEventCallback(this) != OK) {
@@ -2188,14 +2272,14 @@
}
// ThreadBase virtuals
-void AudioFlinger::PlaybackThread::preExit()
+void PlaybackThread::preExit()
{
ALOGV(" preExit()");
status_t result = mOutput->stream->exit();
ALOGE_IF(result != OK, "Error when calling exit(): %d", result);
}
-void AudioFlinger::PlaybackThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
+void PlaybackThread::dumpTracks_l(int fd, const Vector<String16>& /* args */)
{
String8 result;
@@ -2229,7 +2313,7 @@
result.append(prefix);
mTracks[0]->appendDumpHeader(result);
for (size_t i = 0; i < numtracks; ++i) {
- sp<Track> track = mTracks[i];
+ sp<IAfTrack> track = mTracks[i];
if (track != 0) {
bool active = mActiveTracks.indexOf(track) >= 0;
if (active) {
@@ -2249,7 +2333,7 @@
result.append(prefix);
mActiveTracks[0]->appendDumpHeader(result);
for (size_t i = 0; i < numactive; ++i) {
- sp<Track> track = mActiveTracks[i];
+ sp<IAfTrack> track = mActiveTracks[i];
if (mTracks.indexOf(track) < 0) {
result.append(prefix);
track->appendDump(result, true /* active */);
@@ -2260,7 +2344,7 @@
write(fd, result.c_str(), result.size());
}
-void AudioFlinger::PlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void PlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
dprintf(fd, " Master volume: %f\n", mMasterVolume);
dprintf(fd, " Master mute: %s\n", mMasterMute ? "on" : "off");
@@ -2295,9 +2379,9 @@
}
}
-// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
- const sp<AudioFlinger::Client>& client,
+// PlaybackThread::createTrack_l() must be called with AudioFlinger::mutex() held
+sp<IAfTrack> PlaybackThread::createTrack_l(
+ const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
@@ -2321,7 +2405,7 @@
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
- sp<Track> track;
+ sp<IAfTrack> track;
status_t lStatus;
audio_output_flags_t outputFlags = mOutput->flags;
audio_output_flags_t requestedFlags = *flags;
@@ -2350,7 +2434,7 @@
}
if (isBitPerfect) {
- sp<EffectChain> chain = getEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
if (chain.get() != nullptr) {
// Bit-perfect is required according to the configuration and preferred mixer
// attributes, but it is not in the output flag from the client's request. Explicitly
@@ -2399,15 +2483,15 @@
}
// check compatibility with audio effects.
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::lock_guard _l(mutex());
for (audio_session_t session : {
AUDIO_SESSION_DEVICE,
AUDIO_SESSION_OUTPUT_STAGE,
AUDIO_SESSION_OUTPUT_MIX,
sessionId,
}) {
- sp<EffectChain> chain = getEffectChain_l(session);
+ sp<IAfEffectChain> chain = getEffectChain_l(session);
if (chain.get() != nullptr) {
audio_output_flags_t old = *flags;
chain->checkOutputFlagCompatibility(flags);
@@ -2606,15 +2690,15 @@
goto Exit;
}
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::lock_guard _l(mutex());
// all tracks in same audio session must share the same routing strategy otherwise
// conflicts will happen when tracks are moved from one output to another by audio policy
// manager
product_strategy_t strategy = getStrategyForStream(streamType);
for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> t = mTracks[i];
+ sp<IAfTrack> t = mTracks[i];
if (t != 0 && t->isExternalTrack()) {
product_strategy_t actual = getStrategyForStream(t->streamType());
if (sessionId == t->sessionId() && strategy != actual) {
@@ -2636,11 +2720,11 @@
trackFlags = static_cast<audio_output_flags_t>(trackFlags | AUDIO_OUTPUT_FLAG_DIRECT);
}
- track = new Track(this, client, streamType, attr, sampleRate, format,
+ track = IAfTrack::create(this, client, streamType, attr, sampleRate, format,
channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
sessionId, creatorPid, attributionSource, trackFlags,
- TrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
+ IAfTrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
speed, isSpatialized, isBitPerfect);
lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
@@ -2651,13 +2735,13 @@
}
mTracks.add(track);
{
- Mutex::Autolock _atCbL(mAudioTrackCbLock);
+ audio_utils::lock_guard _atCbL(audioTrackCbMutex());
if (callback.get() != nullptr) {
mAudioTrackCallbacks.emplace(track, callback);
}
}
- sp<EffectChain> chain = getEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
if (chain != 0) {
ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
track->setMainBuffer(chain->inBuffer());
@@ -2681,7 +2765,7 @@
}
template<typename T>
-ssize_t AudioFlinger::PlaybackThread::Tracks<T>::remove(const sp<T> &track)
+ssize_t PlaybackThread::Tracks<T>::remove(const sp<T>& track)
{
const int trackId = track->id();
const ssize_t index = mTracks.remove(track);
@@ -2696,17 +2780,17 @@
return index;
}
-uint32_t AudioFlinger::PlaybackThread::correctLatency_l(uint32_t latency) const
+uint32_t PlaybackThread::correctLatency_l(uint32_t latency) const
{
return latency;
}
-uint32_t AudioFlinger::PlaybackThread::latency() const
+uint32_t PlaybackThread::latency() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return latency_l();
}
-uint32_t AudioFlinger::PlaybackThread::latency_l() const
+uint32_t PlaybackThread::latency_l() const
{
uint32_t latency;
if (initCheck() == NO_ERROR && mOutput->stream->getLatency(&latency) == OK) {
@@ -2715,9 +2799,9 @@
return 0;
}
-void AudioFlinger::PlaybackThread::setMasterVolume(float value)
+void PlaybackThread::setMasterVolume(float value)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Don't apply master volume in SW if our HAL can do it for us.
if (mOutput && mOutput->audioHwDev &&
mOutput->audioHwDev->canSetMasterVolume()) {
@@ -2727,17 +2811,17 @@
}
}
-void AudioFlinger::PlaybackThread::setMasterBalance(float balance)
+void PlaybackThread::setMasterBalance(float balance)
{
mMasterBalance.store(balance);
}
-void AudioFlinger::PlaybackThread::setMasterMute(bool muted)
+void PlaybackThread::setMasterMute(bool muted)
{
if (isDuplicating()) {
return;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Don't apply master mute in SW if our HAL can do it for us.
if (mOutput && mOutput->audioHwDev &&
mOutput->audioHwDev->canSetMasterMute()) {
@@ -2747,34 +2831,34 @@
}
}
-void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].volume = value;
broadcast_l();
}
-void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
+void PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].mute = muted;
broadcast_l();
}
-float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
+float PlaybackThread::streamVolume(audio_stream_type_t stream) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mStreamTypes[stream].volume;
}
-void AudioFlinger::PlaybackThread::setVolumeForOutput_l(float left, float right) const
+void PlaybackThread::setVolumeForOutput_l(float left, float right) const
{
mOutput->stream->setVolume(left, right);
}
-// addTrack_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
-NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
+// 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;
@@ -2783,16 +2867,16 @@
// buffers before playing. This is to ensure the client will
// effectively get the latency it requested.
if (track->isExternalTrack()) {
- TrackBase::track_state state = track->mState;
- mLock.unlock();
+ IAfTrackBase::track_state state = track->state();
+ mutex().unlock();
status = AudioSystem::startOutput(track->portId());
- mLock.lock();
+ mutex().lock();
// abort track was stopped/paused while we released the lock
- if (state != track->mState) {
+ if (state != track->state()) {
if (status == NO_ERROR) {
- mLock.unlock();
+ mutex().unlock();
AudioSystem::stopOutput(track->portId());
- mLock.lock();
+ mutex().lock();
}
return INVALID_OPERATION;
}
@@ -2814,34 +2898,34 @@
// set retry count for buffer fill
if (track->isOffloaded()) {
if (track->isStopping_1()) {
- track->mRetryCount = kMaxTrackStopRetriesOffload;
+ track->retryCount() = kMaxTrackStopRetriesOffload;
} else {
- track->mRetryCount = kMaxTrackStartupRetriesOffload;
+ track->retryCount() = kMaxTrackStartupRetriesOffload;
}
- track->mFillingUpStatus = mStandby ? Track::FS_FILLING : Track::FS_FILLED;
+ track->fillingStatus() = mStandby ? IAfTrack::FS_FILLING : IAfTrack::FS_FILLED;
} else {
- track->mRetryCount = kMaxTrackStartupRetries;
- track->mFillingUpStatus =
- track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
+ track->retryCount() = kMaxTrackStartupRetries;
+ track->fillingStatus() =
+ track->sharedBuffer() != 0 ? IAfTrack::FS_FILLED : IAfTrack::FS_FILLING;
}
- sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+ sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
if (mHapticChannelMask != AUDIO_CHANNEL_NONE
&& ((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
|| (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
// Unlock due to VibratorService will lock for this call and will
// call Tracks.mute/unmute which also require thread's lock.
- mLock.unlock();
- const os::HapticScale intensity = AudioFlinger::onExternalVibrationStart(
+ mutex().unlock();
+ const os::HapticScale intensity = afutils::onExternalVibrationStart(
track->getExternalVibration());
std::optional<media::AudioVibratorInfo> vibratorInfo;
{
// TODO(b/184194780): Use the vibrator information from the vibrator that will be
// used to play this track.
- Mutex::Autolock _l(mAudioFlinger->mLock);
- vibratorInfo = std::move(mAudioFlinger->getDefaultVibratorInfo_l());
+ audio_utils::lock_guard _l(mAfThreadCallback->mutex());
+ vibratorInfo = std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
}
- mLock.lock();
+ mutex().lock();
track->setHapticIntensity(intensity);
if (vibratorInfo) {
track->setHapticMaxAmplitude(vibratorInfo->maxAmplitude);
@@ -2862,7 +2946,7 @@
}
}
- track->mResetDone = false;
+ track->setResetDone(false);
track->resetPresentationComplete();
mActiveTracks.add(track);
if (chain != 0) {
@@ -2879,25 +2963,25 @@
return status;
}
-bool AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
+bool PlaybackThread::destroyTrack_l(const sp<IAfTrack>& track)
{
track->terminate();
// active tracks are removed by threadLoop()
bool trackActive = (mActiveTracks.indexOf(track) >= 0);
- track->mState = TrackBase::STOPPED;
+ track->setState(IAfTrackBase::STOPPED);
if (!trackActive) {
removeTrack_l(track);
} else if (track->isFastTrack() || track->isOffloaded() || track->isDirect()) {
if (track->isPausePending()) {
track->pauseAck();
}
- track->mState = TrackBase::STOPPING_1;
+ track->setState(IAfTrackBase::STOPPING_1);
}
return trackActive;
}
-void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
+void PlaybackThread::removeTrack_l(const sp<IAfTrack>& track)
{
track->triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
@@ -2907,26 +2991,26 @@
mTracks.remove(track);
{
- Mutex::Autolock _atCbL(mAudioTrackCbLock);
+ audio_utils::lock_guard _atCbL(audioTrackCbMutex());
mAudioTrackCallbacks.erase(track);
}
if (track->isFastTrack()) {
- int index = track->mFastIndex;
+ int index = track->fastIndex();
ALOG_ASSERT(0 < index && index < (int)FastMixerState::sMaxFastTracks);
ALOG_ASSERT(!(mFastTrackAvailMask & (1 << index)));
mFastTrackAvailMask |= 1 << index;
// redundant as track is about to be destroyed, for dumpsys only
- track->mFastIndex = -1;
+ track->fastIndex() = -1;
}
- sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+ sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
chain->decTrackCnt();
}
}
-String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
+String8 PlaybackThread::getParameters(const String8& keys)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
String8 out_s8;
if (initCheck() == NO_ERROR && mOutput->stream->getParameters(keys, &out_s8) == OK) {
return out_s8;
@@ -2934,15 +3018,15 @@
return {};
}
-status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
- Mutex::Autolock _l(mLock);
+status_t DirectOutputThread::selectPresentation(int presentationId, int programId) {
+ audio_utils::lock_guard _l(mutex());
if (!isStreamInitialized()) {
return NO_INIT;
}
return mOutput->stream->selectPresentation(presentationId, programId);
}
-void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void PlaybackThread::ioConfigChanged(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;
@@ -2964,30 +3048,30 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAudioFlinger->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged(event, desc, pid);
}
-void AudioFlinger::PlaybackThread::onWriteReady()
+void PlaybackThread::onWriteReady()
{
mCallbackThread->resetWriteBlocked();
}
-void AudioFlinger::PlaybackThread::onDrainReady()
+void PlaybackThread::onDrainReady()
{
mCallbackThread->resetDraining();
}
-void AudioFlinger::PlaybackThread::onError()
+void PlaybackThread::onError()
{
mCallbackThread->setAsyncError();
}
-void AudioFlinger::PlaybackThread::onCodecFormatChanged(
+void PlaybackThread::onCodecFormatChanged(
const std::basic_string<uint8_t>& metadataBs)
{
- wp<AudioFlinger::PlaybackThread> weakPointerThis = this;
+ const auto weakPointerThis = wp<PlaybackThread>::fromExisting(this);
std::thread([this, metadataBs, weakPointerThis]() {
- sp<AudioFlinger::PlaybackThread> playbackThread = weakPointerThis.promote();
+ const sp<PlaybackThread> playbackThread = weakPointerThis.promote();
if (playbackThread == nullptr) {
ALOGW("PlaybackThread was destroyed, skip codec format change event");
return;
@@ -3005,26 +3089,26 @@
audio_utils::metadata::ByteString metaDataStr =
audio_utils::metadata::byteStringFromData(metadata);
std::vector metadataVec(metaDataStr.begin(), metaDataStr.end());
- Mutex::Autolock _l(mAudioTrackCbLock);
+ audio_utils::lock_guard _l(audioTrackCbMutex());
for (const auto& callbackPair : mAudioTrackCallbacks) {
callbackPair.second->onCodecFormatChanged(metadataVec);
}
}).detach();
}
-void AudioFlinger::PlaybackThread::resetWriteBlocked(uint32_t sequence)
+void PlaybackThread::resetWriteBlocked(uint32_t sequence)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// reject out of sequence requests
if ((mWriteAckSequence & 1) && (sequence == mWriteAckSequence)) {
mWriteAckSequence &= ~1;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
}
-void AudioFlinger::PlaybackThread::resetDraining(uint32_t sequence)
+void PlaybackThread::resetDraining(uint32_t sequence)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// reject out of sequence requests
if ((mDrainSequence & 1) && (sequence == mDrainSequence)) {
// Register discontinuity when HW drain is completed because that can cause
@@ -3033,11 +3117,13 @@
// elsewhere, e.g. in flush).
mTimestampVerifier.discontinuity(mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
mDrainSequence &= ~1;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
}
-void AudioFlinger::PlaybackThread::readOutputParameters_l()
+void PlaybackThread::readOutputParameters_l()
+NO_THREAD_SAFETY_ANALYSIS
+// 'moveEffectChain_ll' requires holding mutex 'AudioFlinger_Mutex' exclusively
{
// unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
const audio_config_base_t audioConfig = mOutput->getAudioProperties();
@@ -3202,20 +3288,21 @@
// force reconfiguration of effect chains and engines to take new buffer size and audio
// parameters into account
- // Note that mLock is not held when readOutputParameters_l() is called from the constructor
+ // Note that mutex() is not held when readOutputParameters_l() is called from the constructor
// but in this case nothing is done below as no audio sessions have effect yet so it doesn't
// matter.
- // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
- Vector< sp<EffectChain> > effectChains = mEffectChains;
+ // create a copy of mEffectChains as calling moveEffectChain_ll()
+ // can reorder some effect chains
+ Vector<sp<IAfEffectChain>> effectChains = mEffectChains;
for (size_t i = 0; i < effectChains.size(); i ++) {
- mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(),
+ mAfThreadCallback->moveEffectChain_ll(effectChains[i]->sessionId(),
this/* srcThread */, this/* dstThread */);
}
audio_output_flags_t flags = mOutput->flags;
mediametrics::LogItem item(mThreadMetrics.getMetricsId()); // TODO: method in ThreadMetrics?
item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS)
- .set(AMEDIAMETRICS_PROP_ENCODING, formatToString(mFormat).c_str())
+ .set(AMEDIAMETRICS_PROP_ENCODING, IAfThreadBase::formatToString(mFormat).c_str())
.set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
.set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
.set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)mChannelCount)
@@ -3226,7 +3313,7 @@
.set(AMEDIAMETRICS_PROP_PREFIX_HAPTIC AMEDIAMETRICS_PROP_CHANNELCOUNT,
(int32_t)mHapticChannelCount)
.set(AMEDIAMETRICS_PROP_PREFIX_HAL AMEDIAMETRICS_PROP_ENCODING,
- formatToString(mHALFormat).c_str())
+ IAfThreadBase::formatToString(mHALFormat).c_str())
.set(AMEDIAMETRICS_PROP_PREFIX_HAL AMEDIAMETRICS_PROP_FRAMECOUNT,
(int32_t)mFrameCount) // sic - added HAL
;
@@ -3237,14 +3324,14 @@
item.record();
}
-AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::PlaybackThread::updateMetadata_l()
+ThreadBase::MetadataUpdate PlaybackThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
return {}; // nothing to do
}
StreamOutHalInterface::SourceMetadata metadata;
auto backInserter = std::back_inserter(metadata.tracks);
- for (const sp<Track> &track : mActiveTracks) {
+ for (const sp<IAfTrack>& track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
track->copyMetadataTo(backInserter);
}
@@ -3254,18 +3341,19 @@
return change;
}
-void AudioFlinger::PlaybackThread::sendMetadataToBackend_l(
+void PlaybackThread::sendMetadataToBackend_l(
const StreamOutHalInterface::SourceMetadata& metadata)
{
mOutput->stream->updateSourceMetadata(metadata);
};
-status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
+status_t PlaybackThread::getRenderPosition(
+ uint32_t* halFrames, uint32_t* dspFrames) const
{
if (halFrames == NULL || dspFrames == NULL) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (initCheck() != NO_ERROR) {
return INVALID_OPERATION;
}
@@ -3287,7 +3375,7 @@
}
}
-product_strategy_t AudioFlinger::PlaybackThread::getStrategyForSession_l(audio_session_t sessionId)
+product_strategy_t PlaybackThread::getStrategyForSession_l(audio_session_t sessionId) const
{
// session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
// it is moved to correct output by audio policy manager when A2DP is connected or disconnected
@@ -3295,7 +3383,7 @@
return getStrategyForStream(AUDIO_STREAM_MUSIC);
}
for (size_t i = 0; i < mTracks.size(); i++) {
- sp<Track> track = mTracks[i];
+ sp<IAfTrack> track = mTracks[i];
if (sessionId == track->sessionId() && !track->isInvalid()) {
return getStrategyForStream(track->streamType());
}
@@ -3304,15 +3392,15 @@
}
-AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
+AudioStreamOut* PlaybackThread::getOutput() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mOutput;
}
-AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
+AudioStreamOut* PlaybackThread::clearOutput()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioStreamOut *output = mOutput;
mOutput = NULL;
// FIXME FastMixer might also have a raw ptr to mOutputSink;
@@ -3323,8 +3411,8 @@
return output;
}
-// this method must always be called either with ThreadBase mLock held or inside the thread loop
-sp<StreamHalInterface> AudioFlinger::PlaybackThread::stream() const
+// this method must always be called either with ThreadBase mutex() held or inside the thread loop
+sp<StreamHalInterface> PlaybackThread::stream() const
{
if (mOutput == NULL) {
return NULL;
@@ -3332,21 +3420,21 @@
return mOutput->stream;
}
-uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
+uint32_t PlaybackThread::activeSleepTimeUs() const
{
return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
}
-status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<audioflinger::SyncEvent>& event)
+status_t PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
{
if (!isValidSyncEvent(event)) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
+ sp<IAfTrack> track = mTracks[i];
if (event->triggerSession() == track->sessionId()) {
(void) track->setSyncEvent(event);
return NO_ERROR;
@@ -3356,14 +3444,13 @@
return NAME_NOT_FOUND;
}
-bool AudioFlinger::PlaybackThread::isValidSyncEvent(
- const sp<audioflinger::SyncEvent>& event) const
+bool PlaybackThread::isValidSyncEvent(const sp<SyncEvent>& event) const
{
return event->type() == AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
}
-void AudioFlinger::PlaybackThread::threadLoop_removeTracks(
- [[maybe_unused]] const Vector< sp<Track> >& tracksToRemove)
+void PlaybackThread::threadLoop_removeTracks(
+ [[maybe_unused]] const Vector<sp<IAfTrack>>& tracksToRemove)
{
// Miscellaneous track cleanup when removed from the active list,
// called without Thread lock but synchronized with threadLoop processing.
@@ -3377,7 +3464,7 @@
#endif
}
-void AudioFlinger::PlaybackThread::checkSilentMode_l()
+void PlaybackThread::checkSilentMode_l()
{
if (!mMasterMute) {
char value[PROPERTY_VALUE_MAX];
@@ -3403,7 +3490,7 @@
}
// shared by MIXER and DIRECT, overridden by DUPLICATING
-ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
+ssize_t PlaybackThread::threadLoop_write()
{
LOG_HIST_TS();
mInWrite = true;
@@ -3417,7 +3504,7 @@
ATRACE_BEGIN("write");
// update the setpoint when AudioFlinger::mScreenState changes
- uint32_t screenState = AudioFlinger::mScreenState;
+ const uint32_t screenState = mAfThreadCallback->getScreenState();
if (screenState != mScreenState) {
mScreenState = screenState;
MonoPipe *pipe = (MonoPipe *)mPipeSink.get();
@@ -3474,8 +3561,8 @@
return bytesWritten;
}
-// startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::startMelComputation_l(
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
+void PlaybackThread::startMelComputation_l(
const sp<audio_utils::MelProcessor>& processor)
{
auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
@@ -3484,8 +3571,8 @@
}
}
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::stopMelComputation_l()
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
+void PlaybackThread::stopMelComputation_l()
{
auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
if (outputSink != nullptr) {
@@ -3493,7 +3580,7 @@
}
}
-void AudioFlinger::PlaybackThread::threadLoop_drain()
+void PlaybackThread::threadLoop_drain()
{
bool supportsDrain = false;
if (mOutput->stream->supportsDrain(&supportsDrain) == OK && supportsDrain) {
@@ -3509,12 +3596,12 @@
}
}
-void AudioFlinger::PlaybackThread::threadLoop_exit()
+void PlaybackThread::threadLoop_exit()
{
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
- sp<Track> track = mTracks[i];
+ sp<IAfTrack> track = mTracks[i];
track->invalidate();
}
// Clear ActiveTracks to update BatteryNotifier in case active tracks remain.
@@ -3545,13 +3632,13 @@
- idle sleep time
*/
-void AudioFlinger::PlaybackThread::cacheParameters_l()
+void PlaybackThread::cacheParameters_l()
{
mSinkBufferSize = mNormalFrameCount * mFrameSize;
mActiveSleepTimeUs = activeSleepTimeUs();
mIdleSleepTimeUs = idleSleepTimeUs();
- mStandbyDelayNs = AudioFlinger::mStandbyTimeInNsecs;
+ mStandbyDelayNs = getStandbyTimeInNanos();
// make sure standby delay is not too short when connected to an A2DP sink to avoid
// truncating audio when going to standby.
@@ -3562,14 +3649,14 @@
}
}
-bool AudioFlinger::PlaybackThread::invalidateTracks_l(audio_stream_type_t streamType)
+bool PlaybackThread::invalidateTracks_l(audio_stream_type_t streamType)
{
ALOGV("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %zu",
this, streamType, mTracks.size());
bool trackMatch = false;
size_t size = mTracks.size();
for (size_t i = 0; i < size; i++) {
- sp<Track> t = mTracks[i];
+ sp<IAfTrack> t = mTracks[i];
if (t->streamType() == streamType && t->isExternalTrack()) {
t->invalidate();
trackMatch = true;
@@ -3578,22 +3665,22 @@
return trackMatch;
}
-void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
invalidateTracks_l(streamType);
}
-void AudioFlinger::PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
- Mutex::Autolock _l(mLock);
+void PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
+ audio_utils::lock_guard _l(mutex());
invalidateTracks_l(portIds);
}
-bool AudioFlinger::PlaybackThread::invalidateTracks_l(std::set<audio_port_handle_t>& portIds) {
+bool PlaybackThread::invalidateTracks_l(std::set<audio_port_handle_t>& portIds) {
bool trackMatch = false;
const size_t size = mTracks.size();
for (size_t i = 0; i < size; i++) {
- sp<Track> t = mTracks[i];
+ sp<IAfTrack> t = mTracks[i];
if (t->isExternalTrack() && portIds.find(t->portId()) != portIds.end()) {
t->invalidate();
portIds.erase(t->portId());
@@ -3607,7 +3694,7 @@
}
// getTrackById_l must be called with holding thread lock
-AudioFlinger::PlaybackThread::Track* AudioFlinger::PlaybackThread::getTrackById_l(
+IAfTrack* PlaybackThread::getTrackById_l(
audio_port_handle_t trackPortId) {
for (size_t i = 0; i < mTracks.size(); i++) {
if (mTracks[i]->portId() == trackPortId) {
@@ -3617,7 +3704,7 @@
return nullptr;
}
-status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
+status_t PlaybackThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
{
audio_session_t session = chain->sessionId();
sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
@@ -3638,12 +3725,12 @@
}
size_t numSamples = mNormalFrameCount
* (audio_channel_count_from_out_mask(channelMask) + mHapticChannelCount);
- status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+ status_t result = mAfThreadCallback->getEffectsFactoryHal()->allocateBuffer(
numSamples * sizeof(float),
&halInBuffer);
if (result != OK) return result;
- result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+ result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
isSessionSpatialized ? mEffectBuffer : mPostSpatializerBuffer,
isSessionSpatialized ? mEffectBufferSize : mPostSpatializerBufferSize,
&halOutBuffer);
@@ -3658,10 +3745,10 @@
// - OUTPUT_STAGE session uses the mEffectBuffer as input buffer and
// mPostSpatializerBuffer as output buffer
// - DEVICE session uses the mPostSpatializerBuffer as input and output buffer.
- status_t result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+ status_t result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
mEffectBuffer, mEffectBufferSize, &halInBuffer);
if (result != OK) return result;
- result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+ result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
mPostSpatializerBuffer, mPostSpatializerBufferSize, &halOutBuffer);
if (result != OK) return result;
@@ -3670,7 +3757,7 @@
}
}
} else {
- status_t result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+ status_t result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
mEffectBufferEnabled ? mEffectBuffer : mSinkBuffer,
mEffectBufferEnabled ? mEffectBufferSize : mSinkBufferSize,
&halInBuffer);
@@ -3686,7 +3773,8 @@
size_t numSamples = mNormalFrameCount
* (audio_channel_count_from_out_mask(mMixerChannelMask)
+ mHapticChannelCount);
- const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+ const status_t allocateStatus =
+ mAfThreadCallback->getEffectsFactoryHal()->allocateBuffer(
numSamples * sizeof(float),
&halInBuffer);
if (allocateStatus != OK) return allocateStatus;
@@ -3701,7 +3789,7 @@
if (!audio_is_global_session(session)) {
// Attach all tracks with same session ID to this chain.
for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
+ sp<IAfTrack> track = mTracks[i];
if (session == track->sessionId()) {
ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p",
track.get(), buffer);
@@ -3711,7 +3799,7 @@
}
// indicate all active tracks in the chain
- for (const sp<Track> &track : mActiveTracks) {
+ for (const sp<IAfTrack>& track : mActiveTracks) {
if (session == track->sessionId()) {
ALOGV("addEffectChain_l() activating track %p on session %d",
track.get(), session);
@@ -3753,7 +3841,7 @@
return NO_ERROR;
}
-size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t PlaybackThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
{
audio_session_t session = chain->sessionId();
@@ -3763,7 +3851,7 @@
if (chain == mEffectChains[i]) {
mEffectChains.removeAt(i);
// detach all active tracks from the chain
- for (const sp<Track> &track : mActiveTracks) {
+ for (const sp<IAfTrack>& track : mActiveTracks) {
if (session == track->sessionId()) {
ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
chain.get(), session);
@@ -3773,7 +3861,7 @@
// detach all tracks with same session ID from this chain
for (size_t j = 0; j < mTracks.size(); ++j) {
- sp<Track> track = mTracks[j];
+ sp<IAfTrack> track = mTracks[j];
if (session == track->sessionId()) {
track->setMainBuffer(reinterpret_cast<float*>(mSinkBuffer));
chain->decTrackCnt();
@@ -3785,15 +3873,15 @@
return mEffectChains.size();
}
-status_t AudioFlinger::PlaybackThread::attachAuxEffect(
- const sp<AudioFlinger::PlaybackThread::Track>& track, int EffectId)
+status_t PlaybackThread::attachAuxEffect(
+ const sp<IAfTrack>& track, int EffectId)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return attachAuxEffect_l(track, EffectId);
}
-status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
- const sp<AudioFlinger::PlaybackThread::Track>& track, int EffectId)
+status_t PlaybackThread::attachAuxEffect_l(
+ const sp<IAfTrack>& track, int EffectId)
{
status_t status = NO_ERROR;
@@ -3801,7 +3889,7 @@
track->setAuxBuffer(0, NULL);
} else {
// Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
- sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
+ sp<IAfEffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
if (effect != 0) {
if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
@@ -3815,22 +3903,34 @@
return status;
}
-void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
+void PlaybackThread::detachAuxEffect_l(int effectId)
{
for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
+ sp<IAfTrack> track = mTracks[i];
if (track->auxEffectId() == effectId) {
attachAuxEffect_l(track, 0);
}
}
}
-bool AudioFlinger::PlaybackThread::threadLoop()
+bool PlaybackThread::threadLoop()
NO_THREAD_SAFETY_ANALYSIS // manual locking of AudioFlinger
{
aflog::setThreadWriter(mNBLogWriter.get());
- Vector< sp<Track> > tracksToRemove;
+ if (mType == SPATIALIZER) {
+ const pid_t tid = getTid();
+ if (tid == -1) { // odd: we are here, we must be a running thread.
+ ALOGW("%s: Cannot update Spatializer mixer thread priority, no tid", __func__);
+ } else {
+ const int priorityBoost = requestSpatializerPriority(getpid(), tid);
+ if (priorityBoost > 0) {
+ stream()->setHalThreadPriority(priorityBoost);
+ }
+ }
+ }
+
+ Vector<sp<IAfTrack>> tracksToRemove;
mStandbyTimeNs = systemTime();
int64_t lastLoopCountWritten = -2; // never matches "previous" loop, when loopCount = 0.
@@ -3878,27 +3978,28 @@
{
// Log merge requests are performed during AudioFlinger binder transactions, but
// that does not cover audio playback. It's requested here for that reason.
- mAudioFlinger->requestLogMerge();
+ mAfThreadCallback->requestLogMerge();
cpuStats.sample(myName);
- Vector< sp<EffectChain> > effectChains;
+ Vector<sp<IAfEffectChain>> effectChains;
audio_session_t activeHapticSessionId = AUDIO_SESSION_NONE;
bool isHapticSessionSpatialized = false;
- std::vector<sp<Track>> activeTracks;
+ std::vector<sp<IAfTrack>> activeTracks;
// If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
//
- // Note: we access outDeviceTypes() outside of mLock.
+ // Note: we access outDeviceTypes() outside of mutex().
if (isMsdDevice() && outDeviceTypes().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 (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
- std::vector<PatchPanel::SoftwarePatch> swPatches;
+ if (mAfThreadCallback->mutex().try_lock()) {
+ std::vector<SoftwarePatch> swPatches;
double latencyMs = 0.; // not required; initialized for clang-tidy
status_t status = INVALID_OPERATION;
audio_patch_handle_t downstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
- if (mAudioFlinger->mPatchPanel.getDownstreamSoftwarePatches(id(), &swPatches) == OK
+ if (mAfThreadCallback->getPatchPanel()->getDownstreamSoftwarePatches(
+ id(), &swPatches) == OK
&& swPatches.size() > 0) {
status = swPatches[0].getLatencyMs_l(&latencyMs);
downstreamPatchHandle = swPatches[0].getPatchHandle();
@@ -3919,7 +4020,7 @@
}
mDownstreamLatencyStatMs.add(latencyMs);
}
- mAudioFlinger->mLock.unlock();
+ mAfThreadCallback->mutex().unlock();
}
} else {
if (lastDownstreamPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
@@ -3934,16 +4035,16 @@
}
MetadataUpdate metadataUpdate;
- { // scope for mLock
+ { // scope for mutex()
- Mutex::Autolock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
processConfigEvents_l();
if (mCheckOutputStageEffects.load()) {
continue;
}
- // See comment at declaration of logString for why this is done under mLock
+ // See comment at declaration of logString for why this is done under mutex()
if (logString != NULL) {
mNBLogWriter->logTimestamp();
mNBLogWriter->log(logString);
@@ -3968,8 +4069,9 @@
const int64_t waitNs = computeWaitTimeNs_l();
ALOGV("wait async completion (wait time: %lld)", (long long)waitNs);
- status_t status = mWaitWorkCV.waitRelative(mLock, waitNs);
- if (status == TIMED_OUT) {
+ std::cv_status cvstatus =
+ mWaitWorkCV.wait_for(_l, std::chrono::nanoseconds(waitNs));
+ if (cvstatus == std::cv_status::timeout) {
mSignalPending = true; // if timeout recheck everything
}
ALOGV("async completion/wake");
@@ -4011,7 +4113,7 @@
releaseWakeLock_l();
// wait until we have something to do...
ALOGV("%s going to sleep", myName.c_str());
- mWaitWorkCV.wait(mLock);
+ mWaitWorkCV.wait(_l);
ALOGV("%s waking up", myName.c_str());
acquireWakeLock_l();
@@ -4048,7 +4150,7 @@
// TODO: Write haptic data directly to sink buffer when mixing.
if (mHapticChannelCount > 0) {
for (const auto& track : mActiveTracks) {
- sp<EffectChain> effectChain = getEffectChain_l(track->sessionId());
+ sp<IAfEffectChain> effectChain = getEffectChain_l(track->sessionId());
if (effectChain != nullptr
&& effectChain->containsHapticGeneratingEffect_l()) {
activeHapticSessionId = track->sessionId();
@@ -4084,9 +4186,9 @@
&& (mKernelPositionOnStandby
!= mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL])))) {
mHalStarted = true;
- mWaitHalStartCV.broadcast();
+ mWaitHalStartCV.notify_all();
}
- } // mLock scope ends
+ } // mutex() scope ends
if (mBytesRemaining == 0) {
mCurrentWriteLength = 0;
@@ -4103,14 +4205,15 @@
// Tally underrun frames as we are inserting 0s here.
for (const auto& track : activeTracks) {
- if (track->mFillingUpStatus == Track::FS_ACTIVE
+ if (track->fillingStatus() == IAfTrack::FS_ACTIVE
&& !track->isStopped()
&& !track->isPaused()
&& !track->isTerminated()) {
ALOGV("%s: track(%d) %s underrun due to thread sleep of %zu frames",
__func__, track->id(), track->getTrackStateAsString(),
mNormalFrameCount);
- track->mAudioTrackServerProxy->tallyUnderrunFrames(mNormalFrameCount);
+ track->audioTrackServerProxy()->tallyUnderrunFrames(
+ mNormalFrameCount);
}
}
}
@@ -4279,7 +4382,7 @@
unlockEffectChains(effectChains);
if (!metadataUpdate.playbackMetadataUpdate.empty()) {
- mAudioFlinger->mMelReporter->updateMetadataForCsd(id(),
+ mAfThreadCallback->getMelReporter()->updateMetadataForCsd(id(),
metadataUpdate.playbackMetadataUpdate);
}
@@ -4316,7 +4419,7 @@
const double processMs =
(lastIoBeginNs - mLastIoEndNs) * 1e-6;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mIoJitterMs.add(jitterMs);
mProcessTimeMs.add(processMs);
@@ -4417,7 +4520,7 @@
} else {
ATRACE_BEGIN("sleep");
- Mutex::Autolock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
// suspended requires accurate metering of sleep time.
if (isSuspended()) {
// advance by expected sleepTime
@@ -4442,7 +4545,7 @@
mSleepTimeUs = deltaNs / 1000;
}
if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) {
- mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs));
+ mWaitWorkCV.wait_for(_l, std::chrono::microseconds(mSleepTimeUs));
}
ATRACE_END();
}
@@ -4480,7 +4583,7 @@
return false;
}
-void AudioFlinger::PlaybackThread::collectTimestamps_l()
+void PlaybackThread::collectTimestamps_l()
{
if (mStandby) {
mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
@@ -4585,10 +4688,10 @@
? systemTime() : mLastIoBeginNs;
}
- for (const sp<Track> &t : mActiveTracks) {
+ for (const sp<IAfTrack>& t : mActiveTracks) {
if (!t->isFastTrack()) {
t->updateTrackFrameInfo(
- t->mAudioTrackServerProxy->framesReleased(),
+ t->audioTrackServerProxy()->framesReleased(),
mFramesWritten,
mSampleRate,
mTimestamp);
@@ -4615,14 +4718,14 @@
#endif
}
-// removeTracks_l() must be called with ThreadBase::mLock held
-void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
-NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
+// removeTracks_l() must be called with ThreadBase::mutex() held
+void PlaybackThread::removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove)
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mutex()
{
for (const auto& track : tracksToRemove) {
mActiveTracks.remove(track);
ALOGV("%s(%d): removing track on session %d", __func__, track->id(), track->sessionId());
- sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+ sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
ALOGV("%s(%d): stopping track on chain %p for session Id: %d",
__func__, track->id(), chain.get(), track->sessionId());
@@ -4643,11 +4746,11 @@
if (mHapticChannelCount > 0 &&
((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
|| (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
- mLock.unlock();
+ mutex().unlock();
// Unlock due to VibratorService will lock for this call and will
// call Tracks.mute/unmute which also require thread's lock.
- AudioFlinger::onExternalVibrationStop(track->getExternalVibration());
- mLock.lock();
+ afutils::onExternalVibrationStop(track->getExternalVibration());
+ mutex().lock();
// When the track is stop, set the haptic intensity as MUTE
// for the HapticGenerator effect.
@@ -4658,7 +4761,7 @@
}
}
-status_t AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
+status_t PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
{
if (mNormalSink != 0) {
ExtendedTimestamp ets;
@@ -4687,7 +4790,7 @@
// All tracks attached to a mixer with flag VOIP_RX are tied to the same
// stream type STREAM_VOICE_CALL so this will only change the HAL volume once even
// if more than one track are active
-status_t AudioFlinger::PlaybackThread::handleVoipVolume_l(float *volume)
+status_t PlaybackThread::handleVoipVolume_l(float* volume)
{
status_t result = NO_ERROR;
if ((mOutput->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) != 0) {
@@ -4709,7 +4812,7 @@
return result;
}
-status_t AudioFlinger::MixerThread::createAudioPatch_l(const struct audio_patch *patch,
+status_t MixerThread::createAudioPatch_l(const struct audio_patch* patch,
audio_patch_handle_t *handle)
{
status_t status;
@@ -4726,7 +4829,7 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_patch *patch,
+status_t PlaybackThread::createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle)
{
status_t status = NO_ERROR;
@@ -4810,7 +4913,7 @@
return status;
}
-status_t AudioFlinger::MixerThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
+status_t MixerThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
{
status_t status;
if (property_get_bool("af.patch_park", false /* default_value */)) {
@@ -4824,7 +4927,7 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
+status_t PlaybackThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
{
status_t status = NO_ERROR;
@@ -4843,19 +4946,19 @@
return status;
}
-void AudioFlinger::PlaybackThread::addPatchTrack(const sp<PatchTrack>& track)
+void PlaybackThread::addPatchTrack(const sp<IAfPatchTrack>& track)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mTracks.add(track);
}
-void AudioFlinger::PlaybackThread::deletePatchTrack(const sp<PatchTrack>& track)
+void PlaybackThread::deletePatchTrack(const sp<IAfPatchTrack>& track)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
destroyTrack_l(track);
}
-void AudioFlinger::PlaybackThread::toAudioPortConfig(struct audio_port_config *config)
+void PlaybackThread::toAudioPortConfig(struct audio_port_config* config)
{
ThreadBase::toAudioPortConfig(config);
config->role = AUDIO_PORT_ROLE_SOURCE;
@@ -4869,9 +4972,16 @@
// ----------------------------------------------------------------------------
-AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createMixerThread(
+ const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+ audio_io_handle_t id, bool systemReady, type_t type, audio_config_base_t* mixerConfig) {
+ return sp<MixerThread>::make(afThreadCallback, output, id, systemReady, type, mixerConfig);
+}
+
+MixerThread::MixerThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
audio_io_handle_t id, bool systemReady, type_t type, audio_config_base_t *mixerConfig)
- : PlaybackThread(audioFlinger, output, id, type, systemReady, mixerConfig),
+ : PlaybackThread(afThreadCallback, output, id, type, systemReady, mixerConfig),
// mAudioMixer below
// mFastMixer below
mBluetoothLatencyModesEnabled(false),
@@ -4881,7 +4991,7 @@
// mPipeSink below
// mNormalSink below
{
- setMasterBalance(audioFlinger->getMasterBalance_l());
+ setMasterBalance(afThreadCallback->getMasterBalance_l());
ALOGV("MixerThread() id=%d type=%d", id, type);
ALOGV("mSampleRate=%u, mChannelMask=%#x, mChannelCount=%u, mFormat=%#x, mFrameSize=%zu, "
"mFrameCount=%zu, mNormalFrameCount=%zu",
@@ -5008,7 +5118,7 @@
state->mColdFutexAddr = &mFastMixerFutex;
state->mColdGen++;
state->mDumpState = &mFastMixerDumpState;
- mFastMixerNBLogWriter = audioFlinger->newWriter_l(kFastMixerLogSize, "FastMixer");
+ mFastMixerNBLogWriter = afThreadCallback->newWriter_l(kFastMixerLogSize, "FastMixer");
state->mNBLogWriter = mFastMixerNBLogWriter.get();
sq->end();
sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
@@ -5054,7 +5164,7 @@
}
}
-AudioFlinger::MixerThread::~MixerThread()
+MixerThread::~MixerThread()
{
if (mFastMixer != 0) {
FastMixerStateQueue *sq = mFastMixer->sq();
@@ -5087,14 +5197,14 @@
}
#endif
}
- mAudioFlinger->unregisterWriter(mFastMixerNBLogWriter);
+ mAfThreadCallback->unregisterWriter(mFastMixerNBLogWriter);
delete mAudioMixer;
}
-void AudioFlinger::MixerThread::onFirstRef() {
+void MixerThread::onFirstRef() {
PlaybackThread::onFirstRef();
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mOutput != nullptr && mOutput->stream != nullptr) {
status_t status = mOutput->stream->setLatencyModeCallback(this);
if (status != INVALID_OPERATION) {
@@ -5107,7 +5217,7 @@
}
}
-uint32_t AudioFlinger::MixerThread::correctLatency_l(uint32_t latency) const
+uint32_t MixerThread::correctLatency_l(uint32_t latency) const
{
if (mFastMixer != 0) {
MonoPipe *pipe = (MonoPipe *)mPipeSink.get();
@@ -5116,7 +5226,7 @@
return latency;
}
-ssize_t AudioFlinger::MixerThread::threadLoop_write()
+ssize_t MixerThread::threadLoop_write()
{
// FIXME we should only do one push per cycle; confirm this is true
// Start the fast mixer if it's not already running
@@ -5144,7 +5254,7 @@
}
state->mCommand = FastMixerState::MIX_WRITE;
#ifdef FAST_THREAD_STATISTICS
- mFastMixerDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
+ mFastMixerDumpState.increaseSamplingN(mAfThreadCallback->isLowRamDevice() ?
FastThreadDumpState::kSamplingNforLowRamDevice : FastThreadDumpState::kSamplingN);
#endif
sq->end();
@@ -5159,7 +5269,7 @@
return PlaybackThread::threadLoop_write();
}
-void AudioFlinger::MixerThread::threadLoop_standby()
+void MixerThread::threadLoop_standby()
{
// Idle the fast mixer if it's currently running
if (mFastMixer != 0) {
@@ -5197,24 +5307,24 @@
PlaybackThread::threadLoop_standby();
}
-bool AudioFlinger::PlaybackThread::waitingAsyncCallback_l()
+bool PlaybackThread::waitingAsyncCallback_l()
{
return false;
}
-bool AudioFlinger::PlaybackThread::shouldStandby_l()
+bool PlaybackThread::shouldStandby_l()
{
return !mStandby;
}
-bool AudioFlinger::PlaybackThread::waitingAsyncCallback()
+bool PlaybackThread::waitingAsyncCallback()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return waitingAsyncCallback_l();
}
// shared by MIXER and DIRECT, overridden by DUPLICATING
-void AudioFlinger::PlaybackThread::threadLoop_standby()
+void PlaybackThread::threadLoop_standby()
{
ALOGV("Audio hardware entering standby, mixer %p, suspend count %d", this, mSuspended);
mOutput->standby();
@@ -5230,20 +5340,20 @@
setHalLatencyMode_l();
}
-void AudioFlinger::PlaybackThread::onAddNewTrack_l()
+void PlaybackThread::onAddNewTrack_l()
{
ALOGV("signal playback thread");
broadcast_l();
}
-void AudioFlinger::PlaybackThread::onAsyncError()
+void PlaybackThread::onAsyncError()
{
for (int i = AUDIO_STREAM_SYSTEM; i < (int)AUDIO_STREAM_CNT; i++) {
invalidateTracks((audio_stream_type_t)i);
}
}
-void AudioFlinger::MixerThread::threadLoop_mix()
+void MixerThread::threadLoop_mix()
{
// mix buffers...
mAudioMixer->process();
@@ -5261,7 +5371,7 @@
}
-void AudioFlinger::MixerThread::threadLoop_sleepTime()
+void MixerThread::threadLoop_sleepTime()
{
// If no tracks are ready, sleep once for the duration of an output
// buffer size, then write 0s to the output
@@ -5314,9 +5424,9 @@
// TODO add standby time extension fct of effect tail
}
-// prepareTracks_l() must be called with ThreadBase::mLock held
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
- Vector< sp<Track> > *tracksToRemove)
+// prepareTracks_l() must be called with ThreadBase::mutex() held
+PlaybackThread::mixer_state MixerThread::prepareTracks_l(
+ Vector<sp<IAfTrack>>* tracksToRemove)
{
// clean up deleted track ids in AudioMixer before allocating new tracks
(void)mTracks.processDeletedTrackIds([this](int trackId) {
@@ -5343,7 +5453,7 @@
masterVolume = 0;
}
// Delegate master volume control to effect in output mix effect chain if needed
- sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+ sp<IAfEffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
if (chain != 0) {
uint32_t v = (uint32_t)(masterVolume * (1 << 24));
chain->setVolume_l(&v, &v);
@@ -5392,23 +5502,23 @@
// tallyUnderrunFrames() is called to update the track counters
// with the number of underrun frames for a particular mixer period.
// We defer tallying until we know the final mixer status.
- void tallyUnderrunFrames(const sp<Track>& track, size_t underrunFrames) {
+ void tallyUnderrunFrames(const sp<IAfTrack>& track, size_t underrunFrames) {
mUnderrunFrames.emplace_back(track, underrunFrames);
}
private:
const mixer_state * const mMixerStatus;
ThreadMetrics * const mThreadMetrics;
- std::vector<std::pair<sp<Track>, size_t>> mUnderrunFrames;
+ std::vector<std::pair<sp<IAfTrack>, size_t>> mUnderrunFrames;
} deferredOperations(&mixerStatus, &mThreadMetrics);
// implicit nested scope for variable capture
bool noFastHapticTrack = true;
for (size_t i=0 ; i<count ; i++) {
- const sp<Track> t = mActiveTracks[i];
+ const sp<IAfTrack> t = mActiveTracks[i];
// this const just means the local variable doesn't change
- Track* const track = t.get();
+ IAfTrack* const track = t.get();
// process fast tracks
if (track->isFastTrack()) {
@@ -5426,7 +5536,7 @@
// The converse, of removing an (active) track and then creating a new track
// at the identical fast mixer slot within the same normal mix cycle,
// is impossible because the slot isn't marked available until the end of each cycle.
- int j = track->mFastIndex;
+ int j = track->fastIndex();
ALOG_ASSERT(0 < j && j < (int)FastMixerState::sMaxFastTracks);
ALOG_ASSERT(!(mFastTrackAvailMask & (1 << j)));
FastTrack *fastTrack = &state->mFastTracks[j];
@@ -5436,13 +5546,13 @@
FastTrackDump *ftDump = &mFastMixerDumpState.mTracks[j];
FastTrackUnderruns underruns = ftDump->mUnderruns;
uint32_t recentFull = (underruns.mBitFields.mFull -
- track->mObservedUnderruns.mBitFields.mFull) & UNDERRUN_MASK;
+ track->fastTrackUnderruns().mBitFields.mFull) & UNDERRUN_MASK;
uint32_t recentPartial = (underruns.mBitFields.mPartial -
- track->mObservedUnderruns.mBitFields.mPartial) & UNDERRUN_MASK;
+ track->fastTrackUnderruns().mBitFields.mPartial) & UNDERRUN_MASK;
uint32_t recentEmpty = (underruns.mBitFields.mEmpty -
- track->mObservedUnderruns.mBitFields.mEmpty) & UNDERRUN_MASK;
+ track->fastTrackUnderruns().mBitFields.mEmpty) & UNDERRUN_MASK;
uint32_t recentUnderruns = recentPartial + recentEmpty;
- track->mObservedUnderruns = underruns;
+ track->fastTrackUnderruns() = underruns;
// don't count underruns that occur while stopping or pausing
// or stopped which can occur when flush() is called while active
size_t underrunFrames = 0;
@@ -5452,30 +5562,30 @@
underrunFrames = recentUnderruns * mFrameCount;
}
// Immediately account for FastTrack underruns.
- track->mAudioTrackServerProxy->tallyUnderrunFrames(underrunFrames);
+ track->audioTrackServerProxy()->tallyUnderrunFrames(underrunFrames);
// This is similar to the state machine for normal tracks,
// with a few modifications for fast tracks.
bool isActive = true;
- switch (track->mState) {
- case TrackBase::STOPPING_1:
+ switch (track->state()) {
+ case IAfTrackBase::STOPPING_1:
// track stays active in STOPPING_1 state until first underrun
if (recentUnderruns > 0 || track->isTerminated()) {
- track->mState = TrackBase::STOPPING_2;
+ track->setState(IAfTrackBase::STOPPING_2);
}
break;
- case TrackBase::PAUSING:
+ case IAfTrackBase::PAUSING:
// ramp down is not yet implemented
track->setPaused();
break;
- case TrackBase::RESUMING:
+ case IAfTrackBase::RESUMING:
// ramp up is not yet implemented
- track->mState = TrackBase::ACTIVE;
+ track->setState(IAfTrackBase::ACTIVE);
break;
- case TrackBase::ACTIVE:
+ case IAfTrackBase::ACTIVE:
if (recentFull > 0 || recentPartial > 0) {
// track has provided at least some frames recently: reset retry count
- track->mRetryCount = kMaxTrackRetries;
+ track->retryCount() = kMaxTrackRetries;
}
if (recentUnderruns == 0) {
// no recent underruns: stay active
@@ -5489,7 +5599,7 @@
break;
}
// there has recently been an "empty" underrun: decrement the retry counter
- if (--(track->mRetryCount) > 0) {
+ if (--(track->retryCount()) > 0) {
break;
}
// indicate to client process that the track was disabled because of underrun;
@@ -5500,10 +5610,10 @@
break;
}
FALLTHROUGH_INTENDED;
- case TrackBase::STOPPING_2:
- case TrackBase::PAUSED:
- case TrackBase::STOPPED:
- case TrackBase::FLUSHED: // flush() while active
+ case IAfTrackBase::STOPPING_2:
+ case IAfTrackBase::PAUSED:
+ case IAfTrackBase::STOPPED:
+ case IAfTrackBase::FLUSHED: // flush() while active
// Check for presentation complete if track is inactive
// We have consumed all the buffers of this track.
// This would be incomplete if we auto-paused on underrun
@@ -5520,7 +5630,7 @@
}
}
if (track->isStopping_2()) {
- track->mState = TrackBase::STOPPED;
+ track->setState(IAfTrackBase::STOPPED);
}
if (track->isStopped()) {
// Can't reset directly, as fast mixer is still polling this track
@@ -5530,20 +5640,20 @@
}
isActive = false;
break;
- case TrackBase::IDLE:
+ case IAfTrackBase::IDLE:
default:
- LOG_ALWAYS_FATAL("unexpected track state %d", (int)track->mState);
+ LOG_ALWAYS_FATAL("unexpected track state %d", (int)track->state());
}
if (isActive) {
// was it previously inactive?
if (!(state->mTrackMask & (1 << j))) {
- ExtendedAudioBufferProvider *eabp = track;
- VolumeProvider *vp = track;
+ ExtendedAudioBufferProvider *eabp = track->asExtendedAudioBufferProvider();
+ VolumeProvider *vp = track->asVolumeProvider();
fastTrack->mBufferProvider = eabp;
fastTrack->mVolumeProvider = vp;
- fastTrack->mChannelMask = track->mChannelMask;
- fastTrack->mFormat = track->mFormat;
+ fastTrack->mChannelMask = track->channelMask();
+ fastTrack->mFormat = track->format();
fastTrack->mHapticPlaybackEnabled = track->getHapticPlaybackEnabled();
fastTrack->mHapticIntensity = track->getHapticIntensity();
fastTrack->mHapticMaxAmplitude = track->getHapticMaxAmplitude();
@@ -5552,7 +5662,7 @@
didModify = true;
// no acknowledgement required for newly active tracks
}
- sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+ sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
float volume;
if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
volume = 0.f;
@@ -5567,12 +5677,12 @@
const float vh = track->getVolumeHandler()->getVolume(
proxy->framesReleased()).first;
volume *= vh;
- track->mCachedVolume = volume;
+ track->setCachedVolume(volume);
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
- track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{masterVolume == 0.f,
mStreamTypes[track->streamType()].volume == 0.f,
mStreamTypes[track->streamType()].mute,
@@ -5603,13 +5713,13 @@
// TODO Remove the ALOGW when this theory is confirmed.
ALOGW("fast track %d should have been active; "
"mState=%d, mTrackMask=%#x, recentUnderruns=%u, isShared=%d",
- j, (int)track->mState, state->mTrackMask, recentUnderruns,
+ j, (int)track->state(), state->mTrackMask, recentUnderruns,
track->sharedBuffer() != 0);
// Since the FastMixer state already has the track inactive, do nothing here.
}
tracksToRemove->add(track);
// Avoids a misleading display in dumpsys
- track->mObservedUnderruns.mBitFields.mMostRecent = UNDERRUN_FULL;
+ track->fastTrackUnderruns().mBitFields.mMostRecent = UNDERRUN_FULL;
}
if (fastTrack->mHapticPlaybackEnabled != track->getHapticPlaybackEnabled()) {
fastTrack->mHapticPlaybackEnabled = track->getHapticPlaybackEnabled();
@@ -5631,14 +5741,14 @@
if (!mAudioMixer->exists(trackId)) {
status_t status = mAudioMixer->create(
trackId,
- track->mChannelMask,
- track->mFormat,
- track->mSessionId);
+ track->channelMask(),
+ track->format(),
+ track->sessionId());
if (status != OK) {
ALOGW("%s(): AudioMixer cannot create track(%d)"
" mask %#x, format %#x, sessionId %d",
__func__, trackId,
- track->mChannelMask, track->mFormat, track->mSessionId);
+ track->channelMask(), track->format(), track->sessionId());
tracksToRemove->add(track);
track->invalidate(); // consider it dead.
continue;
@@ -5651,8 +5761,8 @@
// hence the test on (mMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
// during last round
size_t desiredFrames;
- const uint32_t sampleRate = track->mAudioTrackServerProxy->getSampleRate();
- const AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
+ const uint32_t sampleRate = track->audioTrackServerProxy()->getSampleRate();
+ const AudioPlaybackRate playbackRate = track->audioTrackServerProxy()->getPlaybackRate();
desiredFrames = sourceFramesNeededWithTimestretch(
sampleRate, mNormalFrameCount, mSampleRate, playbackRate.mSpeed);
@@ -5702,11 +5812,11 @@
int param = AudioMixer::VOLUME;
- if (track->mFillingUpStatus == Track::FS_FILLED) {
+ if (track->fillingStatus() == IAfTrack::FS_FILLED) {
// no ramp for the first volume setting
- track->mFillingUpStatus = Track::FS_ACTIVE;
- if (track->mState == TrackBase::RESUMING) {
- track->mState = TrackBase::ACTIVE;
+ track->fillingStatus() = IAfTrack::FS_ACTIVE;
+ if (track->state() == IAfTrackBase::RESUMING) {
+ track->setState(IAfTrackBase::ACTIVE);
// If a new track is paused immediately after start, do not ramp on resume.
if (cblk->mServer != 0) {
param = AudioMixer::RAMP_VOLUME;
@@ -5727,9 +5837,9 @@
// read original volumes with volume control
float v = masterVolume * mStreamTypes[track->streamType()].volume;
// Always fetch volumeshaper volume to ensure state is updated.
- const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+ const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
const float vh = track->getVolumeHandler()->getVolume(
- track->mAudioTrackServerProxy->framesReleased()).first;
+ track->audioTrackServerProxy()->framesReleased()).first;
if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
v = 0;
@@ -5755,7 +5865,7 @@
vrf = GAIN_FLOAT_UNITY;
}
- track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{masterVolume == 0.f,
mStreamTypes[track->streamType()].volume == 0.f,
mStreamTypes[track->streamType()].mute,
@@ -5791,18 +5901,18 @@
// Update remaining floating point volume levels
vlf = (float)vl / (1 << 24);
vrf = (float)vr / (1 << 24);
- track->mHasVolumeController = true;
+ track->setHasVolumeController(true);
} else {
// force no volume ramp when volume controller was just disabled or removed
// from effect chain to avoid volume spike
- if (track->mHasVolumeController) {
+ if (track->hasVolumeController()) {
param = AudioMixer::VOLUME;
}
- track->mHasVolumeController = false;
+ track->setHasVolumeController(false);
}
// XXX: these things DON'T need to be done each time
- mAudioMixer->setBufferProvider(trackId, track);
+ mAudioMixer->setBufferProvider(trackId, track->asExtendedAudioBufferProvider());
mAudioMixer->enable(trackId);
mAudioMixer->setParameter(trackId, param, AudioMixer::VOLUME0, &vlf);
@@ -5910,13 +6020,14 @@
trackId,
AudioMixer::TRACK,
AudioMixer::HAPTIC_INTENSITY, (void *)(uintptr_t)track->getHapticIntensity());
+ const float hapticMaxAmplitude = track->getHapticMaxAmplitude();
mAudioMixer->setParameter(
trackId,
AudioMixer::TRACK,
- AudioMixer::HAPTIC_MAX_AMPLITUDE, (void *)(&(track->mHapticMaxAmplitude)));
+ AudioMixer::HAPTIC_MAX_AMPLITUDE, (void *)&hapticMaxAmplitude);
// reset retry count
- track->mRetryCount = kMaxTrackRetries;
+ track->retryCount() = kMaxTrackRetries;
// If one track is ready, set the mixer ready if:
// - the mixer was not ready during previous round OR
@@ -5968,7 +6079,7 @@
} else {
// No buffers for this track. Give it a few chances to
// fill a buffer, then remove it from active list.
- if (--(track->mRetryCount) <= 0) {
+ if (--(track->retryCount()) <= 0) {
ALOGI("BUFFER TIMEOUT: remove(%d) from active list on thread %p",
trackId, this);
tracksToRemove->add(track);
@@ -6044,7 +6155,7 @@
size_t i = __builtin_ctz(resetMask);
ALOG_ASSERT(i < count);
resetMask &= ~(1 << i);
- sp<Track> track = mActiveTracks[i];
+ sp<IAfTrack> track = mActiveTracks[i];
ALOG_ASSERT(track->isFastTrack() && track->isStopped());
track->reset();
}
@@ -6109,8 +6220,8 @@
return mixerStatus;
}
-// trackCountForUid_l() must be called with ThreadBase::mLock held
-uint32_t AudioFlinger::PlaybackThread::trackCountForUid_l(uid_t uid) const
+// trackCountForUid_l() must be called with ThreadBase::mutex() held
+uint32_t PlaybackThread::trackCountForUid_l(uid_t uid) const
{
uint32_t trackCount = 0;
for (size_t i = 0; i < mTracks.size() ; i++) {
@@ -6121,7 +6232,7 @@
return trackCount;
}
-bool AudioFlinger::PlaybackThread::IsTimestampAdvancing::check(AudioStreamOut * output)
+bool PlaybackThread::IsTimestampAdvancing::check(AudioStreamOut* output)
{
// Check the timestamp to see if it's advancing once every 150ms. If we check too frequently, we
// could falsely detect that the frame position has stalled due to underrun because we haven't
@@ -6145,15 +6256,15 @@
return mLatchedValue;
}
-void AudioFlinger::PlaybackThread::IsTimestampAdvancing::clear()
+void PlaybackThread::IsTimestampAdvancing::clear()
{
mLatchedValue = true;
mPreviousPosition = 0;
mPreviousNs = 0;
}
-// isTrackAllowed_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::isTrackAllowed_l(
+// isTrackAllowed_l() must be called with ThreadBase::mutex() held
+bool MixerThread::isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
audio_session_t sessionId, uid_t uid) const
{
@@ -6172,8 +6283,8 @@
return true;
}
-// checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePair,
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
+bool MixerThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
bool reconfig = false;
@@ -6187,7 +6298,7 @@
reconfig = true;
}
if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
- if (!isValidPcmSinkFormat((audio_format_t) value)) {
+ if (!isValidPcmSinkFormat(static_cast<audio_format_t>(value))) {
status = BAD_VALUE;
} else {
// no need to save value, since it's constant
@@ -6195,7 +6306,7 @@
}
}
if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
- if (!isValidPcmSinkChannelMask((audio_channel_mask_t) value)) {
+ if (!isValidPcmSinkChannelMask(static_cast<audio_channel_mask_t>(value))) {
status = BAD_VALUE;
} else {
// no need to save value, since it's constant
@@ -6236,14 +6347,14 @@
const int trackId = track->id();
const status_t createStatus = mAudioMixer->create(
trackId,
- track->mChannelMask,
- track->mFormat,
- track->mSessionId);
+ track->channelMask(),
+ track->format(),
+ track->sessionId());
ALOGW_IF(createStatus != NO_ERROR,
"%s(): AudioMixer cannot create track(%d)"
" mask %#x, format %#x, sessionId %d",
__func__,
- trackId, track->mChannelMask, track->mFormat, track->mSessionId);
+ trackId, track->channelMask(), track->format(), track->sessionId());
}
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
@@ -6253,7 +6364,7 @@
}
-void AudioFlinger::MixerThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void MixerThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
PlaybackThread::dumpInternals_l(fd, args);
dprintf(fd, " Thread throttle time (msecs): %u\n", mThreadThrottleTimeMs);
@@ -6300,17 +6411,17 @@
dprintf(fd, "Supported latency modes: %s\n", toString(mSupportedLatencyModes).c_str());
}
-uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() const
+uint32_t MixerThread::idleSleepTimeUs() const
{
return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000) / 2;
}
-uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() const
+uint32_t MixerThread::suspendSleepTimeUs() const
{
return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000);
}
-void AudioFlinger::MixerThread::cacheParameters_l()
+void MixerThread::cacheParameters_l()
{
PlaybackThread::cacheParameters_l();
@@ -6321,11 +6432,11 @@
maxPeriod = seconds(mNormalFrameCount) / mSampleRate * 15;
}
-void AudioFlinger::MixerThread::onHalLatencyModesChanged_l() {
- mAudioFlinger->onSupportedLatencyModesChanged(mId, mSupportedLatencyModes);
+void MixerThread::onHalLatencyModesChanged_l() {
+ mAfThreadCallback->onSupportedLatencyModesChanged(mId, mSupportedLatencyModes);
}
-void AudioFlinger::MixerThread::setHalLatencyMode_l() {
+void MixerThread::setHalLatencyMode_l() {
// Only handle latency mode if:
// - mBluetoothLatencyModesEnabled is true
// - the HAL supports latency modes
@@ -6367,7 +6478,7 @@
}
}
-void AudioFlinger::MixerThread::updateHalSupportedLatencyModes_l() {
+void MixerThread::updateHalSupportedLatencyModes_l() {
if (mOutput == nullptr || mOutput->stream == nullptr) {
return;
@@ -6385,19 +6496,19 @@
}
}
-status_t AudioFlinger::MixerThread::getSupportedLatencyModes(
+status_t MixerThread::getSupportedLatencyModes(
std::vector<audio_latency_mode_t>* modes) {
if (modes == nullptr) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
*modes = mSupportedLatencyModes;
return NO_ERROR;
}
-void AudioFlinger::MixerThread::onRecommendedLatencyModeChanged(
+void MixerThread::onRecommendedLatencyModeChanged(
std::vector<audio_latency_mode_t> modes) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (modes != mSupportedLatencyModes) {
ALOGD("%s: thread(%d) supported latency modes: %s",
__func__, mId, toString(modes).c_str());
@@ -6406,7 +6517,7 @@
}
}
-status_t AudioFlinger::MixerThread::setBluetoothVariableLatencyEnabled(bool enabled) {
+status_t MixerThread::setBluetoothVariableLatencyEnabled(bool enabled) {
if (mOutput == nullptr || mOutput->audioHwDev == nullptr
|| !mOutput->audioHwDev->supportsBluetoothVariableLatency()) {
return INVALID_OPERATION;
@@ -6417,29 +6528,38 @@
// ----------------------------------------------------------------------------
-AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createDirectOutputThread(
+ const sp<IAfThreadCallback>& afThreadCallback,
+ AudioStreamOut* output, audio_io_handle_t id, bool systemReady,
+ const audio_offload_info_t& offloadInfo) {
+ return sp<DirectOutputThread>::make(
+ afThreadCallback, output, id, systemReady, offloadInfo);
+}
+
+DirectOutputThread::DirectOutputThread(const sp<IAfThreadCallback>& afThreadCallback,
AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
const audio_offload_info_t& offloadInfo)
- : PlaybackThread(audioFlinger, output, id, type, systemReady)
+ : PlaybackThread(afThreadCallback, output, id, type, systemReady)
, mOffloadInfo(offloadInfo)
{
- setMasterBalance(audioFlinger->getMasterBalance_l());
+ setMasterBalance(afThreadCallback->getMasterBalance_l());
}
-AudioFlinger::DirectOutputThread::~DirectOutputThread()
+DirectOutputThread::~DirectOutputThread()
{
}
-void AudioFlinger::DirectOutputThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void DirectOutputThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
PlaybackThread::dumpInternals_l(fd, args);
dprintf(fd, " Master balance: %f Left: %f Right: %f\n",
mMasterBalance.load(), mMasterBalanceLeft, mMasterBalanceRight);
}
-void AudioFlinger::DirectOutputThread::setMasterBalance(float balance)
+void DirectOutputThread::setMasterBalance(float balance)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mMasterBalance != balance) {
mMasterBalance.store(balance);
mBalance.computeStereoBalance(balance, &mMasterBalanceLeft, &mMasterBalanceRight);
@@ -6447,12 +6567,12 @@
}
}
-void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTrack)
+void DirectOutputThread::processVolume_l(IAfTrack* track, bool lastTrack)
{
float left, right;
// Ensure volumeshaper state always advances even when muted.
- const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+ const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
const int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
const int64_t time = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
@@ -6486,14 +6606,14 @@
}
left *= v;
right *= v;
- if (mAudioFlinger->getMode() != AUDIO_MODE_IN_COMMUNICATION
+ if (mAfThreadCallback->getMode() != AUDIO_MODE_IN_COMMUNICATION
|| audio_channel_count_from_out_mask(mChannelMask) > 1) {
left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
right *= mMasterBalanceRight;
}
}
- track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{mMasterMute,
mStreamTypes[track->streamType()].volume == 0.f,
mStreamTypes[track->streamType()].mute,
@@ -6525,10 +6645,10 @@
}
}
-void AudioFlinger::DirectOutputThread::onAddNewTrack_l()
+void DirectOutputThread::onAddNewTrack_l()
{
- sp<Track> previousTrack = mPreviousTrack.promote();
- sp<Track> latestTrack = mActiveTracks.getLatest();
+ sp<IAfTrack> previousTrack = mPreviousTrack.promote();
+ sp<IAfTrack> latestTrack = mActiveTracks.getLatest();
if (previousTrack != 0 && latestTrack != 0) {
if (mType == DIRECT) {
@@ -6550,8 +6670,8 @@
PlaybackThread::onAddNewTrack_l();
}
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
- Vector< sp<Track> > *tracksToRemove
+PlaybackThread::mixer_state DirectOutputThread::prepareTracks_l(
+ Vector<sp<IAfTrack>>* tracksToRemove
)
{
size_t count = mActiveTracks.size();
@@ -6560,14 +6680,14 @@
bool doHwResume = false;
// find out which tracks need to be processed
- for (const sp<Track> &t : mActiveTracks) {
+ for (const sp<IAfTrack>& t : mActiveTracks) {
if (t->isInvalid()) {
ALOGW("An invalidated track shouldn't be in active list");
tracksToRemove->add(t);
continue;
}
- Track* const track = t.get();
+ IAfTrack* const track = t.get();
#ifdef VERY_VERY_VERBOSE_LOGGING
audio_track_cblk_t* cblk = track->cblk();
#endif
@@ -6575,7 +6695,7 @@
// In theory an older track could underrun and restart after the new one starts
// but as we only care about the transition phase between two tracks on a
// direct output, it is not a problem to ignore the underrun case.
- sp<Track> l = mActiveTracks.getLatest();
+ sp<IAfTrack> l = mActiveTracks.getLatest();
bool last = l.get() == track;
if (track->isPausePending()) {
@@ -6611,8 +6731,8 @@
// for all its buffers to be filled before processing it.
// Allow draining the buffer in case the client
// app does not call stop() and relies on underrun to stop:
- // hence the test on (track->mRetryCount > 1).
- // If track->mRetryCount <= 1 then track is about to be disabled, paused, removed,
+ // hence the test on (track->retryCount() > 1).
+ // If track->retryCount() <= 1 then track is about to be disabled, paused, removed,
// so we accept any nonzero amount of data delivered by the AudioTrack (which will
// reset the retry counter).
// Do not use a high threshold for compressed audio.
@@ -6624,7 +6744,7 @@
const int32_t retryThreshold = targetRetryCount > 2 ? targetRetryCount - 1 : 1;
uint32_t minFrames;
if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing()
- && (track->mRetryCount > retryThreshold) && audio_has_proportional_frames(mFormat)) {
+ && (track->retryCount() > retryThreshold) && audio_has_proportional_frames(mFormat)) {
minFrames = mNormalFrameCount;
} else {
minFrames = 1;
@@ -6642,8 +6762,8 @@
{
ALOGVV("track(%d) s=%08x [OK]", trackId, cblk->mServer);
- if (track->mFillingUpStatus == Track::FS_FILLED) {
- track->mFillingUpStatus = Track::FS_ACTIVE;
+ if (track->fillingStatus() == IAfTrack::FS_FILLED) {
+ track->fillingStatus() = IAfTrack::FS_ACTIVE;
if (last) {
// make sure processVolume_l() will apply new volume even if 0
mLeftVolFloat = mRightVolFloat = -1.0;
@@ -6656,7 +6776,7 @@
// compute volume for this track
processVolume_l(track, last);
if (last) {
- sp<Track> previousTrack = mPreviousTrack.promote();
+ sp<IAfTrack> previousTrack = mPreviousTrack.promote();
if (previousTrack != 0) {
if (track != previousTrack.get()) {
// Flush any data still being written from last track
@@ -6668,7 +6788,7 @@
mPreviousTrack = track;
// reset retry count
- track->mRetryCount = targetRetryCount;
+ track->retryCount() = targetRetryCount;
mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
if (mHwPaused) {
@@ -6683,7 +6803,7 @@
mEffectChains[0]->clearInputBuffer();
}
if (track->isStopping_1()) {
- track->mState = TrackBase::STOPPING_2;
+ track->setState(IAfTrackBase::STOPPING_2);
if (last && mHwPaused) {
doHwResume = true;
mHwPaused = false;
@@ -6701,7 +6821,7 @@
mOutput->presentationComplete();
}
if (track->isStopping_2()) {
- track->mState = TrackBase::STOPPED;
+ track->setState(IAfTrackBase::STOPPED);
}
if (track->isStopped()) {
track->reset();
@@ -6714,9 +6834,9 @@
// Only consider last track started for mixer state control
bool isTimestampAdvancing = mIsTimestampAdvancing.check(mOutput);
if (!isTunerStream() // tuner streams remain active in underrun
- && --(track->mRetryCount) <= 0) {
+ && --(track->retryCount()) <= 0) {
if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
- track->mRetryCount = kMaxTrackRetriesOffload;
+ track->retryCount() = kMaxTrackRetriesOffload;
} else {
ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", trackId);
tracksToRemove->add(track);
@@ -6773,7 +6893,7 @@
return mixerStatus;
}
-void AudioFlinger::DirectOutputThread::threadLoop_mix()
+void DirectOutputThread::threadLoop_mix()
{
size_t frameCount = mFrameCount;
int8_t *curBuf = (int8_t *)mSinkBuffer;
@@ -6800,7 +6920,7 @@
mActiveTrack.clear();
}
-void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
+void DirectOutputThread::threadLoop_sleepTime()
{
// do not write to HAL when paused
if (mHwPaused || (usesHwAvSync() && mStandby)) {
@@ -6816,10 +6936,10 @@
// linear or proportional PCM direct tracks in underrun.
}
-void AudioFlinger::DirectOutputThread::threadLoop_exit()
+void DirectOutputThread::threadLoop_exit()
{
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
if (mTracks[i]->isFlushPending()) {
mTracks[i]->flushAck();
@@ -6834,7 +6954,7 @@
}
// must be called with thread mutex locked
-bool AudioFlinger::DirectOutputThread::shouldStandby_l()
+bool DirectOutputThread::shouldStandby_l()
{
bool trackPaused = false;
bool trackStopped = false;
@@ -6844,14 +6964,14 @@
if (mTracks.size() > 0) {
trackPaused = mTracks[mTracks.size() - 1]->isPaused();
trackStopped = mTracks[mTracks.size() - 1]->isStopped() ||
- mTracks[mTracks.size() - 1]->mState == TrackBase::IDLE;
+ mTracks[mTracks.size() - 1]->state() == IAfTrackBase::IDLE;
}
return !mStandby && !(trackPaused || (mHwPaused && !trackStopped));
}
-// checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair,
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
+bool DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
bool reconfig = false;
@@ -6893,7 +7013,7 @@
return reconfig;
}
-uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
+uint32_t DirectOutputThread::activeSleepTimeUs() const
{
uint32_t time;
if (audio_has_proportional_frames(mFormat)) {
@@ -6904,7 +7024,7 @@
return time;
}
-uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() const
+uint32_t DirectOutputThread::idleSleepTimeUs() const
{
uint32_t time;
if (audio_has_proportional_frames(mFormat)) {
@@ -6915,7 +7035,7 @@
return time;
}
-uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() const
+uint32_t DirectOutputThread::suspendSleepTimeUs() const
{
uint32_t time;
if (audio_has_proportional_frames(mFormat)) {
@@ -6926,7 +7046,7 @@
return time;
}
-void AudioFlinger::DirectOutputThread::cacheParameters_l()
+void DirectOutputThread::cacheParameters_l()
{
PlaybackThread::cacheParameters_l();
@@ -6942,7 +7062,7 @@
}
}
-void AudioFlinger::DirectOutputThread::flushHw_l()
+void DirectOutputThread::flushHw_l()
{
PlaybackThread::flushHw_l();
mOutput->flush();
@@ -6953,7 +7073,7 @@
mMonotonicFrameCounter.onFlush();
}
-int64_t AudioFlinger::DirectOutputThread::computeWaitTimeNs_l() const {
+int64_t DirectOutputThread::computeWaitTimeNs_l() const {
// If a VolumeShaper is active, we must wake up periodically to update volume.
const int64_t NS_PER_MS = 1000000;
return mVolumeShaperActive ?
@@ -6962,8 +7082,8 @@
// ----------------------------------------------------------------------------
-AudioFlinger::AsyncCallbackThread::AsyncCallbackThread(
- const wp<AudioFlinger::PlaybackThread>& playbackThread)
+AsyncCallbackThread::AsyncCallbackThread(
+ const wp<PlaybackThread>& playbackThread)
: Thread(false /*canCallJava*/),
mPlaybackThread(playbackThread),
mWriteAckSequence(0),
@@ -6972,16 +7092,12 @@
{
}
-AudioFlinger::AsyncCallbackThread::~AsyncCallbackThread()
-{
-}
-
-void AudioFlinger::AsyncCallbackThread::onFirstRef()
+void AsyncCallbackThread::onFirstRef()
{
run("Offload Cbk", ANDROID_PRIORITY_URGENT_AUDIO);
}
-bool AudioFlinger::AsyncCallbackThread::threadLoop()
+bool AsyncCallbackThread::threadLoop()
{
while (!exitPending()) {
uint32_t writeAckSequence;
@@ -6989,12 +7105,12 @@
bool asyncError;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
while (!((mWriteAckSequence & 1) ||
(mDrainSequence & 1) ||
mAsyncError ||
exitPending())) {
- mWaitWorkCV.wait(mLock);
+ mWaitWorkCV.wait(_l);
}
if (exitPending()) {
@@ -7010,7 +7126,7 @@
mAsyncError = false;
}
{
- sp<AudioFlinger::PlaybackThread> playbackThread = mPlaybackThread.promote();
+ const sp<PlaybackThread> playbackThread = mPlaybackThread.promote();
if (playbackThread != 0) {
if (writeAckSequence & 1) {
playbackThread->resetWriteBlocked(writeAckSequence >> 1);
@@ -7027,61 +7143,70 @@
return false;
}
-void AudioFlinger::AsyncCallbackThread::exit()
+void AsyncCallbackThread::exit()
{
ALOGV("AsyncCallbackThread::exit");
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
requestExit();
- mWaitWorkCV.broadcast();
+ mWaitWorkCV.notify_all();
}
-void AudioFlinger::AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
+void AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// bit 0 is cleared
mWriteAckSequence = sequence << 1;
}
-void AudioFlinger::AsyncCallbackThread::resetWriteBlocked()
+void AsyncCallbackThread::resetWriteBlocked()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// ignore unexpected callbacks
if (mWriteAckSequence & 2) {
mWriteAckSequence |= 1;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
}
-void AudioFlinger::AsyncCallbackThread::setDraining(uint32_t sequence)
+void AsyncCallbackThread::setDraining(uint32_t sequence)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// bit 0 is cleared
mDrainSequence = sequence << 1;
}
-void AudioFlinger::AsyncCallbackThread::resetDraining()
+void AsyncCallbackThread::resetDraining()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// ignore unexpected callbacks
if (mDrainSequence & 2) {
mDrainSequence |= 1;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
}
-void AudioFlinger::AsyncCallbackThread::setAsyncError()
+void AsyncCallbackThread::setAsyncError()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mAsyncError = true;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
// ----------------------------------------------------------------------------
-AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
+
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createOffloadThread(
+ const sp<IAfThreadCallback>& afThreadCallback,
+ AudioStreamOut* output, audio_io_handle_t id, bool systemReady,
+ const audio_offload_info_t& offloadInfo) {
+ return sp<OffloadThread>::make(afThreadCallback, output, id, systemReady, offloadInfo);
+}
+
+OffloadThread::OffloadThread(const sp<IAfThreadCallback>& afThreadCallback,
AudioStreamOut* output, audio_io_handle_t id, bool systemReady,
const audio_offload_info_t& offloadInfo)
- : DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady, offloadInfo),
+ : DirectOutputThread(afThreadCallback, output, id, OFFLOAD, systemReady, offloadInfo),
mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
{
//FIXME: mStandby should be set to true by ThreadBase constructo
@@ -7089,7 +7214,7 @@
mKeepWakeLock = property_get_bool("ro.audio.offload_wakelock", true /* default_value */);
}
-void AudioFlinger::OffloadThread::threadLoop_exit()
+void OffloadThread::threadLoop_exit()
{
if (mFlushPending || mHwPaused) {
// If a flush is pending or track was paused, just discard buffered data
@@ -7105,8 +7230,8 @@
PlaybackThread::threadLoop_exit();
}
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTracks_l(
- Vector< sp<Track> > *tracksToRemove
+PlaybackThread::mixer_state OffloadThread::prepareTracks_l(
+ Vector<sp<IAfTrack>>* tracksToRemove
)
{
size_t count = mActiveTracks.size();
@@ -7118,8 +7243,8 @@
ALOGV("OffloadThread::prepareTracks_l active tracks %zu", count);
// find out which tracks need to be processed
- for (const sp<Track> &t : mActiveTracks) {
- Track* const track = t.get();
+ for (const sp<IAfTrack>& t : mActiveTracks) {
+ IAfTrack* const track = t.get();
#ifdef VERY_VERY_VERBOSE_LOGGING
audio_track_cblk_t* cblk = track->cblk();
#endif
@@ -7127,7 +7252,7 @@
// In theory an older track could underrun and restart after the new one starts
// but as we only care about the transition phase between two tracks on a
// direct output, it is not a problem to ignore the underrun case.
- sp<Track> l = mActiveTracks.getLatest();
+ sp<IAfTrack> l = mActiveTracks.getLatest();
bool last = l.get() == track;
if (track->isInvalid()) {
@@ -7136,7 +7261,7 @@
continue;
}
- if (track->mState == TrackBase::IDLE) {
+ if (track->state() == IAfTrackBase::IDLE) {
ALOGW("An idle track shouldn't be in active list");
continue;
}
@@ -7168,9 +7293,9 @@
tracksToRemove->add(track);
} else if (track->isFlushPending()) {
if (track->isStopping_1()) {
- track->mRetryCount = kMaxTrackStopRetriesOffload;
+ track->retryCount() = kMaxTrackStopRetriesOffload;
} else {
- track->mRetryCount = kMaxTrackRetriesOffload;
+ track->retryCount() = kMaxTrackRetriesOffload;
}
track->flushAck();
if (last) {
@@ -7202,8 +7327,8 @@
} else if (track->framesReady() && track->isReady() &&
!track->isPaused() && !track->isTerminated() && !track->isStopping_2()) {
ALOGVV("OffloadThread: track(%d) s=%08x [OK]", track->id(), cblk->mServer);
- if (track->mFillingUpStatus == Track::FS_FILLED) {
- track->mFillingUpStatus = Track::FS_ACTIVE;
+ if (track->fillingStatus() == IAfTrack::FS_FILLED) {
+ track->fillingStatus() = IAfTrack::FS_ACTIVE;
if (last) {
// make sure processVolume_l() will apply new volume even if 0
mLeftVolFloat = mRightVolFloat = -1.0;
@@ -7211,7 +7336,7 @@
}
if (last) {
- sp<Track> previousTrack = mPreviousTrack.promote();
+ sp<IAfTrack> previousTrack = mPreviousTrack.promote();
if (previousTrack != 0) {
if (track != previousTrack.get()) {
// Flush any data still being written from last track
@@ -7237,9 +7362,9 @@
mPreviousTrack = track;
// reset retry count
if (track->isStopping_1()) {
- track->mRetryCount = kMaxTrackStopRetriesOffload;
+ track->retryCount() = kMaxTrackStopRetriesOffload;
} else {
- track->mRetryCount = kMaxTrackRetriesOffload;
+ track->retryCount() = kMaxTrackRetriesOffload;
}
mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
@@ -7247,7 +7372,7 @@
} else {
ALOGVV("OffloadThread: track(%d) s=%08x [NOT READY]", track->id(), cblk->mServer);
if (track->isStopping_1()) {
- if (--(track->mRetryCount) <= 0) {
+ if (--(track->retryCount()) <= 0) {
// Hardware buffer can hold a large amount of audio so we must
// wait for all current track's data to drain before we say
// that the track is stopped.
@@ -7255,7 +7380,8 @@
// Only start draining when all data in mixbuffer
// has been written
ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
- track->mState = TrackBase::STOPPING_2; // so presentation completes after
+ track->setState(IAfTrackBase::STOPPING_2);
+ // so presentation completes after
// drain do not drain if no data was ever sent to HAL (mStandby == true)
if (last && !mStandby) {
// do not modify drain sequence if we are already draining. This happens
@@ -7275,13 +7401,13 @@
}
}
} else if (last) {
- ALOGV("stopping1 underrun retries left %d", track->mRetryCount);
+ ALOGV("stopping1 underrun retries left %d", track->retryCount());
mixerStatus = MIXER_TRACKS_ENABLED;
}
} else if (track->isStopping_2()) {
// Drain has completed or we are in standby, signal presentation complete
if (!(mDrainSequence & 1) || !last || mStandby) {
- track->mState = TrackBase::STOPPED;
+ track->setState(IAfTrackBase::STOPPED);
mOutput->presentationComplete();
track->presentationComplete(latency_l()); // always returns true
track->reset();
@@ -7301,9 +7427,9 @@
// fill a buffer, then remove it from active list.
bool isTimestampAdvancing = mIsTimestampAdvancing.check(mOutput);
if (!isTunerStream() // tuner streams remain active in underrun
- && --(track->mRetryCount) <= 0) {
+ && --(track->retryCount()) <= 0) {
if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
- track->mRetryCount = kMaxTrackRetriesOffload;
+ track->retryCount() = kMaxTrackRetriesOffload;
} else {
ALOGV("OffloadThread: BUFFER TIMEOUT: remove track(%d) from active list",
track->id());
@@ -7347,7 +7473,7 @@
}
// must be called with thread mutex locked
-bool AudioFlinger::OffloadThread::waitingAsyncCallback_l()
+bool OffloadThread::waitingAsyncCallback_l()
{
ALOGVV("waitingAsyncCallback_l mWriteAckSequence %d mDrainSequence %d",
mWriteAckSequence, mDrainSequence);
@@ -7357,13 +7483,13 @@
return false;
}
-bool AudioFlinger::OffloadThread::waitingAsyncCallback()
+bool OffloadThread::waitingAsyncCallback()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return waitingAsyncCallback_l();
}
-void AudioFlinger::OffloadThread::flushHw_l()
+void OffloadThread::flushHw_l()
{
DirectOutputThread::flushHw_l();
// Flush anything still waiting in the mixbuffer
@@ -7384,16 +7510,16 @@
}
}
-void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
+void OffloadThread::invalidateTracks(audio_stream_type_t streamType)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (PlaybackThread::invalidateTracks_l(streamType)) {
mFlushPending = true;
}
}
-void AudioFlinger::OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
- Mutex::Autolock _l(mLock);
+void OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
+ audio_utils::lock_guard _l(mutex());
if (PlaybackThread::invalidateTracks_l(portIds)) {
mFlushPending = true;
}
@@ -7401,23 +7527,30 @@
// ----------------------------------------------------------------------------
-AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
- AudioFlinger::MixerThread* mainThread, audio_io_handle_t id, bool systemReady)
- : MixerThread(audioFlinger, mainThread->getOutput(), id,
+/* static */
+sp<IAfDuplicatingThread> IAfDuplicatingThread::create(
+ const sp<IAfThreadCallback>& afThreadCallback,
+ IAfPlaybackThread* mainThread, audio_io_handle_t id, bool systemReady) {
+ return sp<DuplicatingThread>::make(afThreadCallback, mainThread, id, systemReady);
+}
+
+DuplicatingThread::DuplicatingThread(const sp<IAfThreadCallback>& afThreadCallback,
+ IAfPlaybackThread* mainThread, audio_io_handle_t id, bool systemReady)
+ : MixerThread(afThreadCallback, mainThread->getOutput(), id,
systemReady, DUPLICATING),
mWaitTimeMs(UINT_MAX)
{
addOutputTrack(mainThread);
}
-AudioFlinger::DuplicatingThread::~DuplicatingThread()
+DuplicatingThread::~DuplicatingThread()
{
for (size_t i = 0; i < mOutputTracks.size(); i++) {
mOutputTracks[i]->destroy();
}
}
-void AudioFlinger::DuplicatingThread::threadLoop_mix()
+void DuplicatingThread::threadLoop_mix()
{
// mix buffers...
if (outputsReady()) {
@@ -7435,7 +7568,7 @@
mStandbyTimeNs = systemTime() + mStandbyDelayNs;
}
-void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
+void DuplicatingThread::threadLoop_sleepTime()
{
if (mSleepTimeUs == 0) {
if (mMixerStatus == MIXER_TRACKS_ENABLED) {
@@ -7455,7 +7588,7 @@
}
}
-ssize_t AudioFlinger::DuplicatingThread::threadLoop_write()
+ssize_t DuplicatingThread::threadLoop_write()
{
for (size_t i = 0; i < outputTracks.size(); i++) {
const ssize_t actualWritten = outputTracks[i]->write(mSinkBuffer, writeFrames);
@@ -7483,7 +7616,7 @@
return (ssize_t)mSinkBufferSize;
}
-void AudioFlinger::DuplicatingThread::threadLoop_standby()
+void DuplicatingThread::threadLoop_standby()
{
// DuplicatingThread implements standby by stopping all tracks
for (size_t i = 0; i < outputTracks.size(); i++) {
@@ -7491,7 +7624,7 @@
}
}
-void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
MixerThread::dumpInternals_l(fd, args);
@@ -7501,7 +7634,7 @@
if (numTracks > 0) {
ss << ":";
for (const auto &track : mOutputTracks) {
- const sp<ThreadBase> thread = track->thread().promote();
+ const auto thread = track->thread().promote();
ss << " (" << track->id() << " : ";
if (thread.get() != nullptr) {
ss << thread.get() << ", " << thread->id();
@@ -7516,19 +7649,19 @@
write(fd, result.c_str(), result.size());
}
-void AudioFlinger::DuplicatingThread::saveOutputTracks()
+void DuplicatingThread::saveOutputTracks()
{
outputTracks = mOutputTracks;
}
-void AudioFlinger::DuplicatingThread::clearOutputTracks()
+void DuplicatingThread::clearOutputTracks()
{
outputTracks.clear();
}
-void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
+void DuplicatingThread::addOutputTrack(IAfPlaybackThread* thread)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// The downstream MixerThread consumes thread->frameCount() amount of frames per mix pass.
// Adjust for thread->sampleRate() to determine minimum buffer frame count.
// Then triple buffer because Threads do not run synchronously and may not be clock locked.
@@ -7545,7 +7678,7 @@
attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(
IPCThreadState::self()->getCallingPid()));
attributionSource.token = sp<BBinder>::make();
- sp<OutputTrack> outputTrack = new OutputTrack(thread,
+ sp<IAfOutputTrack> outputTrack = IAfOutputTrack::create(thread,
this,
mSampleRate,
mFormat,
@@ -7563,9 +7696,9 @@
updateWaitTime_l();
}
-void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
+void DuplicatingThread::removeOutputTrack(IAfPlaybackThread* thread)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mOutputTracks.size(); i++) {
if (mOutputTracks[i]->thread() == thread) {
mOutputTracks[i]->destroy();
@@ -7580,12 +7713,12 @@
ALOGV("removeOutputTrack(): unknown thread: %p", thread);
}
-// caller must hold mLock
-void AudioFlinger::DuplicatingThread::updateWaitTime_l()
+// caller must hold mutex()
+void DuplicatingThread::updateWaitTime_l()
{
mWaitTimeMs = UINT_MAX;
for (size_t i = 0; i < mOutputTracks.size(); i++) {
- sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
+ const auto strong = mOutputTracks[i]->thread().promote();
if (strong != 0) {
uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
if (waitTimeMs < mWaitTimeMs) {
@@ -7595,18 +7728,18 @@
}
}
-bool AudioFlinger::DuplicatingThread::outputsReady()
+bool DuplicatingThread::outputsReady()
{
for (size_t i = 0; i < outputTracks.size(); i++) {
- sp<ThreadBase> thread = outputTracks[i]->thread().promote();
+ const auto thread = outputTracks[i]->thread().promote();
if (thread == 0) {
ALOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p",
outputTracks[i].get());
return false;
}
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ IAfPlaybackThread* const playbackThread = thread->asIAfPlaybackThread().get();
// see note at standby() declaration
- if (playbackThread->standby() && !playbackThread->isSuspended()) {
+ if (playbackThread->inStandby() && !playbackThread->isSuspended()) {
ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(),
thread.get());
return false;
@@ -7615,7 +7748,7 @@
return true;
}
-void AudioFlinger::DuplicatingThread::sendMetadataToBackend_l(
+void DuplicatingThread::sendMetadataToBackend_l(
const StreamOutHalInterface::SourceMetadata& metadata)
{
for (auto& outputTrack : outputTracks) { // not mOutputTracks
@@ -7623,12 +7756,12 @@
}
}
-uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const
+uint32_t DuplicatingThread::activeSleepTimeUs() const
{
return (mWaitTimeMs * 1000) / 2;
}
-void AudioFlinger::DuplicatingThread::cacheParameters_l()
+void DuplicatingThread::cacheParameters_l()
{
// updateWaitTime_l() sets mWaitTimeMs, which affects activeSleepTimeUs(), so call it first
updateWaitTime_l();
@@ -7638,31 +7771,26 @@
// ----------------------------------------------------------------------------
-AudioFlinger::SpatializerThread::SpatializerThread(const sp<AudioFlinger>& audioFlinger,
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createSpatializerThread(
+ const sp<IAfThreadCallback>& afThreadCallback,
+ AudioStreamOut* output,
+ audio_io_handle_t id,
+ bool systemReady,
+ audio_config_base_t* mixerConfig) {
+ return sp<SpatializerThread>::make(afThreadCallback, output, id, systemReady, mixerConfig);
+}
+
+SpatializerThread::SpatializerThread(const sp<IAfThreadCallback>& afThreadCallback,
AudioStreamOut* output,
audio_io_handle_t id,
bool systemReady,
audio_config_base_t *mixerConfig)
- : MixerThread(audioFlinger, output, id, systemReady, SPATIALIZER, mixerConfig)
+ : MixerThread(afThreadCallback, output, id, systemReady, SPATIALIZER, mixerConfig)
{
}
-void AudioFlinger::SpatializerThread::onFirstRef() {
- MixerThread::onFirstRef();
-
- const pid_t tid = getTid();
- if (tid == -1) {
- // Unusual: PlaybackThread::onFirstRef() should set the threadLoop running.
- ALOGW("%s: Cannot update Spatializer mixer thread priority, not running", __func__);
- } else {
- const int priorityBoost = requestSpatializerPriority(getpid(), tid);
- if (priorityBoost > 0) {
- stream()->setHalThreadPriority(priorityBoost);
- }
- }
-}
-
-void AudioFlinger::SpatializerThread::setHalLatencyMode_l() {
+void SpatializerThread::setHalLatencyMode_l() {
// if mSupportedLatencyModes is empty, the HAL stream does not support
// latency mode control and we can exit.
if (mSupportedLatencyModes.empty()) {
@@ -7700,23 +7828,25 @@
}
}
-status_t AudioFlinger::SpatializerThread::setRequestedLatencyMode(audio_latency_mode_t mode) {
+status_t SpatializerThread::setRequestedLatencyMode(audio_latency_mode_t mode) {
if (mode != AUDIO_LATENCY_MODE_LOW && mode != AUDIO_LATENCY_MODE_FREE) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mRequestedLatencyMode = mode;
return NO_ERROR;
}
-void AudioFlinger::SpatializerThread::checkOutputStageEffects()
+void SpatializerThread::checkOutputStageEffects()
+NO_THREAD_SAFETY_ANALYSIS
+// 'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
{
bool hasVirtualizer = false;
bool hasDownMixer = false;
- sp<EffectHandle> finalDownMixer;
+ sp<IAfEffectHandle> finalDownMixer;
{
- Mutex::Autolock _l(mLock);
- sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
+ audio_utils::lock_guard _l(mutex());
+ sp<IAfEffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
if (chain != 0) {
hasVirtualizer = chain->getEffectFromType_l(FX_IID_SPATIALIZER) != nullptr;
hasDownMixer = chain->getEffectFromType_l(EFFECT_UIID_DOWNMIX) != nullptr;
@@ -7729,12 +7859,12 @@
if (hasVirtualizer) {
if (finalDownMixer != nullptr) {
int32_t ret;
- finalDownMixer->disable(&ret);
+ finalDownMixer->asIEffect()->disable(&ret);
}
finalDownMixer.clear();
} else if (!hasDownMixer) {
std::vector<effect_descriptor_t> descriptors;
- status_t status = mAudioFlinger->mEffectsFactoryHal->getDescriptors(
+ status_t status = mAfThreadCallback->getEffectsFactoryHal()->getDescriptors(
EFFECT_UIID_DOWNMIX, &descriptors);
if (status != NO_ERROR) {
return;
@@ -7751,12 +7881,12 @@
finalDownMixer.clear();
} else {
int32_t ret;
- finalDownMixer->enable(&ret);
+ finalDownMixer->asIEffect()->enable(&ret);
}
}
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mFinalDownMixer = finalDownMixer;
}
}
@@ -7765,12 +7895,19 @@
// Record
// ----------------------------------------------------------------------------
-AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
+sp<IAfRecordThread> IAfRecordThread::create(const sp<IAfThreadCallback>& afThreadCallback,
+ AudioStreamIn* input,
+ audio_io_handle_t id,
+ bool systemReady) {
+ return sp<RecordThread>::make(afThreadCallback, input, id, systemReady);
+}
+
+RecordThread::RecordThread(const sp<IAfThreadCallback>& afThreadCallback,
AudioStreamIn *input,
audio_io_handle_t id,
bool systemReady
) :
- ThreadBase(audioFlinger, id, RECORD, systemReady, false /* isOut */),
+ ThreadBase(afThreadCallback, id, RECORD, systemReady, false /* isOut */),
mInput(input),
mSource(mInput),
mActiveTracks(&this->mLocalLog),
@@ -7791,7 +7928,7 @@
, mBtNrecSuspended(false)
{
snprintf(mThreadName, kThreadNameLength, "AudioIn_%X", id);
- mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
+ mNBLogWriter = afThreadCallback->newWriter_l(kLogSize, mThreadName);
if (mInput->audioHwDev != nullptr) {
mIsMsdDevice = strcmp(
@@ -7899,7 +8036,8 @@
#ifdef TEE_SINK
// FIXME
#endif
- mFastCaptureNBLogWriter = audioFlinger->newWriter_l(kFastCaptureLogSize, "FastCapture");
+ mFastCaptureNBLogWriter =
+ afThreadCallback->newWriter_l(kFastCaptureLogSize, "FastCapture");
state->mNBLogWriter = mFastCaptureNBLogWriter.get();
sq->end();
sq->push(FastCaptureStateQueue::BLOCK_UNTIL_PUSHED);
@@ -7924,7 +8062,7 @@
// FIXME mNormalSource
}
-AudioFlinger::RecordThread::~RecordThread()
+RecordThread::~RecordThread()
{
if (mFastCapture != 0) {
FastCaptureStateQueue *sq = mFastCapture->sq();
@@ -7941,38 +8079,38 @@
mFastCapture->join();
mFastCapture.clear();
}
- mAudioFlinger->unregisterWriter(mFastCaptureNBLogWriter);
- mAudioFlinger->unregisterWriter(mNBLogWriter);
+ mAfThreadCallback->unregisterWriter(mFastCaptureNBLogWriter);
+ mAfThreadCallback->unregisterWriter(mNBLogWriter);
free(mRsmpInBuffer);
}
-void AudioFlinger::RecordThread::onFirstRef()
+void RecordThread::onFirstRef()
{
run(mThreadName, PRIORITY_URGENT_AUDIO);
}
-void AudioFlinger::RecordThread::preExit()
+void RecordThread::preExit()
{
ALOGV(" preExit()");
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
- sp<RecordTrack> track = mTracks[i];
+ sp<IAfRecordTrack> track = mTracks[i];
track->invalidate();
}
mActiveTracks.clear();
- mStartStopCond.broadcast();
+ mStartStopCV.notify_all();
}
-bool AudioFlinger::RecordThread::threadLoop()
+bool RecordThread::threadLoop()
{
nsecs_t lastWarning = 0;
inputStandBy();
reacquire_wakelock:
- sp<RecordTrack> activeTrack;
+ sp<IAfRecordTrack> activeTrack;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
acquireWakeLock_l();
}
@@ -7983,26 +8121,26 @@
// loop while there is work to do
for (int64_t loopCount = 0;; ++loopCount) { // loopCount used for statistics tracking
- Vector< sp<EffectChain> > effectChains;
+ Vector<sp<IAfEffectChain>> effectChains;
// activeTracks accumulates a copy of a subset of mActiveTracks
- Vector< sp<RecordTrack> > activeTracks;
+ Vector<sp<IAfRecordTrack>> activeTracks;
// reference to the (first and only) active fast track
- sp<RecordTrack> fastTrack;
+ sp<IAfRecordTrack> fastTrack;
// reference to a fast track which is about to be removed
- sp<RecordTrack> fastTrackToRemove;
+ sp<IAfRecordTrack> fastTrackToRemove;
bool silenceFastCapture = false;
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::unique_lock _l(mutex());
processConfigEvents_l();
// check exitPending here because checkForNewParameters_l() and
- // checkForNewParameters_l() can temporarily release mLock
+ // checkForNewParameters_l() can temporarily release mutex()
if (exitPending()) {
break;
}
@@ -8010,7 +8148,7 @@
// sleep with mutex unlocked
if (sleepUs > 0) {
ATRACE_BEGIN("sleepC");
- mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)sleepUs));
+ (void)mWaitWorkCV.wait_for(_l, std::chrono::microseconds(sleepUs));
ATRACE_END();
sleepUs = 0;
continue;
@@ -8024,7 +8162,7 @@
releaseWakeLock_l();
ALOGV("RecordThread: loop stopping");
// go to sleep
- mWaitWorkCV.wait(mLock);
+ mWaitWorkCV.wait(_l);
ALOGV("RecordThread: loop starting");
goto reacquire_wakelock;
}
@@ -8045,40 +8183,40 @@
continue;
}
- TrackBase::track_state activeTrackState = activeTrack->mState;
+ IAfTrackBase::track_state activeTrackState = activeTrack->state();
switch (activeTrackState) {
- case TrackBase::PAUSING:
+ case IAfTrackBase::PAUSING:
mActiveTracks.remove(activeTrack);
- activeTrack->mState = TrackBase::PAUSED;
+ activeTrack->setState(IAfTrackBase::PAUSED);
doBroadcast = true;
size--;
continue;
- case TrackBase::STARTING_1:
+ case IAfTrackBase::STARTING_1:
sleepUs = 10000;
i++;
allStopped = false;
continue;
- case TrackBase::STARTING_2:
+ case IAfTrackBase::STARTING_2:
doBroadcast = true;
if (mStandby) {
mThreadMetrics.logBeginInterval();
mThreadSnapshot.onBegin();
mStandby = false;
}
- activeTrack->mState = TrackBase::ACTIVE;
+ activeTrack->setState(IAfTrackBase::ACTIVE);
allStopped = false;
break;
- case TrackBase::ACTIVE:
+ case IAfTrackBase::ACTIVE:
allStopped = false;
break;
- case TrackBase::IDLE: // cannot be on ActiveTracks if idle
- case TrackBase::PAUSED: // cannot be on ActiveTracks if paused
- case TrackBase::STOPPED: // cannot be on ActiveTracks if destroyed/terminated
+ case IAfTrackBase::IDLE: // cannot be on ActiveTracks if idle
+ case IAfTrackBase::PAUSED: // cannot be on ActiveTracks if paused
+ case IAfTrackBase::STOPPED: // cannot be on ActiveTracks if destroyed/terminated
default:
LOG_ALWAYS_FATAL("%s: Unexpected active track state:%d, id:%d, tracks:%zu",
__func__, activeTrackState, activeTrack->id(), size);
@@ -8131,7 +8269,7 @@
standbyIfNotAlreadyInStandby();
}
if (doBroadcast) {
- mStartStopCond.broadcast();
+ mStartStopCV.notify_all();
}
// sleep if there are no active tracks to process
@@ -8170,7 +8308,7 @@
}
state->mCommand = FastCaptureState::READ_WRITE;
#if 0 // FIXME
- mFastCaptureDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
+ mFastCaptureDumpState.increaseSamplingN(mAfThreadCallback->isLowRamDevice() ?
FastThreadDumpState::kSamplingNforLowRamDevice :
FastThreadDumpState::kSamplingN);
#endif
@@ -8325,7 +8463,7 @@
// From the timestamp, input read latency is negative output write latency.
const audio_input_flags_t flags = mInput != NULL ? mInput->flags : AUDIO_INPUT_FLAG_NONE;
- const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, flags)
+ const double latencyMs = IAfRecordTrack::checkServerLatencySupported(mFormat, flags)
? - mTimestamp.getOutputServerLatencyMs(mSampleRate) : 0.;
if (latencyMs != 0.) { // note 0. means timestamp is empty.
mLatencyMs.add(latencyMs);
@@ -8382,16 +8520,16 @@
// loop over getNextBuffer to handle circular sink
for (;;) {
- activeTrack->mSink.frameCount = ~0;
- status_t status = activeTrack->getNextBuffer(&activeTrack->mSink);
- size_t framesOut = activeTrack->mSink.frameCount;
+ activeTrack->sinkBuffer().frameCount = ~0;
+ status_t status = activeTrack->getNextBuffer(&activeTrack->sinkBuffer());
+ size_t framesOut = activeTrack->sinkBuffer().frameCount;
LOG_ALWAYS_FATAL_IF((status == OK) != (framesOut > 0));
// check available frames and handle overrun conditions
// if the record track isn't draining fast enough.
bool hasOverrun;
size_t framesIn;
- activeTrack->mResamplerBufferProvider->sync(&framesIn, &hasOverrun);
+ activeTrack->resamplerBufferProvider()->sync(&framesIn, &hasOverrun);
if (hasOverrun) {
overrun = OVERRUN_TRUE;
}
@@ -8405,7 +8543,7 @@
// RecordBufferConverter. TODO: remove when no longer needed.
framesOut = min(framesOut,
destinationFramesPossible(
- framesIn, mSampleRate, activeTrack->mSampleRate));
+ framesIn, mSampleRate, activeTrack->sampleRate()));
if (activeTrack->isDirect()) {
// No RecordBufferConverter used for direct streams. Pass
@@ -8413,14 +8551,15 @@
AudioBufferProvider::Buffer buffer;
buffer.frameCount = framesOut;
const status_t getNextBufferStatus =
- activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
+ activeTrack->resamplerBufferProvider()->getNextBuffer(&buffer);
if (getNextBufferStatus == OK && buffer.frameCount != 0) {
ALOGV_IF(buffer.frameCount != framesOut,
"%s() read less than expected (%zu vs %zu)",
__func__, buffer.frameCount, framesOut);
framesOut = buffer.frameCount;
- memcpy(activeTrack->mSink.raw, buffer.raw, buffer.frameCount * mFrameSize);
- activeTrack->mResamplerBufferProvider->releaseBuffer(&buffer);
+ memcpy(activeTrack->sinkBuffer().raw,
+ buffer.raw, buffer.frameCount * mFrameSize);
+ activeTrack->resamplerBufferProvider()->releaseBuffer(&buffer);
} else {
framesOut = 0;
ALOGE("%s() cannot fill request, status: %d, frameCount: %zu",
@@ -8429,9 +8568,9 @@
} else {
// process frames from the RecordThread buffer provider to the RecordTrack
// buffer
- framesOut = activeTrack->mRecordBufferConverter->convert(
- activeTrack->mSink.raw,
- activeTrack->mResamplerBufferProvider,
+ framesOut = activeTrack->recordBufferConverter()->convert(
+ activeTrack->sinkBuffer().raw,
+ activeTrack->resamplerBufferProvider(),
framesOut);
}
@@ -8441,17 +8580,18 @@
// MediaSyncEvent handling: Synchronize AudioRecord to AudioTrack completion.
const ssize_t framesToDrop =
- activeTrack->mSynchronizedRecordState.updateRecordFrames(framesOut);
+ activeTrack->synchronizedRecordState().updateRecordFrames(framesOut);
if (framesToDrop == 0) {
// no sync event, process normally, otherwise ignore.
if (framesOut > 0) {
- activeTrack->mSink.frameCount = framesOut;
+ activeTrack->sinkBuffer().frameCount = framesOut;
// Sanitize before releasing if the track has no access to the source data
// An idle UID receives silence from non virtual devices until active
if (activeTrack->isSilenced()) {
- memset(activeTrack->mSink.raw, 0, framesOut * activeTrack->frameSize());
+ memset(activeTrack->sinkBuffer().raw,
+ 0, framesOut * activeTrack->frameSize());
}
- activeTrack->releaseBuffer(&activeTrack->mSink);
+ activeTrack->releaseBuffer(&activeTrack->sinkBuffer());
}
}
if (framesOut == 0) {
@@ -8480,7 +8620,7 @@
// update frame information and push timestamp out
activeTrack->updateTrackFrameInfo(
- activeTrack->mServerProxy->framesReleased(),
+ activeTrack->serverProxy()->framesReleased(),
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER],
mSampleRate, mTimestamp);
}
@@ -8498,7 +8638,7 @@
{0, 0} /* lastTimestamp */, mSampleRate);
const double processMs = (lastIoBeginNs - mLastIoEndNs) * 1e-6;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mIoJitterMs.add(jitterMs);
mProcessTimeMs.add(processMs);
}
@@ -8511,13 +8651,13 @@
standbyIfNotAlreadyInStandby();
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
- sp<RecordTrack> track = mTracks[i];
+ sp<IAfRecordTrack> track = mTracks[i];
track->invalidate();
}
mActiveTracks.clear();
- mStartStopCond.broadcast();
+ mStartStopCV.notify_all();
}
releaseWakeLock();
@@ -8526,7 +8666,7 @@
return false;
}
-void AudioFlinger::RecordThread::standbyIfNotAlreadyInStandby()
+void RecordThread::standbyIfNotAlreadyInStandby()
{
if (!mStandby) {
inputStandBy();
@@ -8536,7 +8676,7 @@
}
}
-void AudioFlinger::RecordThread::inputStandBy()
+void RecordThread::inputStandBy()
{
// Idle the fast capture if it's currently running
if (mFastCapture != 0) {
@@ -8576,9 +8716,9 @@
}
}
-// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
- const sp<AudioFlinger::Client>& client,
+// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mutex() held
+sp<IAfRecordTrack> RecordThread::createRecordTrack_l(
+ const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
audio_format_t format,
@@ -8596,7 +8736,7 @@
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
- sp<RecordTrack> track;
+ sp<IAfRecordTrack> track;
status_t lStatus;
audio_input_flags_t inputFlags = mInput->flags;
audio_input_flags_t requestedFlags = *flags;
@@ -8620,7 +8760,7 @@
goto Exit;
}
if (maxSharedAudioHistoryMs < 0
- || maxSharedAudioHistoryMs > AudioFlinger::kMaxSharedAudioHistoryMs) {
+ || maxSharedAudioHistoryMs > kMaxSharedAudioHistoryMs) {
lStatus = BAD_VALUE;
goto Exit;
}
@@ -8668,9 +8808,9 @@
mFastTrackAvail
) {
// check compatibility with audio effects.
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Do not accept FAST flag if the session has software effects
- sp<EffectChain> chain = getEffectChain_l(sessionId);
+ sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
if (chain != 0) {
audio_input_flags_t old = *flags;
chain->checkInputFlagCompatibility(flags);
@@ -8732,8 +8872,8 @@
*pFrameCount = frameCount;
*pNotificationFrameCount = notificationFrameCount;
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::lock_guard _l(mutex());
int32_t startFrames = -1;
if (!mSharedAudioPackageName.empty()
&& mSharedAudioPackageName == attributionSource.packageName
@@ -8742,10 +8882,10 @@
startFrames = mSharedAudioStartFrames;
}
- track = new RecordTrack(this, client, attr, sampleRate,
+ track = IAfRecordTrack::create(this, client, attr, sampleRate,
format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
- attributionSource, *flags, TrackBase::TYPE_DEFAULT, portId,
+ attributionSource, *flags, IAfTrackBase::TYPE_DEFAULT, portId,
startFrames);
lStatus = track->initCheck();
@@ -8775,7 +8915,7 @@
return track;
}
-status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
+status_t RecordThread::start(IAfRecordTrack* recordTrack,
AudioSystem::sync_event_t event,
audio_session_t triggerSession)
{
@@ -8786,28 +8926,28 @@
if (event == AudioSystem::SYNC_EVENT_NONE) {
recordTrack->clearSyncStartEvent();
} else if (event != AudioSystem::SYNC_EVENT_SAME) {
- recordTrack->mSynchronizedRecordState.startRecording(
- mAudioFlinger->createSyncEvent(
+ recordTrack->synchronizedRecordState().startRecording(
+ mAfThreadCallback->createSyncEvent(
event, triggerSession,
recordTrack->sessionId(), syncStartEventCallback, recordTrack));
}
{
// This section is a rendezvous between binder thread executing start() and RecordThread
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
if (recordTrack->isInvalid()) {
recordTrack->clearSyncStartEvent();
ALOGW("%s track %d: invalidated before startInput", __func__, recordTrack->portId());
return DEAD_OBJECT;
}
if (mActiveTracks.indexOf(recordTrack) >= 0) {
- if (recordTrack->mState == TrackBase::PAUSING) {
+ if (recordTrack->state() == IAfTrackBase::PAUSING) {
// We haven't stopped yet (moved to PAUSED and not in mActiveTracks)
// so no need to startInput().
ALOGV("active record track PAUSING -> ACTIVE");
- recordTrack->mState = TrackBase::ACTIVE;
+ recordTrack->setState(IAfTrackBase::ACTIVE);
} else {
- ALOGV("active record track state %d", (int)recordTrack->mState);
+ ALOGV("active record track state %d", (int)recordTrack->state());
}
return status;
}
@@ -8815,24 +8955,24 @@
// TODO consider other ways of handling this, such as changing the state to :STARTING and
// adding the track to mActiveTracks after returning from AudioSystem::startInput(),
// or using a separate command thread
- recordTrack->mState = TrackBase::STARTING_1;
+ recordTrack->setState(IAfTrackBase::STARTING_1);
mActiveTracks.add(recordTrack);
if (recordTrack->isExternalTrack()) {
- mLock.unlock();
+ mutex().unlock();
status = AudioSystem::startInput(recordTrack->portId());
- mLock.lock();
+ mutex().lock();
if (recordTrack->isInvalid()) {
recordTrack->clearSyncStartEvent();
- if (status == NO_ERROR && recordTrack->mState == TrackBase::STARTING_1) {
- recordTrack->mState = TrackBase::STARTING_2;
+ if (status == NO_ERROR && recordTrack->state() == IAfTrackBase::STARTING_1) {
+ recordTrack->setState(IAfTrackBase::STARTING_2);
// STARTING_2 forces destroy to call stopInput.
}
ALOGW("%s track %d: invalidated after startInput", __func__, recordTrack->portId());
return DEAD_OBJECT;
}
- if (recordTrack->mState != TrackBase::STARTING_1) {
+ if (recordTrack->state() != IAfTrackBase::STARTING_1) {
ALOGW("%s(%d): unsynchronized mState:%d change",
- __func__, recordTrack->id(), (int)recordTrack->mState);
+ __func__, recordTrack->id(), (int)recordTrack->state());
// Someone else has changed state, let them take over,
// leave mState in the new state.
recordTrack->clearSyncStartEvent();
@@ -8859,67 +8999,66 @@
// was initialized to some value closer to the thread's mRsmpInFront, then the track could
// see previously buffered data before it called start(), but with greater risk of overrun.
- recordTrack->mResamplerBufferProvider->reset();
+ recordTrack->resamplerBufferProvider()->reset();
if (!recordTrack->isDirect()) {
// clear any converter state as new data will be discontinuous
- recordTrack->mRecordBufferConverter->reset();
+ recordTrack->recordBufferConverter()->reset();
}
- recordTrack->mState = TrackBase::STARTING_2;
+ recordTrack->setState(IAfTrackBase::STARTING_2);
// signal thread to start
- mWaitWorkCV.broadcast();
+ mWaitWorkCV.notify_all();
return status;
}
}
-void AudioFlinger::RecordThread::syncStartEventCallback(const wp<audioflinger::SyncEvent>& event)
+void RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
{
- sp<audioflinger::SyncEvent> strongEvent = event.promote();
+ const sp<SyncEvent> strongEvent = event.promote();
if (strongEvent != 0) {
- sp<RefBase> ptr = strongEvent->cookie().promote();
- if (ptr != 0) {
- RecordTrack *recordTrack = (RecordTrack *)ptr.get();
- recordTrack->handleSyncStartEvent(strongEvent);
+ sp<IAfTrackBase> ptr =
+ std::any_cast<const wp<IAfTrackBase>>(strongEvent->cookie()).promote();
+ if (ptr != nullptr) {
+ // TODO(b/291317898) handleSyncStartEvent is in IAfTrackBase not IAfRecordTrack.
+ ptr->handleSyncStartEvent(strongEvent);
}
}
}
-bool AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
+bool RecordThread::stop(IAfRecordTrack* recordTrack) {
ALOGV("RecordThread::stop");
- AutoMutex _l(mLock);
+ audio_utils::unique_lock _l(mutex());
// if we're invalid, we can't be on the ActiveTracks.
- if (mActiveTracks.indexOf(recordTrack) < 0 || recordTrack->mState == TrackBase::PAUSING) {
+ if (mActiveTracks.indexOf(recordTrack) < 0 || recordTrack->state() == IAfTrackBase::PAUSING) {
return false;
}
// note that threadLoop may still be processing the track at this point [without lock]
- recordTrack->mState = TrackBase::PAUSING;
+ recordTrack->setState(IAfTrackBase::PAUSING);
// NOTE: Waiting here is important to keep stop synchronous.
// This is needed for proper patchRecord peer release.
- while (recordTrack->mState == TrackBase::PAUSING && !recordTrack->isInvalid()) {
- mWaitWorkCV.broadcast(); // signal thread to stop
- mStartStopCond.wait(mLock);
+ while (recordTrack->state() == IAfTrackBase::PAUSING && !recordTrack->isInvalid()) {
+ mWaitWorkCV.notify_all(); // signal thread to stop
+ mStartStopCV.wait(_l);
}
- if (recordTrack->mState == TrackBase::PAUSED) { // successful stop
+ if (recordTrack->state() == IAfTrackBase::PAUSED) { // successful stop
ALOGV("Record stopped OK");
return true;
}
// don't handle anything - we've been invalidated or restarted and in a different state
ALOGW_IF("%s(%d): unsynchronized stop, state: %d",
- __func__, recordTrack->id(), recordTrack->mState);
+ __func__, recordTrack->id(), recordTrack->state());
return false;
}
-bool AudioFlinger::RecordThread::isValidSyncEvent(
- const sp<audioflinger::SyncEvent>& /* event */) const
+bool RecordThread::isValidSyncEvent(const sp<SyncEvent>& /* event */) const
{
return false;
}
-status_t AudioFlinger::RecordThread::setSyncEvent(
- const sp<audioflinger::SyncEvent>& event __unused)
+status_t RecordThread::setSyncEvent(const sp<SyncEvent>& /* event */)
{
#if 0 // This branch is currently dead code, but is preserved in case it will be needed in future
if (!isValidSyncEvent(event)) {
@@ -8929,10 +9068,10 @@
audio_session_t eventSession = event->triggerSession();
status_t ret = NAME_NOT_FOUND;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
- sp<RecordTrack> track = mTracks[i];
+ sp<IAfRecordTrack> track = mTracks[i];
if (eventSession == track->sessionId()) {
(void) track->setSyncEvent(event);
ret = NO_ERROR;
@@ -8944,11 +9083,11 @@
#endif
}
-status_t AudioFlinger::RecordThread::getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones)
+status_t RecordThread::getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
{
ALOGV("RecordThread::getActiveMicrophones");
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!isStreamInitialized()) {
return NO_INIT;
}
@@ -8956,35 +9095,35 @@
return status;
}
-status_t AudioFlinger::RecordThread::setPreferredMicrophoneDirection(
+status_t RecordThread::setPreferredMicrophoneDirection(
audio_microphone_direction_t direction)
{
ALOGV("setPreferredMicrophoneDirection(%d)", direction);
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!isStreamInitialized()) {
return NO_INIT;
}
return mInput->stream->setPreferredMicrophoneDirection(direction);
}
-status_t AudioFlinger::RecordThread::setPreferredMicrophoneFieldDimension(float zoom)
+status_t RecordThread::setPreferredMicrophoneFieldDimension(float zoom)
{
ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!isStreamInitialized()) {
return NO_INIT;
}
return mInput->stream->setPreferredMicrophoneFieldDimension(zoom);
}
-status_t AudioFlinger::RecordThread::shareAudioHistory(
+status_t RecordThread::shareAudioHistory(
const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
int64_t sharedAudioStartMs) {
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return shareAudioHistory_l(sharedAudioPackageName, sharedSessionId, sharedAudioStartMs);
}
-status_t AudioFlinger::RecordThread::shareAudioHistory_l(
+status_t RecordThread::shareAudioHistory_l(
const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
int64_t sharedAudioStartMs) {
@@ -9024,20 +9163,20 @@
return NO_ERROR;
}
-void AudioFlinger::RecordThread::resetAudioHistory_l() {
+void RecordThread::resetAudioHistory_l() {
mSharedAudioSessionId = AUDIO_SESSION_NONE;
mSharedAudioStartFrames = -1;
mSharedAudioPackageName = "";
}
-AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::RecordThread::updateMetadata_l()
+ThreadBase::MetadataUpdate RecordThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
return {}; // nothing to do
}
StreamInHalInterface::SinkMetadata metadata;
auto backInserter = std::back_inserter(metadata.tracks);
- for (const sp<RecordTrack> &track : mActiveTracks) {
+ for (const sp<IAfRecordTrack>& track : mActiveTracks) {
track->copyMetadataTo(backInserter);
}
mInput->stream->updateSinkMetadata(metadata);
@@ -9046,11 +9185,11 @@
return change;
}
-// destroyTrack_l() must be called with ThreadBase::mLock held
-void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track)
+// destroyTrack_l() must be called with ThreadBase::mutex() held
+void RecordThread::destroyTrack_l(const sp<IAfRecordTrack>& track)
{
track->terminate();
- track->mState = TrackBase::STOPPED;
+ track->setState(IAfTrackBase::STOPPED);
// active tracks are removed by threadLoop()
if (mActiveTracks.indexOf(track) < 0) {
@@ -9058,7 +9197,7 @@
}
}
-void AudioFlinger::RecordThread::removeTrack_l(const sp<RecordTrack>& track)
+void RecordThread::removeTrack_l(const sp<IAfRecordTrack>& track)
{
String8 result;
track->appendDump(result, false /* active */);
@@ -9072,7 +9211,7 @@
}
}
-void AudioFlinger::RecordThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
+void RecordThread::dumpInternals_l(int fd, const Vector<String16>& /* args */)
{
AudioStreamIn *input = mInput;
audio_input_flags_t flags = input != NULL ? input->flags : AUDIO_INPUT_FLAG_NONE;
@@ -9100,7 +9239,7 @@
copy->dump(fd);
}
-void AudioFlinger::RecordThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
+void RecordThread::dumpTracks_l(int fd, const Vector<String16>& /* args */)
{
String8 result;
size_t numtracks = mTracks.size();
@@ -9113,7 +9252,7 @@
result.append(prefix);
mTracks[0]->appendDumpHeader(result);
for (size_t i = 0; i < numtracks ; ++i) {
- sp<RecordTrack> track = mTracks[i];
+ sp<IAfRecordTrack> track = mTracks[i];
if (track != 0) {
bool active = mActiveTracks.indexOf(track) >= 0;
if (active) {
@@ -9133,7 +9272,7 @@
result.append(prefix);
mActiveTracks[0]->appendDumpHeader(result);
for (size_t i = 0; i < numactive; ++i) {
- sp<RecordTrack> track = mActiveTracks[i];
+ sp<IAfRecordTrack> track = mActiveTracks[i];
if (mTracks.indexOf(track) < 0) {
result.append(prefix);
track->appendDump(result, true /* active */);
@@ -9144,21 +9283,21 @@
write(fd, result.c_str(), result.size());
}
-void AudioFlinger::RecordThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
+void RecordThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size() ; i++) {
- sp<RecordTrack> track = mTracks[i];
+ sp<IAfRecordTrack> track = mTracks[i];
if (track != 0 && track->portId() == portId) {
track->setSilenced(silenced);
}
}
}
-void AudioFlinger::RecordThread::ResamplerBufferProvider::reset()
+void ResamplerBufferProvider::reset()
{
- sp<ThreadBase> threadBase = mRecordTrack->mThread.promote();
- RecordThread *recordThread = (RecordThread *) threadBase.get();
+ const auto threadBase = mRecordTrack->thread().promote();
+ auto* const recordThread = static_cast<RecordThread *>(threadBase->asIAfRecordThread().get());
mRsmpInUnrel = 0;
const int32_t rear = recordThread->mRsmpInRear;
ssize_t deltaFrames = 0;
@@ -9178,11 +9317,11 @@
mRsmpInFront = audio_utils::safe_sub_overflow(rear, static_cast<int32_t>(deltaFrames));
}
-void AudioFlinger::RecordThread::ResamplerBufferProvider::sync(
+void ResamplerBufferProvider::sync(
size_t *framesAvailable, bool *hasOverrun)
{
- sp<ThreadBase> threadBase = mRecordTrack->mThread.promote();
- RecordThread *recordThread = (RecordThread *) threadBase.get();
+ const auto threadBase = mRecordTrack->thread().promote();
+ auto* const recordThread = static_cast<RecordThread *>(threadBase->asIAfRecordThread().get());
const int32_t rear = recordThread->mRsmpInRear;
const int32_t front = mRsmpInFront;
const ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
@@ -9212,16 +9351,16 @@
}
// AudioBufferProvider interface
-status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer(
+status_t ResamplerBufferProvider::getNextBuffer(
AudioBufferProvider::Buffer* buffer)
{
- sp<ThreadBase> threadBase = mRecordTrack->mThread.promote();
+ const auto threadBase = mRecordTrack->thread().promote();
if (threadBase == 0) {
buffer->frameCount = 0;
buffer->raw = NULL;
return NOT_ENOUGH_DATA;
}
- RecordThread *recordThread = (RecordThread *) threadBase.get();
+ auto* const recordThread = static_cast<RecordThread *>(threadBase->asIAfRecordThread().get());
int32_t rear = recordThread->mRsmpInRear;
int32_t front = mRsmpInFront;
ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
@@ -9255,7 +9394,7 @@
}
// AudioBufferProvider interface
-void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer(
+void ResamplerBufferProvider::releaseBuffer(
AudioBufferProvider::Buffer* buffer)
{
int32_t stepCount = static_cast<int32_t>(buffer->frameCount);
@@ -9269,18 +9408,18 @@
buffer->frameCount = 0;
}
-void AudioFlinger::RecordThread::checkBtNrec()
+void RecordThread::checkBtNrec()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
checkBtNrec_l();
}
-void AudioFlinger::RecordThread::checkBtNrec_l()
+void RecordThread::checkBtNrec_l()
{
// disable AEC and NS if the device is a BT SCO headset supporting those
// pre processings
bool suspend = audio_is_bluetooth_sco_device(inDeviceType()) &&
- mAudioFlinger->btNrecIsOff();
+ mAfThreadCallback->btNrecIsOff();
if (mBtNrecSuspended.exchange(suspend) != suspend) {
for (size_t i = 0; i < mEffectChains.size(); i++) {
setEffectSuspended_l(FX_IID_AEC, suspend, mEffectChains[i]->sessionId());
@@ -9290,7 +9429,7 @@
}
-bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValuePair,
+bool RecordThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
bool reconfig = false;
@@ -9378,9 +9517,9 @@
return reconfig;
}
-String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
+String8 RecordThread::getParameters(const String8& keys)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (initCheck() == NO_ERROR) {
String8 out_s8;
if (mInput->stream->getParameters(keys, &out_s8) == OK) {
@@ -9390,7 +9529,7 @@
return {};
}
-void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId) {
sp<AudioIoDescriptor> desc;
switch (event) {
@@ -9408,10 +9547,10 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAudioFlinger->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged(event, desc, pid);
}
-void AudioFlinger::RecordThread::readInputParameters_l()
+void RecordThread::readInputParameters_l()
{
status_t result = mInput->stream->getAudioProperties(&mSampleRate, &mChannelMask, &mHALFormat);
LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving audio properties from HAL: %d", result);
@@ -9445,7 +9584,7 @@
audio_input_flags_t flags = mInput->flags;
mediametrics::LogItem item(mThreadMetrics.getMetricsId());
item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS)
- .set(AMEDIAMETRICS_PROP_ENCODING, formatToString(mFormat).c_str())
+ .set(AMEDIAMETRICS_PROP_ENCODING, IAfThreadBase::formatToString(mFormat).c_str())
.set(AMEDIAMETRICS_PROP_FLAGS, toString(flags).c_str())
.set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
.set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
@@ -9454,9 +9593,9 @@
.record();
}
-uint32_t AudioFlinger::RecordThread::getInputFramesLost()
+uint32_t RecordThread::getInputFramesLost() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
uint32_t result;
if (initCheck() == NO_ERROR && mInput->stream->getInputFramesLost(&result) == OK) {
return result;
@@ -9464,12 +9603,12 @@
return 0;
}
-KeyedVector<audio_session_t, bool> AudioFlinger::RecordThread::sessionIds() const
+KeyedVector<audio_session_t, bool> RecordThread::sessionIds() const
{
KeyedVector<audio_session_t, bool> ids;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t j = 0; j < mTracks.size(); ++j) {
- sp<RecordThread::RecordTrack> track = mTracks[j];
+ sp<IAfRecordTrack> track = mTracks[j];
audio_session_t sessionId = track->sessionId();
if (ids.indexOfKey(sessionId) < 0) {
ids.add(sessionId, true);
@@ -9478,17 +9617,17 @@
return ids;
}
-AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
+AudioStreamIn* RecordThread::clearInput()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioStreamIn *input = mInput;
mInput = NULL;
mInputSource.clear();
return input;
}
-// this method must always be called either with ThreadBase mLock held or inside the thread loop
-sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const
+// this method must always be called either with ThreadBase mutex() held or inside the thread loop
+sp<StreamHalInterface> RecordThread::stream() const
{
if (mInput == NULL) {
return NULL;
@@ -9496,7 +9635,7 @@
return mInput->stream;
}
-status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
+status_t RecordThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
{
ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
chain->setThread(this);
@@ -9514,7 +9653,7 @@
return NO_ERROR;
}
-size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t RecordThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
{
ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
@@ -9527,7 +9666,7 @@
return mEffectChains.size();
}
-status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch *patch,
+status_t RecordThread::createAudioPatch_l(const struct audio_patch* patch,
audio_patch_handle_t *handle)
{
status_t status = NO_ERROR;
@@ -9584,7 +9723,7 @@
return status;
}
-status_t AudioFlinger::RecordThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
+status_t RecordThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
{
status_t status = NO_ERROR;
@@ -9603,9 +9742,9 @@
return status;
}
-void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+void RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mOutDevices = outDevices;
mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9613,7 +9752,7 @@
}
}
-int32_t AudioFlinger::RecordThread::getOldestFront_l()
+int32_t RecordThread::getOldestFront_l()
{
if (mTracks.size() == 0) {
return mRsmpInRear;
@@ -9621,7 +9760,7 @@
int32_t oldestFront = mRsmpInRear;
int32_t maxFilled = 0;
for (size_t i = 0; i < mTracks.size(); i++) {
- int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
+ int32_t front = mTracks[i]->resamplerBufferProvider()->getFront();
int32_t filled;
(void)__builtin_sub_overflow(mRsmpInRear, front, &filled);
if (filled > maxFilled) {
@@ -9635,19 +9774,19 @@
return oldestFront;
}
-void AudioFlinger::RecordThread::updateFronts_l(int32_t offset)
+void RecordThread::updateFronts_l(int32_t offset)
{
if (offset == 0) {
return;
}
for (size_t i = 0; i < mTracks.size(); i++) {
- int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
+ int32_t front = mTracks[i]->resamplerBufferProvider()->getFront();
front = audio_utils::safe_sub_overflow(front, offset);
- mTracks[i]->mResamplerBufferProvider->setFront(front);
+ mTracks[i]->resamplerBufferProvider()->setFront(front);
}
}
-void AudioFlinger::RecordThread::resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs)
+void RecordThread::resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs)
{
// This is the formula for calculating the temporary buffer size.
// With 7 HAL buffers, we can guarantee ability to down-sample the input by ratio of 6:1 to
@@ -9671,7 +9810,7 @@
mRsmpInRear = 0;
ALOG_ASSERT(maxSharedAudioHistoryMs >= 0
- && maxSharedAudioHistoryMs <= AudioFlinger::kMaxSharedAudioHistoryMs,
+ && maxSharedAudioHistoryMs <= kMaxSharedAudioHistoryMs,
"resizeInputBuffer_l() called with invalid max shared history %d",
maxSharedAudioHistoryMs);
if (maxSharedAudioHistoryMs != 0) {
@@ -9740,25 +9879,25 @@
mRsmpInBuffer = rsmpInBuffer;
}
-void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
+void RecordThread::addPatchTrack(const sp<IAfPatchRecord>& record)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mTracks.add(record);
if (record->getSource()) {
mSource = record->getSource();
}
}
-void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
+void RecordThread::deletePatchTrack(const sp<IAfPatchRecord>& record)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mSource == record->getSource()) {
mSource = mInput;
}
destroyTrack_l(record);
}
-void AudioFlinger::RecordThread::toAudioPortConfig(struct audio_port_config *config)
+void RecordThread::toAudioPortConfig(struct audio_port_config* config)
{
ThreadBase::toAudioPortConfig(config);
config->role = AUDIO_PORT_ROLE_SINK;
@@ -9774,59 +9913,88 @@
// Mmap
// ----------------------------------------------------------------------------
-AudioFlinger::MmapThreadHandle::MmapThreadHandle(const sp<MmapThread>& thread)
+// Mmap stream control interface implementation. Each MmapThreadHandle controls one
+// MmapPlaybackThread or MmapCaptureThread instance.
+class MmapThreadHandle : public MmapStreamInterface {
+public:
+ explicit MmapThreadHandle(const sp<IAfMmapThread>& thread);
+ ~MmapThreadHandle() override;
+
+ // MmapStreamInterface virtuals
+ status_t createMmapBuffer(int32_t minSizeFrames,
+ struct audio_mmap_buffer_info* info) final;
+ status_t getMmapPosition(struct audio_mmap_position* position) final;
+ status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) final;
+ 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 reportData(const void* buffer, size_t frameCount) final;
+private:
+ const sp<IAfMmapThread> mThread;
+};
+
+/* static */
+sp<MmapStreamInterface> IAfMmapThread::createMmapStreamInterfaceAdapter(
+ const sp<IAfMmapThread>& mmapThread) {
+ return sp<MmapThreadHandle>::make(mmapThread);
+}
+
+MmapThreadHandle::MmapThreadHandle(const sp<IAfMmapThread>& thread)
: mThread(thread)
{
assert(thread != 0); // thread must start non-null and stay non-null
}
-AudioFlinger::MmapThreadHandle::~MmapThreadHandle()
+// MmapStreamInterface could be directly implemented by MmapThread excepting this
+// special handling on adapter dtor.
+MmapThreadHandle::~MmapThreadHandle()
{
mThread->disconnect();
}
-status_t AudioFlinger::MmapThreadHandle::createMmapBuffer(int32_t minSizeFrames,
+status_t MmapThreadHandle::createMmapBuffer(int32_t minSizeFrames,
struct audio_mmap_buffer_info *info)
{
return mThread->createMmapBuffer(minSizeFrames, info);
}
-status_t AudioFlinger::MmapThreadHandle::getMmapPosition(struct audio_mmap_position *position)
+status_t MmapThreadHandle::getMmapPosition(struct audio_mmap_position* position)
{
return mThread->getMmapPosition(position);
}
-status_t AudioFlinger::MmapThreadHandle::getExternalPosition(uint64_t *position,
+status_t MmapThreadHandle::getExternalPosition(uint64_t* position,
int64_t *timeNanos) {
return mThread->getExternalPosition(position, timeNanos);
}
-status_t AudioFlinger::MmapThreadHandle::start(const AudioClient& client,
+status_t MmapThreadHandle::start(const AudioClient& client,
const audio_attributes_t *attr, audio_port_handle_t *handle)
-
{
return mThread->start(client, attr, handle);
}
-status_t AudioFlinger::MmapThreadHandle::stop(audio_port_handle_t handle)
+status_t MmapThreadHandle::stop(audio_port_handle_t handle)
{
return mThread->stop(handle);
}
-status_t AudioFlinger::MmapThreadHandle::standby()
+status_t MmapThreadHandle::standby()
{
return mThread->standby();
}
-status_t AudioFlinger::MmapThreadHandle::reportData(const void* buffer, size_t frameCount) {
+status_t MmapThreadHandle::reportData(const void* buffer, size_t frameCount)
+{
return mThread->reportData(buffer, frameCount);
}
-AudioFlinger::MmapThread::MmapThread(
- const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+MmapThread::MmapThread(
+ const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady, bool isOut)
- : ThreadBase(audioFlinger, id, (isOut ? MMAP_PLAYBACK : MMAP_CAPTURE), systemReady, isOut),
+ : ThreadBase(afThreadCallback, id, (isOut ? MMAP_PLAYBACK : MMAP_CAPTURE), systemReady, isOut),
mSessionId(AUDIO_SESSION_NONE),
mPortId(AUDIO_PORT_HANDLE_NONE),
mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
@@ -9838,25 +10006,21 @@
readHalParameters_l();
}
-AudioFlinger::MmapThread::~MmapThread()
-{
-}
-
-void AudioFlinger::MmapThread::onFirstRef()
+void MmapThread::onFirstRef()
{
run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
}
-void AudioFlinger::MmapThread::disconnect()
+void MmapThread::disconnect()
{
- ActiveTracks<MmapTrack> activeTracks;
+ ActiveTracks<IAfMmapTrack> activeTracks;
{
- Mutex::Autolock _l(mLock);
- for (const sp<MmapTrack> &t : mActiveTracks) {
+ audio_utils::lock_guard _l(mutex());
+ for (const sp<IAfMmapTrack>& t : mActiveTracks) {
activeTracks.add(t);
}
}
- for (const sp<MmapTrack> &t : activeTracks) {
+ for (const sp<IAfMmapTrack>& t : activeTracks) {
stop(t->portId());
}
// This will decrement references and may cause the destruction of this thread.
@@ -9868,7 +10032,7 @@
}
-void AudioFlinger::MmapThread::configure(const audio_attributes_t *attr,
+void MmapThread::configure(const audio_attributes_t* attr,
audio_stream_type_t streamType __unused,
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
@@ -9882,7 +10046,7 @@
mPortId = portId;
}
-status_t AudioFlinger::MmapThread::createMmapBuffer(int32_t minSizeFrames,
+status_t MmapThread::createMmapBuffer(int32_t minSizeFrames,
struct audio_mmap_buffer_info *info)
{
if (mHalStream == 0) {
@@ -9892,7 +10056,7 @@
return mHalStream->createMmapBuffer(minSizeFrames, info);
}
-status_t AudioFlinger::MmapThread::getMmapPosition(struct audio_mmap_position *position)
+status_t MmapThread::getMmapPosition(struct audio_mmap_position* position) const
{
if (mHalStream == 0) {
return NO_INIT;
@@ -9900,7 +10064,7 @@
return mHalStream->getMmapPosition(position);
}
-status_t AudioFlinger::MmapThread::exitStandby_l()
+status_t MmapThread::exitStandby_l()
{
// The HAL must receive track metadata before starting the stream
updateMetadata_l();
@@ -9917,7 +10081,7 @@
return NO_ERROR;
}
-status_t AudioFlinger::MmapThread::start(const AudioClient& client,
+status_t MmapThread::start(const AudioClient& client,
const audio_attributes_t *attr,
audio_port_handle_t *handle)
{
@@ -9938,7 +10102,7 @@
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
audio_io_handle_t io = mId;
- AttributionSourceState adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ const AttributionSourceState adjAttributionSource = afutils::checkAttributionSourcePackage(
client.attributionSource);
if (isOutput()) {
@@ -9995,24 +10159,24 @@
{
// Add the track record before starting input so that the silent status for the
// client can be cached.
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
setClientSilencedState_l(portId, false /*silenced*/);
}
ret = AudioSystem::startInput(portId);
}
- Mutex::Autolock _l(mLock);
+ 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);
if (!mActiveTracks.isEmpty()) {
- mLock.unlock();
+ mutex().unlock();
if (isOutput()) {
AudioSystem::releaseOutput(portId);
} else {
AudioSystem::releaseInput(portId);
}
- mLock.lock();
+ mutex().lock();
} else {
mHalStream->stop();
}
@@ -10021,7 +10185,8 @@
}
// Given that MmapThread::mAttr is mutable, should a MmapTrack have attributes ?
- sp<MmapTrack> track = new MmapTrack(this, attr == nullptr ? mAttr : *attr, mSampleRate, mFormat,
+ sp<IAfMmapTrack> track = IAfMmapTrack::create(
+ this, attr == nullptr ? mAttr : *attr, mSampleRate, mFormat,
mChannelMask, mSessionId, isOutput(),
client.attributionSource,
IPCThreadState::self()->getCallingPid(), portId);
@@ -10033,7 +10198,7 @@
// force volume update when a new track is added
mHalVolFloat = -1.0f;
} else if (!track->isSilenced_l()) {
- for (const sp<MmapTrack> &t : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& t : mActiveTracks) {
if (t->isSilenced_l()
&& t->uid() != static_cast<uid_t>(client.attributionSource.uid)) {
t->invalidate();
@@ -10042,7 +10207,7 @@
}
mActiveTracks.add(track);
- sp<EffectChain> chain = getEffectChain_l(mSessionId);
+ sp<IAfEffectChain> chain = getEffectChain_l(mSessionId);
if (chain != 0) {
chain->setStrategy(getStrategyForStream(streamType()));
chain->incTrackCnt();
@@ -10063,7 +10228,7 @@
return ret;
}
-status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
+status_t MmapThread::stop(audio_port_handle_t handle)
{
ALOGV("%s handle %d", __FUNCTION__, handle);
@@ -10076,10 +10241,10 @@
return NO_ERROR;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
- sp<MmapTrack> track;
- for (const sp<MmapTrack> &t : mActiveTracks) {
+ sp<IAfMmapTrack> track;
+ for (const sp<IAfMmapTrack>& t : mActiveTracks) {
if (handle == t->portId()) {
track = t;
break;
@@ -10092,7 +10257,7 @@
mActiveTracks.remove(track);
eraseClientSilencedState_l(track->portId());
- mLock.unlock();
+ mutex().unlock();
if (isOutput()) {
AudioSystem::stopOutput(track->portId());
AudioSystem::releaseOutput(track->portId());
@@ -10100,9 +10265,9 @@
AudioSystem::stopInput(track->portId());
AudioSystem::releaseInput(track->portId());
}
- mLock.lock();
+ mutex().lock();
- sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+ sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
chain->decActiveTrackCnt();
chain->decTrackCnt();
@@ -10117,7 +10282,7 @@
return NO_ERROR;
}
-status_t AudioFlinger::MmapThread::standby()
+status_t MmapThread::standby()
{
ALOGV("%s", __FUNCTION__);
@@ -10137,12 +10302,12 @@
return NO_ERROR;
}
-status_t AudioFlinger::MmapThread::reportData(const void* /*buffer*/, size_t /*frameCount*/) {
+status_t MmapThread::reportData(const void* /*buffer*/, size_t /*frameCount*/) {
// This is a stub implementation. The MmapPlaybackThread overrides this function.
return INVALID_OPERATION;
}
-void AudioFlinger::MmapThread::readHalParameters_l()
+void MmapThread::readHalParameters_l()
{
status_t result = mHalStream->getAudioProperties(&mSampleRate, &mChannelMask, &mHALFormat);
LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving audio properties from HAL: %d", result);
@@ -10159,7 +10324,7 @@
// TODO: make a readHalParameters call?
mediametrics::LogItem item(mThreadMetrics.getMetricsId());
item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS)
- .set(AMEDIAMETRICS_PROP_ENCODING, formatToString(mFormat).c_str())
+ .set(AMEDIAMETRICS_PROP_ENCODING, IAfThreadBase::formatToString(mFormat).c_str())
.set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
.set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
.set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)mChannelCount)
@@ -10172,13 +10337,13 @@
(int32_t)mHapticChannelCount)
*/
.set(AMEDIAMETRICS_PROP_PREFIX_HAL AMEDIAMETRICS_PROP_ENCODING,
- formatToString(mHALFormat).c_str())
+ IAfThreadBase::formatToString(mHALFormat).c_str())
.set(AMEDIAMETRICS_PROP_PREFIX_HAL AMEDIAMETRICS_PROP_FRAMECOUNT,
(int32_t)mFrameCount) // sic - added HAL
.record();
}
-bool AudioFlinger::MmapThread::threadLoop()
+bool MmapThread::threadLoop()
{
checkSilentMode_l();
@@ -10186,10 +10351,10 @@
while (!exitPending())
{
- Vector< sp<EffectChain> > effectChains;
+ Vector<sp<IAfEffectChain>> effectChains;
{ // under Thread lock
- Mutex::Autolock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
if (mSignalPending) {
// A signal was raised while we were unlocked
@@ -10205,7 +10370,7 @@
// wait until we have something to do...
ALOGV("%s going to sleep", myName.c_str());
- mWaitWorkCV.wait(mLock);
+ mWaitWorkCV.wait(_l);
ALOGV("%s waking up", myName.c_str());
checkSilentMode_l();
@@ -10248,8 +10413,8 @@
return false;
}
-// checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MmapThread::checkForNewParameter_l(const String8& keyValuePair,
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
+bool MmapThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
AudioParameter param = AudioParameter(keyValuePair);
@@ -10267,9 +10432,9 @@
return false;
}
-String8 AudioFlinger::MmapThread::getParameters(const String8& keys)
+String8 MmapThread::getParameters(const String8& keys)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
String8 out_s8;
if (initCheck() == NO_ERROR && mHalStream->getParameters(keys, &out_s8) == OK) {
return out_s8;
@@ -10277,7 +10442,7 @@
return {};
}
-void AudioFlinger::MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId __unused) {
sp<AudioIoDescriptor> desc;
bool isInput = false;
@@ -10299,12 +10464,12 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAudioFlinger->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged(event, desc, pid);
}
-status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *patch,
+status_t MmapThread::createAudioPatch_l(const struct audio_patch* patch,
audio_patch_handle_t *handle)
-NO_THREAD_SAFETY_ANALYSIS // elease and re-acquire mLock
+NO_THREAD_SAFETY_ANALYSIS // elease and re-acquire mutex()
{
status_t status = NO_ERROR;
@@ -10380,9 +10545,9 @@
}
sp<MmapStreamCallback> callback = mCallback.promote();
if (mDeviceId != deviceId && callback != 0) {
- mLock.unlock();
+ mutex().unlock();
callback->onRoutingChanged(deviceId);
- mLock.lock();
+ mutex().lock();
}
mPatch = *patch;
mDeviceId = deviceId;
@@ -10393,7 +10558,7 @@
return status;
}
-status_t AudioFlinger::MmapThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
+status_t MmapThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
{
status_t status = NO_ERROR;
@@ -10415,7 +10580,7 @@
return status;
}
-void AudioFlinger::MmapThread::toAudioPortConfig(struct audio_port_config *config)
+void MmapThread::toAudioPortConfig(struct audio_port_config* config)
{
ThreadBase::toAudioPortConfig(config);
if (isOutput()) {
@@ -10429,14 +10594,14 @@
}
}
-status_t AudioFlinger::MmapThread::addEffectChain_l(const sp<EffectChain>& chain)
+status_t MmapThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
{
audio_session_t session = chain->sessionId();
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
// Attach all tracks with same session ID to this chain.
// indicate all active tracks in the chain
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
if (session == track->sessionId()) {
chain->incTrackCnt();
chain->incActiveTrackCnt();
@@ -10453,7 +10618,7 @@
return NO_ERROR;
}
-size_t AudioFlinger::MmapThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t MmapThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
{
audio_session_t session = chain->sessionId();
@@ -10464,7 +10629,7 @@
mEffectChains.removeAt(i);
// detach all active tracks from the chain
// detach all tracks with same session ID from this chain
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
if (session == track->sessionId()) {
chain->decActiveTrackCnt();
chain->decTrackCnt();
@@ -10476,29 +10641,29 @@
return mEffectChains.size();
}
-void AudioFlinger::MmapThread::threadLoop_standby()
+void MmapThread::threadLoop_standby()
{
mHalStream->standby();
}
-void AudioFlinger::MmapThread::threadLoop_exit()
+void MmapThread::threadLoop_exit()
{
// Do not call callback->onTearDown() because it is redundant for thread exit
// and because it can cause a recursive mutex lock on stop().
}
-status_t AudioFlinger::MmapThread::setSyncEvent(const sp<audioflinger::SyncEvent>& /* event */)
+status_t MmapThread::setSyncEvent(const sp<SyncEvent>& /* event */)
{
return BAD_VALUE;
}
-bool AudioFlinger::MmapThread::isValidSyncEvent(
- const sp<audioflinger::SyncEvent>& /* event */) const
+bool MmapThread::isValidSyncEvent(
+ const sp<SyncEvent>& /* event */) const
{
return false;
}
-status_t AudioFlinger::MmapThread::checkEffectCompatibility_l(
+status_t MmapThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
// No global effect sessions on mmap threads
@@ -10524,7 +10689,7 @@
return BAD_VALUE;
}
- if (EffectModule::isHapticGenerator(&desc->type)) {
+ if (IAfEffectModule::isHapticGenerator(&desc->type)) {
ALOGE("%s(): HapticGenerator is not supported for MmapThread", __func__);
return BAD_VALUE;
}
@@ -10532,11 +10697,11 @@
return NO_ERROR;
}
-void AudioFlinger::MmapThread::checkInvalidTracks_l()
-NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
+void MmapThread::checkInvalidTracks_l()
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mutex()
{
sp<MmapStreamCallback> callback;
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
if (track->isInvalid()) {
callback = mCallback.promote();
if (callback == nullptr && mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
@@ -10547,13 +10712,13 @@
}
}
if (callback != 0) {
- mLock.unlock();
+ mutex().unlock();
callback->onRoutingChanged(AUDIO_PORT_HANDLE_NONE);
- mLock.lock();
+ mutex().lock();
}
}
-void AudioFlinger::MmapThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
+void MmapThread::dumpInternals_l(int fd, const Vector<String16>& /* args */)
{
dprintf(fd, " Attributes: content type %d usage %d source %d\n",
mAttr.content_type, mAttr.usage, mAttr.source);
@@ -10563,7 +10728,7 @@
}
}
-void AudioFlinger::MmapThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
+void MmapThread::dumpTracks_l(int fd, const Vector<String16>& /* args */)
{
String8 result;
size_t numtracks = mActiveTracks.size();
@@ -10573,7 +10738,7 @@
result.append(prefix);
mActiveTracks[0]->appendDumpHeader(result);
for (size_t i = 0; i < numtracks ; ++i) {
- sp<MmapTrack> track = mActiveTracks[i];
+ sp<IAfMmapTrack> track = mActiveTracks[i];
result.append(prefix);
track->appendDump(result, true /* active */);
}
@@ -10583,10 +10748,17 @@
write(fd, result.c_str(), result.size());
}
-AudioFlinger::MmapPlaybackThread::MmapPlaybackThread(
- const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+/* static */
+sp<IAfMmapPlaybackThread> IAfMmapPlaybackThread::create(
+ const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
+ AudioHwDevice* hwDev, AudioStreamOut* output, bool systemReady) {
+ return sp<MmapPlaybackThread>::make(afThreadCallback, id, hwDev, output, systemReady);
+}
+
+MmapPlaybackThread::MmapPlaybackThread(
+ const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady)
- : MmapThread(audioFlinger, id, hwDev, output->stream, systemReady, true /* isOut */),
+ : MmapThread(afThreadCallback, id, hwDev, output->stream, systemReady, true /* isOut */),
mStreamType(AUDIO_STREAM_MUSIC),
mStreamVolume(1.0),
mStreamMute(false),
@@ -10594,8 +10766,8 @@
{
snprintf(mThreadName, kThreadNameLength, "AudioMmapOut_%X", id);
mChannelCount = audio_channel_count_from_out_mask(mChannelMask);
- mMasterVolume = audioFlinger->masterVolume_l();
- mMasterMute = audioFlinger->masterMute_l();
+ mMasterVolume = afThreadCallback->masterVolume_l();
+ mMasterMute = afThreadCallback->masterMute_l();
if (mAudioHwDev) {
if (mAudioHwDev->canSetMasterVolume()) {
mMasterVolume = 1.0;
@@ -10607,7 +10779,7 @@
}
}
-void AudioFlinger::MmapPlaybackThread::configure(const audio_attributes_t *attr,
+void MmapPlaybackThread::configure(const audio_attributes_t* attr,
audio_stream_type_t streamType,
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
@@ -10618,17 +10790,17 @@
mStreamType = streamType;
}
-AudioStreamOut* AudioFlinger::MmapPlaybackThread::clearOutput()
+AudioStreamOut* MmapPlaybackThread::clearOutput()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioStreamOut *output = mOutput;
mOutput = NULL;
return output;
}
-void AudioFlinger::MmapPlaybackThread::setMasterVolume(float value)
+void MmapPlaybackThread::setMasterVolume(float value)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Don't apply master volume in SW if our HAL can do it for us.
if (mAudioHwDev &&
mAudioHwDev->canSetMasterVolume()) {
@@ -10638,9 +10810,9 @@
}
}
-void AudioFlinger::MmapPlaybackThread::setMasterMute(bool muted)
+void MmapPlaybackThread::setMasterMute(bool muted)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Don't apply master mute in SW if our HAL can do it for us.
if (mAudioHwDev && mAudioHwDev->canSetMasterMute()) {
mMasterMute = false;
@@ -10649,49 +10821,49 @@
}
}
-void AudioFlinger::MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (stream == mStreamType) {
mStreamVolume = value;
broadcast_l();
}
}
-float AudioFlinger::MmapPlaybackThread::streamVolume(audio_stream_type_t stream) const
+float MmapPlaybackThread::streamVolume(audio_stream_type_t stream) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (stream == mStreamType) {
return mStreamVolume;
}
return 0.0f;
}
-void AudioFlinger::MmapPlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
+void MmapPlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (stream == mStreamType) {
mStreamMute= muted;
broadcast_l();
}
}
-void AudioFlinger::MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (streamType == mStreamType) {
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
track->invalidate();
}
broadcast_l();
}
}
-void AudioFlinger::MmapPlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds)
+void MmapPlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
bool trackMatch = false;
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
if (portIds.find(track->portId()) != portIds.end()) {
track->invalidate();
trackMatch = true;
@@ -10706,7 +10878,7 @@
}
}
-void AudioFlinger::MmapPlaybackThread::processVolume_l()
+void MmapPlaybackThread::processVolume_l()
NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
{
float volume;
@@ -10738,9 +10910,9 @@
if (callback != 0) {
mHalVolFloat = volume; // SW volume control worked, so update value.
mNoCallbackWarningCount = 0;
- mLock.unlock();
+ mutex().unlock();
callback->onVolumeChanged(volume);
- mLock.lock();
+ mutex().lock();
} else {
if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
ALOGW("Could not set MMAP stream volume: no volume callback!");
@@ -10748,9 +10920,9 @@
}
}
}
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
track->setMetadataHasChanged();
- track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{mMasterMute,
mStreamVolume == 0.f,
mStreamMute,
@@ -10762,13 +10934,13 @@
}
}
-AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::MmapPlaybackThread::updateMetadata_l()
+ThreadBase::MetadataUpdate MmapPlaybackThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
return {}; // nothing to do
}
StreamOutHalInterface::SourceMetadata metadata;
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
playback_track_metadata_v7_t trackMetadata;
trackMetadata.base = {
@@ -10787,7 +10959,7 @@
return change;
};
-void AudioFlinger::MmapPlaybackThread::checkSilentMode_l()
+void MmapPlaybackThread::checkSilentMode_l()
{
if (!mMasterMute) {
char value[PROPERTY_VALUE_MAX];
@@ -10804,7 +10976,7 @@
}
}
-void AudioFlinger::MmapPlaybackThread::toAudioPortConfig(struct audio_port_config *config)
+void MmapPlaybackThread::toAudioPortConfig(struct audio_port_config* config)
{
MmapThread::toAudioPortConfig(config);
if (mOutput && mOutput->flags != AUDIO_OUTPUT_FLAG_NONE) {
@@ -10813,8 +10985,8 @@
}
}
-status_t AudioFlinger::MmapPlaybackThread::getExternalPosition(uint64_t *position,
- int64_t *timeNanos)
+status_t MmapPlaybackThread::getExternalPosition(uint64_t* position,
+ int64_t* timeNanos) const
{
if (mOutput == nullptr) {
return NO_INIT;
@@ -10827,7 +10999,7 @@
return status;
}
-status_t AudioFlinger::MmapPlaybackThread::reportData(const void* buffer, size_t frameCount) {
+status_t MmapPlaybackThread::reportData(const void* buffer, size_t frameCount) {
// Send to MelProcessor for sound dose measurement.
auto processor = mMelProcessor.load();
if (processor) {
@@ -10837,8 +11009,8 @@
return NO_ERROR;
}
-// startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MmapPlaybackThread::startMelComputation_l(
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
+void MmapPlaybackThread::startMelComputation_l(
const sp<audio_utils::MelProcessor>& processor)
{
ALOGV("%s: starting mel processor for thread %d", __func__, id());
@@ -10851,8 +11023,8 @@
// assigned constant for each thread
}
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MmapPlaybackThread::stopMelComputation_l()
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
+void MmapPlaybackThread::stopMelComputation_l()
{
ALOGV("%s: pausing mel processor for thread %d", __func__, id());
auto melProcessor = mMelProcessor.load();
@@ -10861,7 +11033,7 @@
}
}
-void AudioFlinger::MmapPlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void MmapPlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
MmapThread::dumpInternals_l(fd, args);
@@ -10870,17 +11042,24 @@
dprintf(fd, " Master volume: %f Master mute %d\n", mMasterVolume, mMasterMute);
}
-AudioFlinger::MmapCaptureThread::MmapCaptureThread(
- const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+/* static */
+sp<IAfMmapCaptureThread> IAfMmapCaptureThread::create(
+ const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
+ AudioHwDevice* hwDev, AudioStreamIn* input, bool systemReady) {
+ return sp<MmapCaptureThread>::make(afThreadCallback, id, hwDev, input, systemReady);
+}
+
+MmapCaptureThread::MmapCaptureThread(
+ const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice *hwDev, AudioStreamIn *input, bool systemReady)
- : MmapThread(audioFlinger, id, hwDev, input->stream, systemReady, false /* isOut */),
+ : MmapThread(afThreadCallback, id, hwDev, input->stream, systemReady, false /* isOut */),
mInput(input)
{
snprintf(mThreadName, kThreadNameLength, "AudioMmapIn_%X", id);
mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
}
-status_t AudioFlinger::MmapCaptureThread::exitStandby_l()
+status_t MmapCaptureThread::exitStandby_l()
{
{
// mInput might have been cleared by clearInput()
@@ -10891,16 +11070,15 @@
return MmapThread::exitStandby_l();
}
-AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
+AudioStreamIn* MmapCaptureThread::clearInput()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioStreamIn *input = mInput;
mInput = NULL;
return input;
}
-
-void AudioFlinger::MmapCaptureThread::processVolume_l()
+void MmapCaptureThread::processVolume_l()
{
bool changed = false;
bool silenced = false;
@@ -10927,13 +11105,13 @@
}
}
-AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::MmapCaptureThread::updateMetadata_l()
+ThreadBase::MetadataUpdate MmapCaptureThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
return {}; // nothing to do
}
StreamInHalInterface::SinkMetadata metadata;
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
// No track is invalid as this is called after prepareTrack_l in the same critical section
record_track_metadata_v7_t trackMetadata;
trackMetadata.base = {
@@ -10950,9 +11128,9 @@
return change;
}
-void AudioFlinger::MmapCaptureThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
+void MmapCaptureThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mActiveTracks.size() ; i++) {
if (mActiveTracks[i]->portId() == portId) {
mActiveTracks[i]->setSilenced_l(silenced);
@@ -10962,7 +11140,7 @@
setClientSilencedIfExists_l(portId, silenced);
}
-void AudioFlinger::MmapCaptureThread::toAudioPortConfig(struct audio_port_config *config)
+void MmapCaptureThread::toAudioPortConfig(struct audio_port_config* config)
{
MmapThread::toAudioPortConfig(config);
if (mInput && mInput->flags != AUDIO_INPUT_FLAG_NONE) {
@@ -10971,8 +11149,8 @@
}
}
-status_t AudioFlinger::MmapCaptureThread::getExternalPosition(
- uint64_t *position, int64_t *timeNanos)
+status_t MmapCaptureThread::getExternalPosition(
+ uint64_t* position, int64_t* timeNanos) const
{
if (mInput == nullptr) {
return NO_INIT;
@@ -10982,12 +11160,19 @@
// ----------------------------------------------------------------------------
-AudioFlinger::BitPerfectThread::BitPerfectThread(const sp<AudioFlinger> &audioflinger,
- AudioStreamOut *output, audio_io_handle_t id, bool systemReady)
- : MixerThread(audioflinger, output, id, systemReady, BIT_PERFECT) {}
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createBitPerfectThread(
+ const sp<IAfThreadCallback>& afThreadCallback,
+ AudioStreamOut* output, audio_io_handle_t id, bool systemReady) {
+ return sp<BitPerfectThread>::make(afThreadCallback, output, id, systemReady);
+}
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::BitPerfectThread::prepareTracks_l(
- Vector<sp<Track>> *tracksToRemove) {
+BitPerfectThread::BitPerfectThread(const sp<IAfThreadCallback> &afThreadCallback,
+ AudioStreamOut *output, audio_io_handle_t id, bool systemReady)
+ : MixerThread(afThreadCallback, output, id, systemReady, BIT_PERFECT) {}
+
+PlaybackThread::mixer_state BitPerfectThread::prepareTracks_l(
+ Vector<sp<IAfTrack>>* tracksToRemove) {
mixer_state result = MixerThread::prepareTracks_l(tracksToRemove);
// If there is only one active track and it is bit-perfect, enable tee buffer.
float volumeLeft = 1.0f;
@@ -11019,7 +11204,7 @@
return result;
}
-void AudioFlinger::BitPerfectThread::threadLoop_mix() {
+void BitPerfectThread::threadLoop_mix() {
MixerThread::threadLoop_mix();
mHasDataCopiedToSinkBuffer = mIsBitPerfect;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 6795a13..3105ad7 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -15,37 +15,43 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
-class ThreadBase : public Thread {
+// ADD_BATTERY_DATA AUDIO_WATCHDOG FAST_THREAD_STATISTICS STATE_QUEUE_DUMP TEE_SINK
+#include "Configuration.h"
+#include "IAfThread.h"
+#include "IAfTrack.h"
+
+#include <android-base/macros.h> // DISALLOW_COPY_AND_ASSIGN
+#include <android/os/IPowerManager.h>
+#include <afutils/AudioWatchdog.h>
+#include <afutils/NBAIO_Tee.h>
+#include <audio_utils/Balance.h>
+#include <audio_utils/SimpleLog.h>
+#include <datapath/ThreadMetrics.h>
+#include <fastpath/FastCapture.h>
+#include <fastpath/FastMixer.h>
+#include <mediautils/Synchronization.h>
+#include <mediautils/ThreadSnapshot.h>
+#include <timing/MonotonicFrameCounter.h>
+#include <utils/Log.h>
+
+namespace android {
+
+class AsyncCallbackThread;
+
+class ThreadBase : public virtual IAfThreadBase, public Thread {
public:
-
-#include "TrackBase.h"
-
- enum type_t {
- MIXER, // Thread class is MixerThread
- DIRECT, // Thread class is DirectOutputThread
- DUPLICATING, // Thread class is DuplicatingThread
- RECORD, // Thread class is RecordThread
- OFFLOAD, // Thread class is OffloadThread
- MMAP_PLAYBACK, // Thread class for MMAP playback stream
- MMAP_CAPTURE, // Thread class for MMAP capture stream
- SPATIALIZER, //
- BIT_PERFECT, // Thread class for BitPerfectThread
- // If you add any values here, also update ThreadBase::threadTypeToString()
- };
-
static const char *threadTypeToString(type_t type);
- ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+ IAfThreadCallback* afThreadCallback() const final { return mAfThreadCallback.get(); }
+
+ ThreadBase(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
type_t type, bool systemReady, bool isOut);
- virtual ~ThreadBase();
+ ~ThreadBase() override;
- virtual status_t readyToRun();
-
- void clearPowerManager();
+ status_t readyToRun() final;
+ void clearPowerManager() final;
// base for record and playback
enum {
@@ -71,26 +77,24 @@
// Config event sequence by client if status needed (e.g binder thread calling setParameters()):
// 1. create SetParameterConfigEvent. This sets mWaitStatus in config event
- // 2. Lock mLock
+ // 2. Lock mutex()
// 3. Call sendConfigEvent_l(): Append to mConfigEvents and mWaitWorkCV.signal
// 4. sendConfigEvent_l() reads status from event->mStatus;
// 5. sendConfigEvent_l() returns status
// 6. Unlock
//
// Parameter sequence by server: threadLoop calling processConfigEvents_l():
- // 1. Lock mLock
+ // 1. Lock mutex()
// 2. If there is an entry in mConfigEvents proceed ...
// 3. Read first entry in mConfigEvents
// 4. Remove first entry from mConfigEvents
// 5. Process
// 6. Set event->mStatus
- // 7. event->mCond.signal
+ // 7. event->mCondition.notify_one()
// 8. Unlock
class ConfigEvent: public RefBase {
public:
- virtual ~ConfigEvent() {}
-
void dump(char *buffer, size_t size) {
snprintf(buffer, size, "Event type: %d\n", mType);
if (mData != nullptr) {
@@ -99,9 +103,10 @@
}
}
+ audio_utils::mutex& mutex() const { return mMutex; }
const int mType; // event type e.g. CFG_EVENT_IO
- Mutex mLock; // mutex associated with mCond
- Condition mCond; // condition for status return
+ mutable audio_utils::mutex mMutex; // mutex associated with mCondition
+ audio_utils::condition_variable mCondition; // condition for status return
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
@@ -134,7 +139,6 @@
ConfigEvent(CFG_EVENT_IO) {
mData = new IoConfigEventData(event, pid, portId);
}
- virtual ~IoConfigEvent() {}
};
class PrioConfigEventData : public ConfigEventData {
@@ -159,7 +163,6 @@
ConfigEvent(CFG_EVENT_PRIO, true) {
mData = new PrioConfigEventData(pid, tid, prio, forApp);
}
- virtual ~PrioConfigEvent() {}
};
class SetParameterConfigEventData : public ConfigEventData {
@@ -181,7 +184,6 @@
mData = new SetParameterConfigEventData(keyValuePairs);
mWaitStatus = true;
}
- virtual ~SetParameterConfigEvent() {}
};
class CreateAudioPatchConfigEventData : public ConfigEventData {
@@ -206,7 +208,6 @@
mData = new CreateAudioPatchConfigEventData(patch, handle);
mWaitStatus = true;
}
- virtual ~CreateAudioPatchConfigEvent() {}
};
class ReleaseAudioPatchConfigEventData : public ConfigEventData {
@@ -228,7 +229,6 @@
mData = new ReleaseAudioPatchConfigEventData(handle);
mWaitStatus = true;
}
- virtual ~ReleaseAudioPatchConfigEvent() {}
};
class UpdateOutDevicesConfigEventData : public ConfigEventData {
@@ -249,8 +249,6 @@
ConfigEvent(CFG_EVENT_UPDATE_OUT_DEVICE) {
mData = new UpdateOutDevicesConfigEventData(outDevices);
}
-
- virtual ~UpdateOutDevicesConfigEvent();
};
class ResizeBufferConfigEventData : public ConfigEventData {
@@ -271,8 +269,6 @@
ConfigEvent(CFG_EVENT_RESIZE_BUFFER) {
mData = new ResizeBufferConfigEventData(maxSharedAudioHistoryMs);
}
-
- virtual ~ResizeBufferConfigEvent() {}
};
class CheckOutputStageEffectsEvent : public ConfigEvent {
@@ -280,8 +276,6 @@
CheckOutputStageEffectsEvent() :
ConfigEvent(CFG_EVENT_CHECK_OUTPUT_STAGE_EFFECTS) {
}
-
- virtual ~CheckOutputStageEffectsEvent() {}
};
class HalLatencyModesChangedEvent : public ConfigEvent {
@@ -289,8 +283,6 @@
HalLatencyModesChangedEvent() :
ConfigEvent(CFG_EVENT_HAL_LATENCY_MODES_CHANGED) {
}
-
- virtual ~HalLatencyModesChangedEvent() {}
};
@@ -308,109 +300,88 @@
wp<ThreadBase> mThread;
};
- virtual status_t initCheck() const = 0;
+ type_t type() const final { return mType; }
+ bool isDuplicating() const final { return (mType == DUPLICATING); }
+ audio_io_handle_t id() const final { return mId;}
- // static externally-visible
- type_t type() const { return mType; }
- bool isDuplicating() const { return (mType == DUPLICATING); }
-
- audio_io_handle_t id() const { return mId;}
-
- // dynamic externally-visible
- uint32_t sampleRate() const { return mSampleRate; }
- audio_channel_mask_t channelMask() const { return mChannelMask; }
- virtual audio_channel_mask_t mixerChannelMask() const { return mChannelMask; }
-
- audio_format_t format() const { return mHALFormat; }
- uint32_t channelCount() const { return mChannelCount; }
-
- // Called by AudioFlinger::frameCount(audio_io_handle_t output) and effects,
- // and returns the [normal mix] buffer's frame count.
- virtual size_t frameCount() const = 0;
- virtual audio_channel_mask_t hapticChannelMask() const { return AUDIO_CHANNEL_NONE; }
- virtual uint32_t latency_l() const { return 0; }
- virtual void setVolumeForOutput_l(float left __unused, float right __unused) const {}
+ uint32_t sampleRate() const final { return mSampleRate; }
+ audio_channel_mask_t channelMask() const final { return mChannelMask; }
+ audio_channel_mask_t mixerChannelMask() const override { return mChannelMask; }
+ audio_format_t format() const final { return mHALFormat; }
+ 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 {}
// Return's the HAL's frame count i.e. fast mixer buffer size.
- size_t frameCountHAL() const { return mFrameCount; }
-
- size_t frameSize() const { return mFrameSize; }
+ size_t frameCountHAL() const final { return mFrameCount; }
+ size_t frameSize() const final { return mFrameSize; }
// Should be "virtual status_t requestExitAndWait()" and override same
// method in Thread, but Thread::requestExitAndWait() is not yet virtual.
- void exit();
- virtual bool checkForNewParameter_l(const String8& keyValuePair,
- status_t& status) = 0;
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys) = 0;
- virtual void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
- // sendConfigEvent_l() must be called with ThreadBase::mLock held
+ void exit() final;
+ status_t setParameters(const String8& keyValuePairs) final;
+
+ // 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);
- void sendIoConfigEvent(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
- void sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
- void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp);
- void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp);
- status_t sendSetParameterConfigEvent_l(const String8& keyValuePair);
- status_t sendCreateAudioPatchConfigEvent(const struct audio_patch *patch,
- audio_patch_handle_t *handle);
- status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle);
- status_t sendUpdateOutDeviceConfigEvent(
- const DeviceDescriptorBaseVector& outDevices);
- void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs);
- void sendCheckOutputStageEffectsEvent();
- void sendCheckOutputStageEffectsEvent_l();
- void sendHalLatencyModesChangedEvent_l();
+ status_t sendConfigEvent_l(sp<ConfigEvent>& event);
+ void sendIoConfigEvent(audio_io_config_event_t event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
+ 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;
+ status_t sendCreateAudioPatchConfigEvent(const struct audio_patch* patch,
+ audio_patch_handle_t* handle) final;
+ status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) final;
+ 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;
- void processConfigEvents_l();
- virtual void setCheckOutputStageEffects() {}
- virtual void cacheParameters_l() = 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);
- virtual void toAudioPortConfig(struct audio_port_config *config) = 0;
+ void processConfigEvents_l() final;
+ void setCheckOutputStageEffects() override {}
+ void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
+ void toAudioPortConfig(struct audio_port_config* config) override;
+ void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override;
- virtual void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs);
+ // see note at declaration of mStandby, mOutDevice and mInDevice
+ bool inStandby() const override { return mStandby; }
+ const DeviceTypeSet outDeviceTypes() const final {
+ return getAudioDeviceTypes(mOutDeviceTypeAddrs);
+ }
+ audio_devices_t inDeviceType() const final { return mInDeviceTypeAddr.mType; }
+ DeviceTypeSet getDeviceTypes() const final {
+ return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
+ }
- // see note at declaration of mStandby, mOutDevice and mInDevice
- bool standby() const { return mStandby; }
- const DeviceTypeSet outDeviceTypes() const {
- return getAudioDeviceTypes(mOutDeviceTypeAddrs);
- }
- audio_devices_t inDeviceType() const { return mInDeviceTypeAddr.mType; }
- DeviceTypeSet getDeviceTypes() const {
- return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
- }
+ const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const final {
+ return mOutDeviceTypeAddrs;
+ }
+ const AudioDeviceTypeAddr& inDeviceTypeAddr() const final {
+ return mInDeviceTypeAddr;
+ }
- const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const {
- return mOutDeviceTypeAddrs;
- }
- const AudioDeviceTypeAddr& inDeviceTypeAddr() const {
- return mInDeviceTypeAddr;
- }
+ bool isOutput() const final { return mIsOut; }
- bool isOutput() const { return mIsOut; }
+ bool isOffloadOrMmap() const final {
+ switch (mType) {
+ case OFFLOAD:
+ case MMAP_PLAYBACK:
+ case MMAP_CAPTURE:
+ return true;
+ default:
+ return false;
+ }
+ }
- bool isOffloadOrMmap() const {
- switch (mType) {
- case OFFLOAD:
- case MMAP_PLAYBACK:
- case MMAP_CAPTURE:
- return true;
- default:
- return false;
- }
- }
-
- virtual sp<StreamHalInterface> stream() const = 0;
-
- sp<EffectHandle> createEffect_l(
- const sp<AudioFlinger::Client>& client,
+ sp<IAfEffectHandle> createEffect_l(
+ const sp<Client>& client,
const sp<media::IEffectClient>& effectClient,
int32_t priority,
audio_session_t sessionId,
@@ -419,7 +390,8 @@
status_t *status /*non-NULL*/,
bool pinned,
bool probe,
- bool notifyFramesProcessed);
+ bool notifyFramesProcessed) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
// return values for hasAudioSession (bit field)
enum effect_state {
@@ -435,48 +407,42 @@
// bit-perfect track
};
- // get effect chain corresponding to session Id.
- sp<EffectChain> getEffectChain(audio_session_t sessionId);
- // same as getEffectChain() but must be called with ThreadBase mutex locked
- sp<EffectChain> getEffectChain_l(audio_session_t sessionId) const;
- std::vector<int> getEffectIds_l(audio_session_t sessionId);
- // add an effect chain to the chain list (mEffectChains)
- virtual status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
- // remove an effect chain from the chain list (mEffectChains)
- virtual size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0;
+ // 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;
+
// 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<EffectChain> >& effectChains);
+ void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) final;
// unlock effect chains after process
- void unlockEffectChains(const Vector< sp<EffectChain> >& effectChains);
+ void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) final;
// get a copy of mEffectChains vector
- Vector< sp<EffectChain> > getEffectChains_l() const { return mEffectChains; };
+ Vector<sp<IAfEffectChain>> getEffectChains_l() const final { return mEffectChains; };
// set audio mode to all effect chains
- void setMode(audio_mode_t mode);
+ void setMode(audio_mode_t mode) final;
// get effect module with corresponding ID on specified audio session
- sp<AudioFlinger::EffectModule> getEffect(audio_session_t sessionId, int effectId);
- sp<AudioFlinger::EffectModule> getEffect_l(audio_session_t sessionId, int effectId);
+ sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const final;
+ sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const final;
// 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
- status_t addEffect_l(const sp< EffectModule>& effect);
+ status_t addEffect_ll(const sp<IAfEffectModule>& effect) final
+ 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< EffectModule>& effect, bool release = false);
+ void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) final;
// disconnect an effect handle from module and destroy module if last handle
- void disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast);
+ void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast) final;
// detach all tracks connected to an auxiliary effect
- virtual void detachAuxEffect_l(int effectId __unused) {}
- // 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;
- uint32_t hasAudioSession(audio_session_t sessionId) const {
- Mutex::Autolock _l(mLock);
+ void detachAuxEffect_l(int /* effectId */) override {}
+ // 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);
}
@@ -487,7 +453,7 @@
result = EFFECT_SESSION;
}
for (size_t i = 0; i < tracks.size(); ++i) {
- const sp<TrackBase>& track = tracks[i];
+ const sp<IAfTrackBase>& track = tracks[i];
if (sessionId == track->sessionId()
&& !track->isInvalid() // not yet removed from tracks.
&& !track->isTerminated()) {
@@ -509,19 +475,17 @@
// 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 __unused) {
+ product_strategy_t getStrategyForSession_l(
+ audio_session_t /* sessionId */) const override {
return static_cast<product_strategy_t>(0);
}
// check if some effects must be suspended/restored when an effect is enabled
// or disabled
- void checkSuspendOnEffectEnabled(bool enabled,
+ void checkSuspendOnEffectEnabled(bool enabled,
audio_session_t sessionId,
- bool threadLocked);
+ bool threadLocked) final;
- virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
- 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
// objects that will be read-only to client processes, read/write to mediaserver,
@@ -529,37 +493,36 @@
// The heap is per-thread rather than common across all threads, because
// clients can't be trusted not to modify the offset of the IMemory they receive.
// If a thread does not have such a heap, this method returns 0.
- virtual sp<MemoryDealer> readOnlyHeap() const { return 0; }
+ sp<MemoryDealer> readOnlyHeap() const override { return nullptr; }
- virtual sp<IMemory> pipeMemory() const { return 0; }
+ sp<IMemory> pipeMemory() const override { return nullptr; }
- void systemReady();
+ void systemReady() final;
- // checkEffectCompatibility_l() must be called with ThreadBase::mLock held
- virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
- audio_session_t sessionId) = 0;
+ void broadcast_l() final;
- void broadcast_l();
+ bool isTimestampCorrectionEnabled() const override { return false; }
- virtual bool isTimestampCorrectionEnabled() const { return false; }
+ bool isMsdDevice() const final { return mIsMsdDevice; }
- bool isMsdDevice() const { return mIsMsdDevice; }
-
- void dump(int fd, const Vector<String16>& args);
+ void dump(int fd, const Vector<String16>& args) override;
// deliver stats to mediametrics.
- void sendStatistics(bool force);
+ void sendStatistics(bool force) final;
- mutable Mutex mLock;
+ audio_utils::mutex& mutex() const final RETURN_CAPABILITY(audio_utils::ThreadBase_Mutex) {
+ return mMutex;
+ }
+ mutable audio_utils::mutex mMutex;
- void onEffectEnable(const sp<EffectModule>& effect);
- void onEffectDisable();
+ void onEffectEnable(const sp<IAfEffectModule>& effect) final;
+ void onEffectDisable() final;
- // invalidateTracksForAudioSession_l must be called with holding mLock.
- virtual void invalidateTracksForAudioSession_l(audio_session_t sessionId __unused) const { }
+ // invalidateTracksForAudioSession_l must be called with holding mutex().
+ void invalidateTracksForAudioSession_l(audio_session_t /* sessionId */) const override {}
// Invalidate all the tracks with the given audio session.
- void invalidateTracksForAudioSession(audio_session_t sessionId) const {
- Mutex::Autolock _l(mLock);
+ void invalidateTracksForAudioSession(audio_session_t sessionId) const final {
+ std::lock_guard _l(mutex());
invalidateTracksForAudioSession_l(sessionId);
}
@@ -567,17 +530,17 @@
void invalidateTracksForAudioSession_l(audio_session_t sessionId,
const T& tracks) const {
for (size_t i = 0; i < tracks.size(); ++i) {
- const sp<TrackBase>& track = tracks[i];
+ const sp<IAfTrackBase>& track = tracks[i];
if (sessionId == track->sessionId()) {
track->invalidate();
}
}
}
- virtual bool isStreamInitialized() = 0;
-
- virtual void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor);
- virtual void stopMelComputation_l();
+ void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void stopMelComputation_l() override
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
protected:
@@ -601,13 +564,13 @@
// occurs when all suspend requests are cancelled.
void setEffectSuspended_l(const effect_uuid_t *type,
bool suspend,
- audio_session_t sessionId);
+ audio_session_t sessionId) final;
// updated mSuspendedSessions when an effect is suspended or restored
void updateSuspendedSessions_l(const effect_uuid_t *type,
bool suspend,
audio_session_t sessionId);
// check if some effects must be suspended when an effect chain is added
- void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain);
+ void checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain);
// sends the metadata of the active tracks to the HAL
struct MetadataUpdate {
@@ -627,8 +590,10 @@
ExtendedTimestamp *timestamp __unused) const {
return INVALID_OPERATION;
}
-
+public:
+// TODO(b/291317898) organize with publics
product_strategy_t getStrategyForStream(audio_stream_type_t stream) const;
+protected:
virtual void onHalLatencyModesChanged_l() {}
@@ -636,15 +601,12 @@
{ }
virtual void dumpTracks_l(int fd __unused, const Vector<String16>& args __unused) { }
-
- friend class AudioFlinger; // for mEffectChains and mAudioManager
-
const type_t mType;
// Used by parameters, config events, addTrack_l, exit
- Condition mWaitWorkCV;
+ audio_utils::condition_variable mWaitWorkCV;
- const sp<AudioFlinger> mAudioFlinger;
+ const sp<IAfThreadCallback> mAfThreadCallback;
ThreadMetrics mThreadMetrics;
const bool mIsOut;
@@ -680,7 +642,7 @@
audio_source_t mAudioSource;
const audio_io_handle_t mId;
- Vector< sp<EffectChain> > mEffectChains;
+ Vector<sp<IAfEffectChain>> mEffectChains;
static const int kThreadNameLength = 16; // prctl(PR_SET_NAME) limit
char mThreadName[kThreadNameLength]; // guaranteed NUL-terminated
@@ -781,7 +743,7 @@
bool isEmpty() const {
return mActiveTracks.isEmpty();
}
- ssize_t indexOf(const sp<T>& item) {
+ ssize_t indexOf(const sp<T>& item) const {
return mActiveTracks.indexOf(item);
}
sp<T> operator[](size_t index) const {
@@ -844,35 +806,14 @@
void dumpEffectChains_l(int fd, const Vector<String16>& args);
};
-class VolumeInterface {
- public:
-
- virtual ~VolumeInterface() {}
-
- virtual void setMasterVolume(float value) = 0;
- virtual void setMasterMute(bool muted) = 0;
- virtual void setStreamVolume(audio_stream_type_t stream, float value) = 0;
- virtual void setStreamMute(audio_stream_type_t stream, bool muted) = 0;
- virtual float streamVolume(audio_stream_type_t stream) const = 0;
-
-};
-
// --- PlaybackThread ---
-class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback,
- public VolumeInterface, public StreamOutHalInterfaceEventCallback {
+class PlaybackThread : public ThreadBase, public virtual IAfPlaybackThread,
+ public StreamOutHalInterfaceCallback,
+ public virtual VolumeInterface, public StreamOutHalInterfaceEventCallback {
public:
-
-#include "PlaybackTracks.h"
-
- enum mixer_state {
- MIXER_IDLE, // no active tracks
- MIXER_TRACKS_ENABLED, // at least one active track, but no track has any data ready
- MIXER_TRACKS_READY, // at least one active track, and at least one track has data
- MIXER_DRAIN_TRACK, // drain currently playing track
- MIXER_DRAIN_ALL, // fully drain the hardware
- // standby mode does not have an enum value
- // suspend by audio policy manager is orthogonal to mixer state
- };
+ sp<IAfPlaybackThread> asIAfPlaybackThread() final {
+ return sp<IAfPlaybackThread>::fromExisting(this);
+ }
// retry count before removing active track in case of underrun on offloaded thread:
// we need to make sure that AudioTrack client has enough time to send large buffers
@@ -880,7 +821,6 @@
// handled for offloaded tracks
static const int8_t kMaxTrackRetriesOffload = 20;
static const int8_t kMaxTrackStartupRetriesOffload = 100;
- static const int8_t kMaxTrackStopRetriesOffload = 2;
static constexpr uint32_t kMaxTracksPerUid = 40;
static constexpr size_t kMaxTracks = 256;
@@ -890,19 +830,23 @@
// for initial conditions or large delays.
static const nsecs_t kMaxNextBufferDelayNs = 100000000;
- PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+ PlaybackThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
audio_io_handle_t id, type_t type, bool systemReady,
audio_config_base_t *mixerConfig = nullptr);
- virtual ~PlaybackThread();
+ ~PlaybackThread() override;
// Thread virtuals
- virtual bool threadLoop();
+ bool threadLoop() final;
// RefBase
- virtual void onFirstRef();
+ void onFirstRef() override;
- virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
- audio_session_t sessionId);
+ status_t checkEffectCompatibility_l(
+ const effect_descriptor_t* desc, audio_session_t sessionId) final;
+
+ void addOutputTrack_l(const sp<IAfTrack>& track) final {
+ mTracks.add(track);
+ }
protected:
// Code snippets that were lifted up out of threadLoop()
@@ -912,14 +856,14 @@
virtual void threadLoop_drain();
virtual void threadLoop_standby();
virtual void threadLoop_exit();
- virtual void threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove);
+ virtual void threadLoop_removeTracks(const Vector<sp<IAfTrack>>& tracksToRemove);
// 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<Track> > *tracksToRemove) = 0;
- void removeTracks_l(const Vector< sp<Track> >& tracksToRemove);
+ virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) = 0;
+ void removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove);
status_t handleVoipVolume_l(float *volume);
// StreamOutHalInterfaceCallback implementation
@@ -927,18 +871,21 @@
virtual void onDrainReady();
virtual void onError();
+public: // AsyncCallbackThread
void resetWriteBlocked(uint32_t sequence);
void resetDraining(uint32_t sequence);
+protected:
virtual bool waitingAsyncCallback();
virtual bool waitingAsyncCallback_l();
virtual bool shouldStandby_l();
virtual void onAddNewTrack_l();
+public: // AsyncCallbackThread
void onAsyncError(); // error reported by AsyncCallbackThread
-
+protected:
// StreamHalInterfaceCodecFormatCallback implementation
void onCodecFormatChanged(
- const std::basic_string<uint8_t>& metadataBs) override;
+ const std::basic_string<uint8_t>& metadataBs) final;
// ThreadBase virtuals
virtual void preExit();
@@ -953,30 +900,29 @@
virtual void setHalLatencyMode_l() {}
- 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;
+ void dumpTracks_l(int fd, const Vector<String16>& args) final;
public:
- virtual status_t initCheck() const { return (mOutput == NULL) ? NO_INIT : NO_ERROR; }
+ status_t initCheck() const final { return mOutput == nullptr ? NO_INIT : NO_ERROR; }
// return estimated latency in milliseconds, as reported by HAL
- uint32_t latency() const;
+ uint32_t latency() const final;
// same, but lock must already be held
- uint32_t latency_l() const override;
+ uint32_t latency_l() const final;
// VolumeInterface
- virtual void setMasterVolume(float value);
- virtual void setMasterBalance(float balance);
- virtual void setMasterMute(bool muted);
- virtual void setStreamVolume(audio_stream_type_t stream, float value);
- virtual void setStreamMute(audio_stream_type_t stream, bool muted);
- virtual float streamVolume(audio_stream_type_t stream) const;
+ void setMasterVolume(float value) final;
+ void setMasterBalance(float balance) override;
+ 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 setVolumeForOutput_l(float left, float right) const final;
- void setVolumeForOutput_l(float left, float right) const override;
-
- sp<Track> createTrack_l(
- const sp<AudioFlinger::Client>& client,
+ sp<IAfTrack> createTrack_l(
+ const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
uint32_t *sampleRate,
@@ -996,15 +942,21 @@
audio_port_handle_t portId,
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
- bool isBitPerfect);
+ bool isBitPerfect) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- AudioStreamOut* getOutput() const;
- AudioStreamOut* clearOutput();
- virtual sp<StreamHalInterface> stream() const;
+ bool isTrackActive(const sp<IAfTrack>& track) const final {
+ return mActiveTracks.indexOf(track) >= 0;
+ }
+
+ AudioStreamOut* getOutput_l() const final { return mOutput; }
+ AudioStreamOut* getOutput() const final;
+ AudioStreamOut* clearOutput() final;
+ sp<StreamHalInterface> stream() const final;
// a very large number of suspend() will eventually wraparound, but unlikely
- void suspend() { (void) android_atomic_inc(&mSuspended); }
- void restore()
+ 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
@@ -1012,124 +964,130 @@
android_atomic_release_store(0, &mSuspended);
}
}
- bool isSuspended() const
+ bool isSuspended() const final
{ return android_atomic_acquire_load(&mSuspended) > 0; }
- virtual String8 getParameters(const String8& keys);
- virtual void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
- status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
+ String8 getParameters(const String8& keys);
+ void ioConfigChanged(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;
// Consider also removing and passing an explicit mMainBuffer initialization
- // parameter to AF::PlaybackThread::Track::Track().
- float *sinkBuffer() const {
+ // parameter to AF::IAfTrack::Track().
+ float* sinkBuffer() const final {
return reinterpret_cast<float *>(mSinkBuffer); };
- virtual void detachAuxEffect_l(int effectId);
- status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track,
- int EffectId);
- status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track>& track,
- int EffectId);
+ void detachAuxEffect_l(int effectId) final;
- virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
- virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
- uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) final;
+ status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) final;
+
+ 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 {
return ThreadBase::hasAudioSession_l(sessionId, mTracks);
}
- virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId);
+ product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const final;
- status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
- bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
+ bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const final;
// called with AudioFlinger lock held
- bool invalidateTracks_l(audio_stream_type_t streamType);
- bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds);
- virtual void invalidateTracks(audio_stream_type_t streamType);
+ bool invalidateTracks_l(audio_stream_type_t streamType) final;
+ bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) final;
+ 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.
- virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds);
+ void invalidateTracks(std::set<audio_port_handle_t>& portIds) override;
- virtual size_t frameCount() const { return mNormalFrameCount; }
+ size_t frameCount() const final { return mNormalFrameCount; }
- audio_channel_mask_t mixerChannelMask() const override {
+ audio_channel_mask_t mixerChannelMask() const final {
return mMixerChannelMask;
}
- status_t getTimestamp_l(AudioTimestamp& timestamp);
+ status_t getTimestamp_l(AudioTimestamp& timestamp) final;
- void addPatchTrack(const sp<PatchTrack>& track);
- void deletePatchTrack(const sp<PatchTrack>& track);
+ void addPatchTrack(const sp<IAfPatchTrack>& track) final;
+ void deletePatchTrack(const sp<IAfPatchTrack>& track) final;
- virtual void toAudioPortConfig(struct audio_port_config *config);
+ void toAudioPortConfig(struct audio_port_config* config) final;
// Return the asynchronous signal wait time.
- virtual int64_t computeWaitTimeNs_l() const { return INT64_MAX; }
+ int64_t computeWaitTimeNs_l() const override { return INT64_MAX; }
// returns true if the track is allowed to be added to the thread.
- virtual bool isTrackAllowed_l(
+ bool isTrackAllowed_l(
audio_channel_mask_t channelMask __unused,
audio_format_t format __unused,
audio_session_t sessionId __unused,
- uid_t uid) const {
+ uid_t uid) const override {
return trackCountForUid_l(uid) < PlaybackThread::kMaxTracksPerUid
&& mTracks.size() < PlaybackThread::kMaxTracks;
}
- bool isTimestampCorrectionEnabled() const override {
+ bool isTimestampCorrectionEnabled() const final {
return audio_is_output_devices(mTimestampCorrectedDevice)
&& outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
}
- virtual bool isStreamInitialized() {
+ bool isStreamInitialized() const final {
return !(mOutput == nullptr || mOutput->stream == nullptr);
}
- audio_channel_mask_t hapticChannelMask() const override {
+ audio_channel_mask_t hapticChannelMask() const final {
return mHapticChannelMask;
}
- bool supportsHapticPlayback() const {
+
+ uint32_t hapticChannelCount() const final {
+ return mHapticChannelCount;
+ }
+
+ bool supportsHapticPlayback() const final {
return (mHapticChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE;
}
- void setDownStreamPatch(const struct audio_patch *patch) {
- Mutex::Autolock _l(mLock);
+ void setDownStreamPatch(const struct audio_patch* patch) final {
+ std::lock_guard _l(mutex());
mDownStreamPatch = *patch;
}
- PlaybackThread::Track* getTrackById_l(audio_port_handle_t trackId);
+ IAfTrack* getTrackById_l(audio_port_handle_t trackId) final;
- bool hasMixer() const {
+ bool hasMixer() const final {
return mType == MIXER || mType == DUPLICATING || mType == SPATIALIZER;
}
- virtual status_t setRequestedLatencyMode(
- audio_latency_mode_t mode __unused) { return INVALID_OPERATION; }
+ status_t setRequestedLatencyMode(
+ audio_latency_mode_t /* mode */) override { return INVALID_OPERATION; }
- virtual status_t getSupportedLatencyModes(
- std::vector<audio_latency_mode_t>* modes __unused) {
+ status_t getSupportedLatencyModes(
+ std::vector<audio_latency_mode_t>* /* modes */) override {
return INVALID_OPERATION;
}
- virtual status_t setBluetoothVariableLatencyEnabled(bool enabled __unused) {
+ status_t setBluetoothVariableLatencyEnabled(bool /* enabled */) override{
return INVALID_OPERATION;
}
- void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override;
- void stopMelComputation_l() override;
+ void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void stopMelComputation_l() override
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- void setStandby() {
- Mutex::Autolock _l(mLock);
+ void setStandby() final {
+ std::lock_guard _l(mutex());
setStandby_l();
}
- void setStandby_l() {
+ void setStandby_l() final {
mStandby = true;
mHalStarted = false;
mKernelPositionOnStandby =
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
}
- bool waitForHalStart() {
- Mutex::Autolock _l(mLock);
+ bool waitForHalStart() final {
+ audio_utils::unique_lock _l(mutex());
static const nsecs_t kWaitHalTimeoutNs = seconds(2);
nsecs_t endWaitTimetNs = systemTime() + kWaitHalTimeoutNs;
while (!mHalStarted) {
@@ -1138,7 +1096,7 @@
break;
}
nsecs_t waitTimeLeftNs = endWaitTimetNs - timeNs;
- mWaitHalStartCV.waitRelative(mLock, waitTimeLeftNs);
+ mWaitHalStartCV.wait_for(_l, std::chrono::nanoseconds(waitTimeLeftNs));
}
return mHalStarted;
}
@@ -1243,7 +1201,6 @@
audio_channel_mask_t mMixerChannelMask = AUDIO_CHANNEL_NONE;
-private:
// 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.
@@ -1257,8 +1214,7 @@
: mTimestampVerifier.DISCONTINUITY_MODE_CONTINUOUS;
}
-protected:
- ActiveTracks<Track> mActiveTracks;
+ ActiveTracks<IAfTrack> mActiveTracks;
// Time to sleep between cycles when:
virtual uint32_t activeSleepTimeUs() const; // mixer state MIXER_TRACKS_ENABLED
@@ -1268,7 +1224,7 @@
// No sleep in standby mode; waits on a condition
// Code snippets that are temporarily lifted up out of threadLoop() until the merge
- void checkSilentMode_l();
+ virtual void checkSilentMode_l() final; // consider unification with MMapThread
// Non-trivial for DUPLICATING only
virtual void saveOutputTracks() { }
@@ -1286,26 +1242,23 @@
audio_patch_handle_t *handle);
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
- bool usesHwAvSync() const { return (mType == DIRECT) && (mOutput != NULL)
+ bool usesHwAvSync() const final { return mType == DIRECT && mOutput != nullptr
&& mHwSupportsPause
&& (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
uint32_t trackCountForUid_l(uid_t uid) const;
void invalidateTracksForAudioSession_l(
- audio_session_t sessionId) const override {
+ audio_session_t sessionId) const override {
ThreadBase::invalidateTracksForAudioSession_l(sessionId, mTracks);
}
-private:
-
- friend class AudioFlinger; // for numerous
-
DISALLOW_COPY_AND_ASSIGN(PlaybackThread);
- status_t addTrack_l(const sp<Track>& track);
- bool destroyTrack_l(const sp<Track>& track);
- void removeTrack_l(const sp<Track>& track);
+ status_t addTrack_l(const sp<IAfTrack>& track) final;
+ bool destroyTrack_l(const sp<IAfTrack>& track) final;
+
+ void removeTrack_l(const sp<IAfTrack>& track);
void readOutputParameters_l();
MetadataUpdate updateMetadata_l() final;
@@ -1363,9 +1316,10 @@
SortedVector<sp<T>> mTracks; // wrapped SortedVector.
};
- Tracks<Track> mTracks;
+ Tracks<IAfTrack> mTracks;
stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
+
AudioStreamOut *mOutput;
float mMasterVolume;
@@ -1420,19 +1374,21 @@
// Bit 0 is reset by the async callback thread calling resetDraining(). Out of sequence
// callbacks are ignored.
uint32_t mDrainSequence;
+
sp<AsyncCallbackThread> mCallbackThread;
- Mutex mAudioTrackCbLock;
+ audio_utils::mutex& audioTrackCbMutex() const { return mAudioTrackCbMutex; }
+ mutable audio_utils::mutex mAudioTrackCbMutex;
// Record of IAudioTrackCallback
- std::map<sp<Track>, sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
+ std::map<sp<IAfTrack>, sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
-private:
// The HAL output sink is treated as non-blocking, but current implementation is blocking
sp<NBAIO_Sink> mOutputSink;
// If a fast mixer is present, the blocking pipe sink, otherwise clear
sp<NBAIO_Sink> mPipeSink;
// The current sink for the normal mixer to write it's (sub)mix, mOutputSink or mPipeSink
sp<NBAIO_Sink> mNormalSink;
+
uint32_t mScreenState; // cached copy of gScreenState
// TODO: add comment and adjust size as needed
static const size_t kFastMixerLogSize = 8 * 1024;
@@ -1443,21 +1399,21 @@
// output stream start detection based on render position returned by the kernel
// condition signalled when the output stream has started
- Condition mWaitHalStartCV;
+ audio_utils::condition_variable mWaitHalStartCV;
// true when the output stream render position has moved, reset to false in standby
bool mHalStarted = false;
// last kernel render position saved when entering standby
int64_t mKernelPositionOnStandby = 0;
public:
- virtual bool hasFastMixer() const = 0;
- virtual FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex __unused) const
- { FastTrackUnderruns dummy; return dummy; }
- const std::atomic<int64_t>& framesWritten() const { return mFramesWritten; }
+ FastTrackUnderruns getFastTrackUnderruns(size_t /* fastIndex */) const override
+ { return {}; }
+ const std::atomic<int64_t>& framesWritten() const final { return mFramesWritten; }
protected:
// accessed by both binder threads and within threadLoop(), lock on mutex needed
- unsigned mFastTrackAvailMask; // bit i set if fast track [i] is available
+ uint32_t& fastTrackAvailMask_l() final { return mFastTrackAvailMask; }
+ uint32_t mFastTrackAvailMask; // bit i set if fast track [i] is available
bool mHwSupportsPause;
bool mHwPaused;
bool mFlushPending;
@@ -1508,36 +1464,35 @@
class MixerThread : public PlaybackThread,
public StreamOutHalInterfaceLatencyModeCallback {
public:
- MixerThread(const sp<AudioFlinger>& audioFlinger,
+ MixerThread(const sp<IAfThreadCallback>& afThreadCallback,
AudioStreamOut* output,
audio_io_handle_t id,
bool systemReady,
type_t type = MIXER,
audio_config_base_t *mixerConfig = nullptr);
- virtual ~MixerThread();
+ ~MixerThread() override;
// RefBase
- virtual void onFirstRef();
+ void onFirstRef() override;
// StreamOutHalInterfaceLatencyModeCallback
void onRecommendedLatencyModeChanged(
- std::vector<audio_latency_mode_t> modes) override;
+ std::vector<audio_latency_mode_t> modes) final;
// Thread virtuals
- virtual bool checkForNewParameter_l(const String8& keyValuePair,
- status_t& status);
+ bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final;
- virtual bool isTrackAllowed_l(
+ bool isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
- audio_session_t sessionId, uid_t uid) const override;
+ audio_session_t sessionId, uid_t uid) const final;
protected:
- virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
- virtual uint32_t idleSleepTimeUs() const;
- virtual uint32_t suspendSleepTimeUs() const;
- virtual void cacheParameters_l();
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) override;
+ uint32_t idleSleepTimeUs() const final;
+ uint32_t suspendSleepTimeUs() const final;
+ void cacheParameters_l() override;
- virtual void acquireWakeLock_l() {
+ void acquireWakeLock_l() final {
PlaybackThread::acquireWakeLock_l();
if (hasFastMixer()) {
mFastMixer->setBoottimeOffset(
@@ -1548,15 +1503,15 @@
void dumpInternals_l(int fd, const Vector<String16>& args) override;
// threadLoop snippets
- virtual ssize_t threadLoop_write();
- virtual void threadLoop_standby();
- virtual void threadLoop_mix();
- virtual void threadLoop_sleepTime();
- virtual uint32_t correctLatency_l(uint32_t latency) const;
+ 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;
- 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);
+ 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;
AudioMixer* mAudioMixer; // normal mixer
@@ -1632,17 +1587,21 @@
void setHalLatencyMode_l() override;
};
-class DirectOutputThread : public PlaybackThread {
+class DirectOutputThread : public PlaybackThread, public virtual IAfDirectOutputThread {
public:
- DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+ sp<IAfDirectOutputThread> asIAfDirectOutputThread() final {
+ return sp<IAfDirectOutputThread>::fromExisting(this);
+ }
+
+ DirectOutputThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
audio_io_handle_t id, bool systemReady,
const audio_offload_info_t& offloadInfo)
- : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady, offloadInfo) { }
+ : DirectOutputThread(afThreadCallback, output, id, DIRECT, systemReady, offloadInfo) { }
virtual ~DirectOutputThread();
- status_t selectPresentation(int presentationId, int programId);
+ status_t selectPresentation(int presentationId, int programId) final;
// Thread virtuals
@@ -1662,7 +1621,7 @@
void dumpInternals_l(int fd, const Vector<String16>& args) override;
// threadLoop snippets
- virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+ virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
virtual void threadLoop_mix();
virtual void threadLoop_sleepTime();
virtual void threadLoop_exit();
@@ -1675,16 +1634,16 @@
audioflinger::MonotonicFrameCounter mMonotonicFrameCounter; // for VolumeShaper
bool mVolumeShaperActive = false;
- DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+ 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(Track *track, bool lastTrack);
+ void processVolume_l(IAfTrack *track, bool lastTrack);
bool isTunerStream() const { return (mOffloadInfo.content_id > 0); }
// prepareTracks_l() tells threadLoop_mix() the name of the single active track
- sp<Track> mActiveTrack;
+ sp<IAfTrack> mActiveTrack;
- wp<Track> mPreviousTrack; // used to detect track switch
+ wp<IAfTrack> mPreviousTrack; // used to detect track switch
// This must be initialized for initial condition of mMasterBalance = 0 (disabled).
float mMasterBalanceLeft = 1.f;
@@ -1716,7 +1675,7 @@
class OffloadThread : public DirectOutputThread {
public:
- OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+ OffloadThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
audio_io_handle_t id, bool systemReady,
const audio_offload_info_t& offloadInfo);
virtual ~OffloadThread() {};
@@ -1724,7 +1683,7 @@
protected:
// threadLoop snippets
- virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+ virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
virtual void threadLoop_exit();
virtual bool waitingAsyncCallback();
@@ -1742,11 +1701,8 @@
class AsyncCallbackThread : public Thread {
public:
-
explicit AsyncCallbackThread(const wp<PlaybackThread>& playbackThread);
- virtual ~AsyncCallbackThread();
-
// Thread virtuals
virtual bool threadLoop();
@@ -1770,21 +1726,28 @@
// setDraining(). The sequence is shifted one bit to the left and the lsb is used
// to indicate that the callback has been received via resetDraining()
uint32_t mDrainSequence;
- Condition mWaitWorkCV;
- Mutex mLock;
+ audio_utils::condition_variable mWaitWorkCV;
+ mutable audio_utils::mutex mMutex;
bool mAsyncError;
+
+ audio_utils::mutex& mutex() const { return mMutex; }
};
-class DuplicatingThread : public MixerThread {
+class DuplicatingThread : public MixerThread, public IAfDuplicatingThread {
public:
- DuplicatingThread(const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread,
+ DuplicatingThread(const sp<IAfThreadCallback>& afThreadCallback,
+ IAfPlaybackThread* mainThread,
audio_io_handle_t id, bool systemReady);
- virtual ~DuplicatingThread();
+ ~DuplicatingThread() override;
+
+ sp<IAfDuplicatingThread> asIAfDuplicatingThread() final {
+ return sp<IAfDuplicatingThread>::fromExisting(this);
+ }
// Thread virtuals
- void addOutputTrack(MixerThread* thread);
- void removeOutputTrack(MixerThread* thread);
- uint32_t waitTimeMs() const { return mWaitTimeMs; }
+ void addOutputTrack(IAfPlaybackThread* thread) final;
+ void removeOutputTrack(IAfPlaybackThread* thread) final;
+ uint32_t waitTimeMs() const final { return mWaitTimeMs; }
void sendMetadataToBackend_l(
const StreamOutHalInterface::SourceMetadata& metadata) override;
@@ -1811,8 +1774,8 @@
private:
uint32_t mWaitTimeMs;
- SortedVector < sp<OutputTrack> > outputTracks;
- SortedVector < sp<OutputTrack> > mOutputTracks;
+ SortedVector <sp<IAfOutputTrack>> outputTracks;
+ SortedVector <sp<IAfOutputTrack>> mOutputTracks;
public:
virtual bool hasFastMixer() const { return false; }
status_t threadloop_getHalTimestamp_l(
@@ -1835,110 +1798,62 @@
class SpatializerThread : public MixerThread {
public:
- SpatializerThread(const sp<AudioFlinger>& audioFlinger,
+ SpatializerThread(const sp<IAfThreadCallback>& afThreadCallback,
AudioStreamOut* output,
audio_io_handle_t id,
bool systemReady,
audio_config_base_t *mixerConfig);
- ~SpatializerThread() override {}
- bool hasFastMixer() const override { return false; }
+ bool hasFastMixer() const final { return false; }
- // RefBase
- virtual void onFirstRef();
-
- status_t setRequestedLatencyMode(audio_latency_mode_t mode) override;
+ status_t setRequestedLatencyMode(audio_latency_mode_t mode) final;
protected:
- void checkOutputStageEffects() override;
- void setHalLatencyMode_l() override;
+ void checkOutputStageEffects() final;
+ void setHalLatencyMode_l() final;
private:
// Do not request a specific mode by default
audio_latency_mode_t mRequestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
- sp<EffectHandle> mFinalDownMixer;
+ sp<IAfEffectHandle> mFinalDownMixer;
};
// record thread
-class RecordThread : public ThreadBase
+class RecordThread : public IAfRecordThread, public ThreadBase
{
+ friend class ResamplerBufferProvider;
public:
+ sp<IAfRecordThread> asIAfRecordThread() final {
+ return sp<IAfRecordThread>::fromExisting(this);
+ }
- class RecordTrack;
-
- /* The ResamplerBufferProvider is used to retrieve recorded input data from the
- * RecordThread. It maintains local state on the relative position of the read
- * position of the RecordTrack compared with the RecordThread.
- */
- class ResamplerBufferProvider : public AudioBufferProvider
- {
- public:
- explicit ResamplerBufferProvider(RecordTrack* recordTrack) :
- mRecordTrack(recordTrack),
- mRsmpInUnrel(0), mRsmpInFront(0) { }
- virtual ~ResamplerBufferProvider() { }
-
- // called to set the ResamplerBufferProvider to head of the RecordThread data buffer,
- // skipping any previous data read from the hal.
- virtual void reset();
-
- /* Synchronizes RecordTrack position with the RecordThread.
- * Calculates available frames and handle overruns if the RecordThread
- * has advanced faster than the ResamplerBufferProvider has retrieved data.
- * TODO: why not do this for every getNextBuffer?
- *
- * Parameters
- * framesAvailable: pointer to optional output size_t to store record track
- * frames available.
- * hasOverrun: pointer to optional boolean, returns true if track has overrun.
- */
-
- virtual void sync(size_t *framesAvailable = NULL, bool *hasOverrun = NULL);
-
- // AudioBufferProvider interface
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
- virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
-
- int32_t getFront() const { return mRsmpInFront; }
- void setFront(int32_t front) { mRsmpInFront = front; }
- private:
- RecordTrack * const mRecordTrack;
- size_t mRsmpInUnrel; // unreleased frames remaining from
- // most recent getNextBuffer
- // for debug only
- int32_t mRsmpInFront; // next available frame
- // rolling counter that is never cleared
- };
-
-#include "RecordTracks.h"
-
- RecordThread(const sp<AudioFlinger>& audioFlinger,
+ RecordThread(const sp<IAfThreadCallback>& afThreadCallback,
AudioStreamIn *input,
audio_io_handle_t id,
bool systemReady
);
- virtual ~RecordThread();
+ ~RecordThread() override;
// no addTrack_l ?
- void destroyTrack_l(const sp<RecordTrack>& track);
- void removeTrack_l(const sp<RecordTrack>& track);
+ void destroyTrack_l(const sp<IAfRecordTrack>& track) final;
+ void removeTrack_l(const sp<IAfRecordTrack>& track) final;
// Thread virtuals
- virtual bool threadLoop();
- virtual void preExit();
+ bool threadLoop() final;
+ void preExit() final;
// RefBase
- virtual void onFirstRef();
+ void onFirstRef() final;
- virtual status_t initCheck() const { return (mInput == NULL) ? NO_INIT : NO_ERROR; }
+ status_t initCheck() const final { return mInput == nullptr ? NO_INIT : NO_ERROR; }
- virtual sp<MemoryDealer> readOnlyHeap() const { return mReadOnlyHeap; }
+ sp<MemoryDealer> readOnlyHeap() const final { return mReadOnlyHeap; }
- virtual sp<IMemory> pipeMemory() const { return mPipeMemory; }
+ sp<IMemory> pipeMemory() const final { return mPipeMemory; }
- sp<AudioFlinger::RecordThread::RecordTrack> createRecordTrack_l(
- const sp<AudioFlinger::Client>& client,
+ sp<IAfRecordTrack> createRecordTrack_l(
+ const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
audio_format_t format,
@@ -1952,17 +1867,20 @@
pid_t tid,
status_t *status /*non-NULL*/,
audio_port_handle_t portId,
- int32_t maxSharedAudioHistoryMs);
+ int32_t maxSharedAudioHistoryMs) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- status_t start(RecordTrack* recordTrack,
+ status_t start(IAfRecordTrack* recordTrack,
AudioSystem::sync_event_t event,
- audio_session_t triggerSession);
+ audio_session_t triggerSession) final;
// 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(RecordTrack* recordTrack);
+ bool stop(IAfRecordTrack* recordTrack) final;
+ AudioStreamIn* getInput() const final { return mInput; }
+ AudioStreamIn* clearInput() final;
- AudioStreamIn* clearInput();
+ // TODO(b/291317898) Unify with IAfThreadBase
virtual sp<StreamHalInterface> stream() const;
@@ -1970,22 +1888,22 @@
status_t& status);
virtual void cacheParameters_l() {}
virtual String8 getParameters(const String8& keys);
- virtual void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+ void ioConfigChanged(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;
- void addPatchTrack(const sp<PatchRecord>& record);
- void deletePatchTrack(const sp<PatchRecord>& record);
+ void addPatchTrack(const sp<IAfPatchRecord>& record) final;
+ void deletePatchTrack(const sp<IAfPatchRecord>& record) final;
void readInputParameters_l();
- virtual uint32_t getInputFramesLost();
+ uint32_t getInputFramesLost() const final;
- virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
- virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+ 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 {
return ThreadBase::hasAudioSession_l(sessionId, mTracks);
}
@@ -2001,7 +1919,7 @@
static void syncStartEventCallback(const wp<audioflinger::SyncEvent>& event);
virtual size_t frameCount() const { return mFrameCount; }
- bool hasFastCapture() const { return mFastCapture != 0; }
+ 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,
@@ -2012,20 +1930,20 @@
mActiveTracks.updatePowerState(this, true /* force */);
}
- void checkBtNrec();
+ void checkBtNrec() final;
// Sets the UID records silence
- void setRecordSilenced(audio_port_handle_t portId, bool silenced);
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
- status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones);
-
- status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
- status_t setPreferredMicrophoneFieldDimension(float zoom);
+ 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;
MetadataUpdate updateMetadata_l() override;
- bool fastTrackAvailable() const { return mFastTrackAvail; }
+ bool fastTrackAvailable() const final { return mFastTrackAvail; }
+ void setFastTrackAvailable(bool available) final { mFastTrackAvail = available; }
bool isTimestampCorrectionEnabled() const override {
// checks popcount for exactly one device.
@@ -2035,15 +1953,15 @@
&& inDeviceType() == mTimestampCorrectedDevice;
}
- status_t shareAudioHistory(const std::string& sharedAudioPackageName,
+ status_t shareAudioHistory(const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
- int64_t sharedAudioStartMs = -1);
+ int64_t sharedAudioStartMs = -1) final;
status_t shareAudioHistory_l(const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
int64_t sharedAudioStartMs = -1);
- void resetAudioHistory_l();
+ void resetAudioHistory_l() final;
- virtual bool isStreamInitialized() {
+ bool isStreamInitialized() const final {
return !(mInput == nullptr || mInput->stream == nullptr);
}
@@ -2065,12 +1983,12 @@
AudioStreamIn *mInput;
Source *mSource;
- SortedVector < sp<RecordTrack> > mTracks;
+ SortedVector <sp<IAfRecordTrack>> mTracks;
// mActiveTracks has dual roles: it indicates the current active track(s), and
- // is used together with mStartStopCond to indicate start()/stop() progress
- ActiveTracks<RecordTrack> mActiveTracks;
+ // is used together with mStartStopCV to indicate start()/stop() progress
+ ActiveTracks<IAfRecordTrack> mActiveTracks;
- Condition mStartStopCond;
+ audio_utils::condition_variable mStartStopCV;
// resampler converts input at HAL Hz to output at AudioRecord client Hz
void *mRsmpInBuffer; // size = mRsmpInFramesOA
@@ -2135,90 +2053,85 @@
audio_session_t mSharedAudioSessionId = AUDIO_SESSION_NONE;
};
-class MmapThread : public ThreadBase
+class MmapThread : public ThreadBase, public virtual IAfMmapThread
{
public:
-
-#include "MmapTracks.h"
-
- MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+ MmapThread(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady,
bool isOut);
- virtual ~MmapThread();
- virtual void configure(const audio_attributes_t *attr,
+ void configure(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);
+ audio_port_handle_t portId) override;
- void disconnect();
+ void disconnect() final;
- // MmapStreamInterface
- status_t createMmapBuffer(int32_t minSizeFrames,
- struct audio_mmap_buffer_info *info);
- status_t getMmapPosition(struct audio_mmap_position *position);
+ // 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 start(const AudioClient& client,
const audio_attributes_t *attr,
- audio_port_handle_t *handle);
- status_t stop(audio_port_handle_t handle);
- status_t standby();
- virtual status_t getExternalPosition(uint64_t *position, int64_t *timeNaos) = 0;
- virtual status_t reportData(const void* buffer, size_t frameCount);
+ 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;
// RefBase
- virtual void onFirstRef();
+ void onFirstRef() final;
// Thread virtuals
- virtual bool threadLoop();
+ bool threadLoop() final;
- virtual void threadLoop_exit();
- virtual void threadLoop_standby();
- virtual bool shouldStandby_l() { return false; }
- virtual status_t exitStandby_l() REQUIRES(mLock);
+ // Not in ThreadBase
+ virtual void threadLoop_exit() final;
+ virtual void threadLoop_standby() final;
+ virtual bool shouldStandby_l() final { return false; }
+ virtual status_t exitStandby_l() REQUIRES(mutex());
- virtual status_t initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; }
- virtual size_t frameCount() const { return mFrameCount; }
- virtual bool checkForNewParameter_l(const String8& keyValuePair,
- status_t& status);
- virtual String8 getParameters(const String8& keys);
- virtual void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+ 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();
- virtual void cacheParameters_l() {}
- 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);
- virtual void toAudioPortConfig(struct audio_port_config *config);
+ void cacheParameters_l() final {}
+ 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;
+ void toAudioPortConfig(struct audio_port_config* config) override;
- virtual sp<StreamHalInterface> stream() const { return mHalStream; }
- virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
- virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
- virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
- audio_session_t sessionId);
+ 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 checkEffectCompatibility_l(
+ const effect_descriptor_t *desc, audio_session_t sessionId) final;
- uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
// Note: using mActiveTracks as no mTracks here.
return ThreadBase::hasAudioSession_l(sessionId, mActiveTracks);
}
- virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event);
- virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
+ bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const final;
- virtual void checkSilentMode_l() {}
- virtual void processVolume_l() {}
+ virtual void checkSilentMode_l() {} // cannot be const (RecordThread)
+ virtual void processVolume_l() {}
void checkInvalidTracks_l();
- virtual audio_stream_type_t streamType() { return AUDIO_STREAM_DEFAULT; }
-
- virtual void invalidateTracks(audio_stream_type_t streamType __unused) {}
- virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds __unused) {}
+ // 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 {}
// Sets the UID records silence
- virtual void setRecordSilenced(audio_port_handle_t portId __unused,
- bool silenced __unused) {}
+ void setRecordSilenced(
+ audio_port_handle_t /* portId */, bool /* silenced */) override {}
- virtual bool isStreamInitialized() { return false; }
+ bool isStreamInitialized() const override { return false; }
void setClientSilencedState_l(audio_port_handle_t portId, bool silenced) {
mClientSilencedStates[portId] = silenced;
@@ -2241,8 +2154,8 @@
}
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;
+ void dumpTracks_l(int fd, const Vector<String16>& args) final;
/**
* @brief mDeviceId current device port unique identifier
@@ -2257,7 +2170,7 @@
sp<StreamHalInterface> mHalStream;
sp<DeviceHalInterface> mHalDevice;
AudioHwDevice* const mAudioHwDev;
- ActiveTracks<MmapTrack> mActiveTracks;
+ ActiveTracks<IAfMmapTrack> mActiveTracks;
float mHalVolFloat;
std::map<audio_port_handle_t, bool> mClientSilencedStates;
@@ -2265,56 +2178,61 @@
static constexpr int32_t kMaxNoCallbackWarnings = 5;
};
-class MmapPlaybackThread : public MmapThread, public VolumeInterface
-{
-
+class MmapPlaybackThread : public MmapThread, public IAfMmapPlaybackThread,
+ public virtual VolumeInterface {
public:
- MmapPlaybackThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+ MmapPlaybackThread(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady);
- virtual ~MmapPlaybackThread() {}
- virtual void configure(const audio_attributes_t *attr,
+ sp<IAfMmapPlaybackThread> asIAfMmapPlaybackThread() final {
+ return sp<IAfMmapPlaybackThread>::fromExisting(this);
+ }
+
+ void configure(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);
+ audio_port_handle_t portId) final;
- AudioStreamOut* clearOutput();
+ AudioStreamOut* clearOutput() final;
// VolumeInterface
- virtual void setMasterVolume(float value);
- virtual void setMasterMute(bool muted);
- virtual void setStreamVolume(audio_stream_type_t stream, float value);
- virtual void setStreamMute(audio_stream_type_t stream, bool muted);
- virtual float streamVolume(audio_stream_type_t stream) const;
+ 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;
void setMasterMute_l(bool muted) { mMasterMute = muted; }
- virtual void invalidateTracks(audio_stream_type_t streamType);
- void invalidateTracks(std::set<audio_port_handle_t>& portIds) override;
+ void invalidateTracks(audio_stream_type_t streamType) final;
+ void invalidateTracks(std::set<audio_port_handle_t>& portIds) final;
- virtual audio_stream_type_t streamType() { return mStreamType; }
- virtual void checkSilentMode_l();
- void processVolume_l() override;
+ audio_stream_type_t streamType() const final { return mStreamType; }
+ void checkSilentMode_l() final;
+ void processVolume_l() final;
- MetadataUpdate updateMetadata_l() override;
+ MetadataUpdate updateMetadata_l() final;
- virtual void toAudioPortConfig(struct audio_port_config *config);
+ void toAudioPortConfig(struct audio_port_config* config) final;
- status_t getExternalPosition(uint64_t *position, int64_t *timeNanos) override;
+ status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const final;
- virtual bool isStreamInitialized() {
+ bool isStreamInitialized() const final {
return !(mOutput == nullptr || mOutput->stream == nullptr);
}
- status_t reportData(const void* buffer, size_t frameCount) override;
+ status_t reportData(const void* buffer, size_t frameCount) final;
- void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override;
- void stopMelComputation_l() override;
+ void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void stopMelComputation_l() final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
protected:
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) final;
audio_stream_type_t mStreamType;
float mMasterVolume;
@@ -2326,28 +2244,29 @@
mediautils::atomic_sp<audio_utils::MelProcessor> mMelProcessor;
};
-class MmapCaptureThread : public MmapThread
+class MmapCaptureThread : public MmapThread, public IAfMmapCaptureThread
{
-
public:
- MmapCaptureThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+ MmapCaptureThread(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice *hwDev, AudioStreamIn *input, bool systemReady);
- virtual ~MmapCaptureThread() {}
- AudioStreamIn* clearInput();
+ sp<IAfMmapCaptureThread> asIAfMmapCaptureThread() final {
+ return sp<IAfMmapCaptureThread>::fromExisting(this);
+ }
- status_t exitStandby_l() REQUIRES(mLock) override;
+ AudioStreamIn* clearInput() final;
- MetadataUpdate updateMetadata_l() override;
- void processVolume_l() override;
- void setRecordSilenced(audio_port_handle_t portId,
- bool silenced) override;
+ status_t exitStandby_l() REQUIRES(mutex()) final;
- virtual void toAudioPortConfig(struct audio_port_config *config);
+ MetadataUpdate updateMetadata_l() final;
+ void processVolume_l() final;
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
- status_t getExternalPosition(uint64_t *position, int64_t *timeNanos) override;
+ void toAudioPortConfig(struct audio_port_config* config) final;
- virtual bool isStreamInitialized() {
+ status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const final;
+
+ bool isStreamInitialized() const final {
return !(mInput == nullptr || mInput->stream == nullptr);
}
@@ -2358,15 +2277,17 @@
class BitPerfectThread : public MixerThread {
public:
- BitPerfectThread(const sp<AudioFlinger>& audioflinger, AudioStreamOut *output,
+ BitPerfectThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut *output,
audio_io_handle_t id, bool systemReady);
protected:
- mixer_state prepareTracks_l(Vector<sp<Track>> *tracksToRemove) override;
- void threadLoop_mix() override;
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) final;
+ void threadLoop_mix() final;
private:
bool mIsBitPerfect;
float mVolumeLeft = 0.f;
float mVolumeRight = 0.f;
};
+
+} // namespace android
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index d5b6a98..4e37953 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -15,46 +15,26 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "Configuration.h" // TEE_SINK
+#include "IAfTrack.h"
+
+#include <afutils/NBAIO_Tee.h>
+#include <android-base/macros.h> // DISALLOW_COPY_AND_ASSIGN
+#include <datapath/TrackMetrics.h>
+#include <mediautils/BatteryNotifier.h>
+
+#include <atomic> // avoid transitive dependency
+#include <list> // avoid transitive dependency
+#include <optional> // avoid transitive dependency
+
+namespace android {
// base for record and playback
-class TrackBase : public ExtendedAudioBufferProvider, public RefBase {
-
+class TrackBase : public ExtendedAudioBufferProvider, public virtual IAfTrackBase {
public:
- enum track_state : int32_t {
- IDLE,
- FLUSHED, // for PlaybackTracks only
- STOPPED,
- // next 2 states are currently used for fast tracks
- // and offloaded tracks only
- STOPPING_1, // waiting for first underrun
- STOPPING_2, // waiting for presentation complete
- RESUMING, // for PlaybackTracks only
- ACTIVE,
- PAUSING,
- PAUSED,
- STARTING_1, // for RecordTrack only
- STARTING_2, // for RecordTrack only
- };
-
- // where to allocate the data buffer
- enum alloc_type {
- ALLOC_CBLK, // allocate immediately after control block
- ALLOC_READONLY, // allocate from a separate read-only heap per thread
- ALLOC_PIPE, // do not allocate; use the pipe buffer
- ALLOC_LOCAL, // allocate a local buffer
- ALLOC_NONE, // do not allocate:use the buffer passed to TrackBase constructor
- };
-
- enum track_type {
- TYPE_DEFAULT,
- TYPE_OUTPUT,
- TYPE_PATCH,
- };
-
- TrackBase(ThreadBase *thread,
+ TrackBase(IAfThreadBase* thread,
const sp<Client>& client,
const audio_attributes_t& mAttr,
uint32_t sampleRate,
@@ -71,87 +51,79 @@
track_type type = TYPE_DEFAULT,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
std::string metricsId = {});
- virtual ~TrackBase();
- virtual status_t initCheck() const;
+ ~TrackBase() override;
+ status_t initCheck() const override;
+ sp<IMemory> getCblk() const final { return mCblkMemory; }
+ audio_track_cblk_t* cblk() const final { return mCblk; }
+ audio_session_t sessionId() const final { return mSessionId; }
+ uid_t uid() const final { return mUid; }
+ pid_t creatorPid() const final { return mCreatorPid; }
+ audio_port_handle_t portId() const final { return mPortId; }
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+ track_state state() const final { return mState; }
+ void setState(track_state state) final { mState = state; }
+ sp<IMemory> getBuffers() const final { return mBufferMemory; }
+ void* buffer() const final { return mBuffer; }
+ size_t bufferSize() const final { return mBufferSize; }
- virtual status_t start(AudioSystem::sync_event_t event,
- audio_session_t triggerSession) = 0;
- virtual void stop() = 0;
- sp<IMemory> getCblk() const { return mCblkMemory; }
- audio_track_cblk_t* cblk() const { return mCblk; }
- audio_session_t sessionId() const { return mSessionId; }
- uid_t uid() const { return mUid; }
- pid_t creatorPid() const { return mCreatorPid; }
-
- audio_port_handle_t portId() const { return mPortId; }
- virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event);
-
- sp<IMemory> getBuffers() const { return mBufferMemory; }
- void* buffer() const { return mBuffer; }
- size_t bufferSize() const { return mBufferSize; }
- virtual bool isFastTrack() const = 0;
- virtual bool isDirect() const = 0;
- bool isOutputTrack() const { return (mType == TYPE_OUTPUT); }
- bool isPatchTrack() const { return (mType == TYPE_PATCH); }
- bool isExternalTrack() const { return !isOutputTrack() && !isPatchTrack(); }
-
- virtual void invalidate() {
+ bool isOutputTrack() const final { return (mType == TYPE_OUTPUT); }
+ bool isPatchTrack() const final { return (mType == TYPE_PATCH); }
+ bool isExternalTrack() const final { return !isOutputTrack() && !isPatchTrack(); }
+ void invalidate() override {
if (mIsInvalid) return;
mTrackMetrics.logInvalidate();
mIsInvalid = true;
}
- bool isInvalid() const { return mIsInvalid; }
+ bool isInvalid() const final { return mIsInvalid; }
+ void terminate() final { mTerminated = true; }
+ bool isTerminated() const final { return mTerminated; }
+ audio_attributes_t attributes() const final { return mAttr; }
+ bool isSpatialized() const override { return false; }
+ bool isBitPerfect() const override { return false; }
- void terminate() { mTerminated = true; }
- bool isTerminated() const { return mTerminated; }
+ wp<IAfThreadBase> thread() const final { return mThread; }
- audio_attributes_t attributes() const { return mAttr; }
-
- virtual bool isSpatialized() const { return false; }
-
- virtual bool isBitPerfect() const { return false; }
+ const sp<ServerProxy>& serverProxy() const final { return mServerProxy; }
#ifdef TEE_SINK
- void dumpTee(int fd, const std::string &reason) const {
- mTee.dump(fd, reason);
- }
+ void dumpTee(int fd, const std::string &reason) const final {
+ mTee.dump(fd, reason);
+ }
#endif
-
- /** returns the buffer contents size converted to time in milliseconds
- * for PCM Playback or Record streaming tracks. The return value is zero for
- * PCM static tracks and not defined for non-PCM tracks.
- *
- * This may be called without the thread lock.
- */
- virtual double bufferLatencyMs() const {
+ /** returns the buffer contents size converted to time in milliseconds
+ * for PCM Playback or Record streaming tracks. The return value is zero for
+ * PCM static tracks and not defined for non-PCM tracks.
+ *
+ * This may be called without the thread lock.
+ */
+ double bufferLatencyMs() const override {
return mServerProxy->framesReadySafe() * 1000. / sampleRate();
}
- /** returns whether the track supports server latency computation.
- * This is set in the constructor and constant throughout the track lifetime.
- */
+ /** returns whether the track supports server latency computation.
+ * This is set in the constructor and constant throughout the track lifetime.
+ */
+ bool isServerLatencySupported() const final { return mServerLatencySupported; }
- bool isServerLatencySupported() const { return mServerLatencySupported; }
-
- /** computes the server latency for PCM Playback or Record track
- * to the device sink/source. This is the time for the next frame in the track buffer
- * written or read from the server thread to the device source or sink.
- *
- * This may be called without the thread lock, but latencyMs and fromTrack
- * may be not be synchronized. For example PatchPanel may not obtain the
- * thread lock before calling.
- *
- * \param latencyMs on success is set to the latency in milliseconds of the
- * next frame written/read by the server thread to/from the track buffer
- * from the device source/sink.
- * \param fromTrack on success is set to true if latency was computed directly
- * from the track timestamp; otherwise set to false if latency was
- * estimated from the server timestamp.
- * fromTrack may be nullptr or omitted if not required.
- *
- * \returns OK or INVALID_OPERATION on failure.
- */
- status_t getServerLatencyMs(double *latencyMs, bool *fromTrack = nullptr) const {
+ /** computes the server latency for PCM Playback or Record track
+ * to the device sink/source. This is the time for the next frame in the track buffer
+ * written or read from the server thread to the device source or sink.
+ *
+ * This may be called without the thread lock, but latencyMs and fromTrack
+ * may be not be synchronized. For example PatchPanel may not obtain the
+ * thread lock before calling.
+ *
+ * \param latencyMs on success is set to the latency in milliseconds of the
+ * next frame written/read by the server thread to/from the track buffer
+ * from the device source/sink.
+ * \param fromTrack on success is set to true if latency was computed directly
+ * from the track timestamp; otherwise set to false if latency was
+ * estimated from the server timestamp.
+ * fromTrack may be nullptr or omitted if not required.
+ *
+ * \returns OK or INVALID_OPERATION on failure.
+ */
+ status_t getServerLatencyMs(double* latencyMs, bool* fromTrack = nullptr) const final {
if (!isServerLatencySupported()) {
return INVALID_OPERATION;
}
@@ -170,25 +142,25 @@
return OK;
}
- /** computes the total client latency for PCM Playback or Record tracks
- * for the next client app access to the device sink/source; i.e. the
- * server latency plus the buffer latency.
- *
- * This may be called without the thread lock, but latencyMs and fromTrack
- * may be not be synchronized. For example PatchPanel may not obtain the
- * thread lock before calling.
- *
- * \param latencyMs on success is set to the latency in milliseconds of the
- * next frame written/read by the client app to/from the track buffer
- * from the device sink/source.
- * \param fromTrack on success is set to true if latency was computed directly
- * from the track timestamp; otherwise set to false if latency was
- * estimated from the server timestamp.
- * fromTrack may be nullptr or omitted if not required.
- *
- * \returns OK or INVALID_OPERATION on failure.
- */
- status_t getTrackLatencyMs(double *latencyMs, bool *fromTrack = nullptr) const {
+ /** computes the total client latency for PCM Playback or Record tracks
+ * for the next client app access to the device sink/source; i.e. the
+ * server latency plus the buffer latency.
+ *
+ * This may be called without the thread lock, but latencyMs and fromTrack
+ * may be not be synchronized. For example PatchPanel may not obtain the
+ * thread lock before calling.
+ *
+ * \param latencyMs on success is set to the latency in milliseconds of the
+ * next frame written/read by the client app to/from the track buffer
+ * from the device sink/source.
+ * \param fromTrack on success is set to true if latency was computed directly
+ * from the track timestamp; otherwise set to false if latency was
+ * estimated from the server timestamp.
+ * fromTrack may be nullptr or omitted if not required.
+ *
+ * \returns OK or INVALID_OPERATION on failure.
+ */
+ status_t getTrackLatencyMs(double* latencyMs, bool* fromTrack = nullptr) const {
double serverLatencyMs;
status_t status = getServerLatencyMs(&serverLatencyMs, fromTrack);
if (status == OK) {
@@ -197,21 +169,15 @@
return status;
}
- // TODO: Consider making this external.
- struct FrameTime {
- int64_t frames;
- int64_t timeNs;
- };
-
- // KernelFrameTime is updated per "mix" period even for non-pcm tracks.
- void getKernelFrameTime(FrameTime *ft) const {
+ // KernelFrameTime is updated per "mix" period even for non-pcm tracks.
+ void getKernelFrameTime(FrameTime* ft) const final {
*ft = mKernelFrameTime.load();
}
- audio_format_t format() const { return mFormat; }
- int id() const { return mId; }
+ audio_format_t format() const final { return mFormat; }
+ int id() const final { return mId; }
- const char *getTrackStateAsString() const {
+ const char* getTrackStateAsString() const final {
if (isTerminated()) {
return "TERMINATED";
}
@@ -245,19 +211,19 @@
// Called by the PlaybackThread to indicate that the track is becoming active
// and a new interval should start with a given device list.
- void logBeginInterval(const std::string& devices) {
+ void logBeginInterval(const std::string& devices) final {
mTrackMetrics.logBeginInterval(devices);
}
// Called by the PlaybackThread to indicate the track is no longer active.
- void logEndInterval() {
+ void logEndInterval() final {
mTrackMetrics.logEndInterval();
}
// Called to tally underrun frames in playback.
- virtual void tallyUnderrunFrames(size_t /* frames */) {}
+ void tallyUnderrunFrames(size_t /* frames */) override {}
- audio_channel_mask_t channelMask() const { return mChannelMask; }
+ audio_channel_mask_t channelMask() const final { return mChannelMask; }
/** @return true if the track has changed (metadata or volume) since
* the last time this function was called,
@@ -265,10 +231,10 @@
* false otherwise.
* Thread safe.
*/
- bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
+ bool readAndClearHasChanged() final { return !mChangeNotified.test_and_set(); }
/** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
- void setMetadataHasChanged() { mChangeNotified.clear(); }
+ void setMetadataHasChanged() final { mChangeNotified.clear(); }
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -285,31 +251,31 @@
}
// AudioBufferProvider interface
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
- virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+ // status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
+ void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
// ExtendedAudioBufferProvider interface is only needed for Track,
// but putting it in TrackBase avoids the complexity of virtual inheritance
- virtual size_t framesReady() const { return SIZE_MAX; }
+ size_t framesReady() const override { return SIZE_MAX; } // MmapTrack doesn't implement.
uint32_t channelCount() const { return mChannelCount; }
- size_t frameSize() const { return mFrameSize; }
+ size_t frameSize() const final { return mFrameSize; }
- virtual uint32_t sampleRate() const { return mSampleRate; }
+ uint32_t sampleRate() const override { return mSampleRate; }
- bool isStopped() const {
+ bool isStopped() const final {
return (mState == STOPPED || mState == FLUSHED);
}
// for fast tracks and offloaded tracks only
- bool isStopping() const {
+ bool isStopping() const final {
return mState == STOPPING_1 || mState == STOPPING_2;
}
- bool isStopping_1() const {
+ bool isStopping_1() const final {
return mState == STOPPING_1;
}
- bool isStopping_2() const {
+ bool isStopping_2() const final {
return mState == STOPPING_2;
}
@@ -351,7 +317,7 @@
// true for Track, false for RecordTrack,
// this could be a track type if needed later
- const wp<ThreadBase> mThread;
+ const wp<IAfThreadBase> mThread;
const alloc_type mAllocType;
/*const*/ sp<Client> mClient; // see explanation at ~TrackBase() why not const
sp<IMemory> mCblkMemory;
@@ -415,37 +381,28 @@
std::atomic_flag mChangeNotified = ATOMIC_FLAG_INIT;
};
-// PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord.
-// it provides buffer access methods that map those of a ClientProxy (see AudioTrackShared.h)
-class PatchProxyBufferProvider
+class PatchTrackBase : public PatchProxyBufferProvider, public virtual IAfPatchTrackBase
{
public:
-
- virtual ~PatchProxyBufferProvider() {}
-
- virtual bool producesBufferOnDemand() const = 0;
- virtual status_t obtainBuffer(Proxy::Buffer* buffer,
- const struct timespec *requested = NULL) = 0;
- virtual void releaseBuffer(Proxy::Buffer* buffer) = 0;
-};
-
-class PatchTrackBase : public PatchProxyBufferProvider
-{
-public:
- using Timeout = std::optional<std::chrono::nanoseconds>;
- PatchTrackBase(const sp<ClientProxy>& proxy, const ThreadBase& thread,
+ PatchTrackBase(const sp<ClientProxy>& proxy,
+ IAfThreadBase* thread,
const Timeout& timeout);
- void setPeerTimeout(std::chrono::nanoseconds timeout);
- template <typename T>
- void setPeerProxy(const sp<T> &proxy, bool holdReference) {
- mPeerReferenceHold = holdReference ? proxy : nullptr;
- mPeerProxy = proxy.get();
- }
- void clearPeerProxy() {
+ void setPeerTimeout(std::chrono::nanoseconds timeout) final;
+ void setPeerProxy(const sp<IAfPatchTrackBase>& proxy, bool holdReference) final {
+ if (proxy) {
+ mPeerReferenceHold = holdReference ? proxy : nullptr;
+ mPeerProxy = proxy->asPatchProxyBufferProvider();
+ } else {
+ clearPeerProxy();
+ }
+ }
+ void clearPeerProxy() final {
mPeerReferenceHold.clear();
mPeerProxy = nullptr;
}
+ PatchProxyBufferProvider* asPatchProxyBufferProvider() final { return this; }
+
bool producesBufferOnDemand() const override { return false; }
protected:
@@ -453,5 +410,6 @@
sp<RefBase> mPeerReferenceHold; // keeps mPeerProxy alive during access.
PatchProxyBufferProvider* mPeerProxy = nullptr;
struct timespec mPeerTimeout{};
-
};
+
+} // namespace android
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 30c8240..31246ec 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -15,28 +15,33 @@
** limitations under the License.
*/
-
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_AUDIO
-#include "Configuration.h"
-#include <linux/futex.h>
-#include <math.h>
-#include <sys/syscall.h>
+#include "MmapTracks.h"
+#include "PlaybackTracks.h"
+#include "RecordTracks.h"
+
+#include "Client.h"
+#include "IAfEffect.h"
+#include "IAfThread.h"
+#include "ResamplerBufferProvider.h"
+
+#include <audio_utils/minifloat.h>
+#include <media/AudioValidator.h>
+#include <media/RecordBufferConverter.h>
+#include <media/nbaio/Pipe.h>
+#include <media/nbaio/PipeReader.h>
+#include <mediautils/ServiceUtilities.h>
+#include <mediautils/SharedMemoryAllocator.h>
+#include <private/media/AudioTrackShared.h>
#include <utils/Log.h>
#include <utils/Trace.h>
-#include <private/media/AudioTrackShared.h>
-
-#include "AudioFlinger.h"
-
-#include <media/nbaio/Pipe.h>
-#include <media/nbaio/PipeReader.h>
-#include <media/AudioValidator.h>
-#include <media/RecordBufferConverter.h>
-#include <mediautils/ServiceUtilities.h>
-#include <audio_utils/minifloat.h>
+#include <linux/futex.h>
+#include <math.h>
+#include <sys/syscall.h>
// ----------------------------------------------------------------------------
@@ -76,8 +81,8 @@
static volatile int32_t nextTrackId = 55;
// TrackBase constructor must be called with AudioFlinger::mLock held
-AudioFlinger::ThreadBase::TrackBase::TrackBase(
- ThreadBase *thread,
+TrackBase::TrackBase(
+ IAfThreadBase *thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
@@ -94,7 +99,7 @@
track_type type,
audio_port_handle_t portId,
std::string metricsId)
- : RefBase(),
+ :
mThread(thread),
mAllocType(alloc),
mClient(client),
@@ -253,7 +258,7 @@
return attributionSource;
}
-status_t AudioFlinger::ThreadBase::TrackBase::initCheck() const
+status_t TrackBase::initCheck() const
{
status_t status;
if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
@@ -264,7 +269,7 @@
return status;
}
-AudioFlinger::ThreadBase::TrackBase::~TrackBase()
+TrackBase::~TrackBase()
{
// delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
mServerProxy.clear();
@@ -272,7 +277,7 @@
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
if (mClient != 0) {
// Client destructor must run with AudioFlinger client mutex locked
- Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
+ audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
// If the client's reference count drops to zero, the associated destructor
// must run with AudioFlinger lock held. Thus the explicit clear() rather than
// relying on the automatic clear() at end of scope.
@@ -289,7 +294,7 @@
// AudioBufferProvider interface
// getNextBuffer() = 0;
// This implementation of releaseBuffer() is used by Track and RecordTrack
-void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
{
#ifdef TEE_SINK
mTee.write(buffer->raw, buffer->frameCount);
@@ -303,29 +308,28 @@
mServerProxy->releaseBuffer(&buf);
}
-status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(
+status_t TrackBase::setSyncEvent(
const sp<audioflinger::SyncEvent>& event)
{
mSyncEvents.emplace_back(event);
return NO_ERROR;
}
-AudioFlinger::ThreadBase::PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
- const ThreadBase& thread,
- const Timeout& timeout)
+PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
+ IAfThreadBase* thread, const Timeout& timeout)
: mProxy(proxy)
{
if (timeout) {
setPeerTimeout(*timeout);
} else {
// Double buffer mixer
- uint64_t mixBufferNs = ((uint64_t)2 * thread.frameCount() * 1000000000) /
- thread.sampleRate();
+ uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
+ thread->sampleRate();
setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
}
}
-void AudioFlinger::ThreadBase::PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
+void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
}
@@ -337,14 +341,58 @@
#undef LOG_TAG
#define LOG_TAG "AF::TrackHandle"
-AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
+class TrackHandle : public android::media::BnAudioTrack {
+public:
+ explicit TrackHandle(const sp<IAfTrack>& track);
+ ~TrackHandle() override;
+
+ binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
+ binder::Status start(int32_t* _aidl_return) final;
+ binder::Status stop() final;
+ binder::Status flush() final;
+ binder::Status pause() final;
+ binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
+ binder::Status setParameters(const std::string& keyValuePairs,
+ int32_t* _aidl_return) final;
+ binder::Status selectPresentation(int32_t presentationId, int32_t programId,
+ int32_t* _aidl_return) final;
+ binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
+ int32_t* _aidl_return) final;
+ binder::Status signal() final;
+ binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
+ const media::VolumeShaperOperation& operation,
+ int32_t* _aidl_return) final;
+ binder::Status getVolumeShaperState(
+ int32_t id,
+ std::optional<media::VolumeShaperState>* _aidl_return) final;
+ binder::Status getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return) final;
+ binder::Status setDualMonoMode(
+ media::audio::common::AudioDualMonoMode mode) final;
+ binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
+ binder::Status setAudioDescriptionMixLevel(float leveldB) final;
+ binder::Status getPlaybackRateParameters(
+ media::audio::common::AudioPlaybackRate* _aidl_return) final;
+ binder::Status setPlaybackRateParameters(
+ const media::audio::common::AudioPlaybackRate& playbackRate) final;
+
+private:
+ const sp<IAfTrack> mTrack;
+};
+
+/* static */
+sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
+ return sp<TrackHandle>::make(track);
+}
+
+TrackHandle::TrackHandle(const sp<IAfTrack>& track)
: BnAudioTrack(),
mTrack(track)
{
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
-AudioFlinger::TrackHandle::~TrackHandle() {
+TrackHandle::~TrackHandle() {
// just stop the track on deletion, associated resources
// will be freed from the main thread once all pending buffers have
// been played. Unless it's not in the active track list, in which
@@ -352,51 +400,51 @@
mTrack->destroy();
}
-Status AudioFlinger::TrackHandle::getCblk(
+Status TrackHandle::getCblk(
std::optional<media::SharedFileRegion>* _aidl_return) {
*_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
return Status::ok();
}
-Status AudioFlinger::TrackHandle::start(int32_t* _aidl_return) {
+Status TrackHandle::start(int32_t* _aidl_return) {
*_aidl_return = mTrack->start();
return Status::ok();
}
-Status AudioFlinger::TrackHandle::stop() {
+Status TrackHandle::stop() {
mTrack->stop();
return Status::ok();
}
-Status AudioFlinger::TrackHandle::flush() {
+Status TrackHandle::flush() {
mTrack->flush();
return Status::ok();
}
-Status AudioFlinger::TrackHandle::pause() {
+Status TrackHandle::pause() {
mTrack->pause();
return Status::ok();
}
-Status AudioFlinger::TrackHandle::attachAuxEffect(int32_t effectId,
+Status TrackHandle::attachAuxEffect(int32_t effectId,
int32_t* _aidl_return) {
*_aidl_return = mTrack->attachAuxEffect(effectId);
return Status::ok();
}
-Status AudioFlinger::TrackHandle::setParameters(const std::string& keyValuePairs,
+Status TrackHandle::setParameters(const std::string& keyValuePairs,
int32_t* _aidl_return) {
*_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
return Status::ok();
}
-Status AudioFlinger::TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
+Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
int32_t* _aidl_return) {
*_aidl_return = mTrack->selectPresentation(presentationId, programId);
return Status::ok();
}
-Status AudioFlinger::TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
+Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
int32_t* _aidl_return) {
AudioTimestamp legacy;
*_aidl_return = mTrack->getTimestamp(legacy);
@@ -407,12 +455,12 @@
return Status::ok();
}
-Status AudioFlinger::TrackHandle::signal() {
+Status TrackHandle::signal() {
mTrack->signal();
return Status::ok();
}
-Status AudioFlinger::TrackHandle::applyVolumeShaper(
+Status TrackHandle::applyVolumeShaper(
const media::VolumeShaperConfiguration& configuration,
const media::VolumeShaperOperation& operation,
int32_t* _aidl_return) {
@@ -432,7 +480,7 @@
return Status::ok();
}
-Status AudioFlinger::TrackHandle::getVolumeShaperState(
+Status TrackHandle::getVolumeShaperState(
int32_t id,
std::optional<media::VolumeShaperState>* _aidl_return) {
sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
@@ -446,7 +494,7 @@
return Status::ok();
}
-Status AudioFlinger::TrackHandle::getDualMonoMode(
+Status TrackHandle::getDualMonoMode(
media::audio::common::AudioDualMonoMode* _aidl_return)
{
audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
@@ -459,7 +507,7 @@
return binderStatusFromStatusT(status);
}
-Status AudioFlinger::TrackHandle::setDualMonoMode(
+Status TrackHandle::setDualMonoMode(
media::audio::common::AudioDualMonoMode mode)
{
const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
@@ -468,7 +516,7 @@
?: mTrack->setDualMonoMode(localMonoMode));
}
-Status AudioFlinger::TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
+Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
{
float leveldB = -std::numeric_limits<float>::infinity();
const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
@@ -477,13 +525,13 @@
return binderStatusFromStatusT(status);
}
-Status AudioFlinger::TrackHandle::setAudioDescriptionMixLevel(float leveldB)
+Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
{
return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
?: mTrack->setAudioDescriptionMixLevel(leveldB));
}
-Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
+Status TrackHandle::getPlaybackRateParameters(
media::audio::common::AudioPlaybackRate* _aidl_return)
{
audio_playback_rate_t localPlaybackRate{};
@@ -496,7 +544,7 @@
return binderStatusFromStatusT(status);
}
-Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
+Status TrackHandle::setPlaybackRateParameters(
const media::audio::common::AudioPlaybackRate& playbackRate)
{
const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
@@ -510,9 +558,8 @@
// -------------------------------
// static
-sp<AudioFlinger::PlaybackThread::OpPlayAudioMonitor>
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
- AudioFlinger::ThreadBase* thread,
+sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
+ IAfThreadBase* thread,
const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
audio_stream_type_t streamType)
{
@@ -542,11 +589,10 @@
return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
}
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
- AudioFlinger::ThreadBase* thread,
- const AttributionSourceState& attributionSource,
- audio_usage_t usage, int id, uid_t uid)
- : mThread(wp<AudioFlinger::ThreadBase>::fromExisting(thread)),
+OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
+ const AttributionSourceState& attributionSource,
+ audio_usage_t usage, int id, uid_t uid)
+ : mThread(wp<IAfThreadBase>::fromExisting(thread)),
mHasOpPlayAudio(true),
mAttributionSource(attributionSource),
mUsage((int32_t)usage),
@@ -555,7 +601,7 @@
mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
attributionSource.packageName.value_or("")))) {}
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::~OpPlayAudioMonitor()
+OpPlayAudioMonitor::~OpPlayAudioMonitor()
{
if (mOpCallback != 0) {
mAppOpsManager.stopWatchingMode(mOpCallback);
@@ -563,7 +609,7 @@
mOpCallback.clear();
}
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
+void OpPlayAudioMonitor::onFirstRef()
{
// make sure not to broadcast the initial state since it is not needed and could
// cause a deadlock since this method can be called with the mThread->mLock held
@@ -575,14 +621,14 @@
}
}
-bool AudioFlinger::PlaybackThread::OpPlayAudioMonitor::hasOpPlayAudio() const {
+bool OpPlayAudioMonitor::hasOpPlayAudio() const {
return mHasOpPlayAudio.load();
}
// Note this method is never called (and never to be) for audio server / patch record track
// - not called from constructor due to check on UID,
// - not called from PlayAudioOpCallback because the callback is not installed in this case
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
+void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
{
const bool hasAppOps = mAttributionSource.packageName.has_value()
&& mAppOpsManager.checkAudioOpNoThrow(
@@ -594,20 +640,20 @@
ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
if (doBroadcast) {
auto thread = mThread.promote();
- if (thread != nullptr && thread->type() == AudioFlinger::ThreadBase::OFFLOAD) {
+ if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
// Wake up Thread if offloaded, otherwise it may be several seconds for update.
- Mutex::Autolock _l(thread->mLock);
+ audio_utils::lock_guard _l(thread->mutex());
thread->broadcast_l();
}
}
}
}
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
+OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
{ }
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
+void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
const String16& packageName) {
// we only have uid, so we need to check all package names anyway
UNUSED(packageName);
@@ -621,7 +667,7 @@
}
// static
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::getPackagesForUid(
+void OpPlayAudioMonitor::getPackagesForUid(
uid_t uid, Vector<String16>& packages)
{
PermissionController permissionController;
@@ -632,9 +678,57 @@
#undef LOG_TAG
#define LOG_TAG "AF::Track"
+/* static */
+sp<IAfTrack> IAfTrack::create(
+ IAfPlaybackThread* thread,
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ const audio_attributes_t& attr,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount,
+ void *buffer,
+ size_t bufferSize,
+ const sp<IMemory>& sharedBuffer,
+ audio_session_t sessionId,
+ pid_t creatorPid,
+ const AttributionSourceState& attributionSource,
+ audio_output_flags_t flags,
+ track_type type,
+ audio_port_handle_t portId,
+ /** default behaviour is to start when there are as many frames
+ * ready as possible (aka. Buffer is full). */
+ size_t frameCountToBeReady,
+ float speed,
+ bool isSpatialized,
+ bool isBitPerfect) {
+ return sp<Track>::make(thread,
+ client,
+ streamType,
+ attr,
+ sampleRate,
+ format,
+ channelMask,
+ frameCount,
+ buffer,
+ bufferSize,
+ sharedBuffer,
+ sessionId,
+ creatorPid,
+ attributionSource,
+ flags,
+ type,
+ portId,
+ frameCountToBeReady,
+ speed,
+ isSpatialized,
+ isBitPerfect);
+}
+
// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
-AudioFlinger::PlaybackThread::Track::Track(
- PlaybackThread *thread,
+Track::Track(
+ IAfPlaybackThread* thread,
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
@@ -668,7 +762,7 @@
type,
portId,
std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
- mFillingUpStatus(FS_INVALID),
+ mFillingStatus(FS_INVALID),
// mRetryCount initialized later when needed
mSharedBuffer(sharedBuffer),
mStreamType(streamType),
@@ -725,15 +819,15 @@
// race with setSyncEvent(). However, if we call it, we cannot properly start
// static fast tracks (SoundPool) immediately after stopping.
//mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
- ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
- int i = __builtin_ctz(thread->mFastTrackAvailMask);
+ ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
+ const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
// FIXME This is too eager. We allocate a fast track index before the
// fast track becomes active. Since fast tracks are a scarce resource,
// this means we are potentially denying other more important fast tracks from
// being created. It would be better to allocate the index dynamically.
mFastIndex = i;
- thread->mFastTrackAvailMask &= ~(1 << i);
+ thread->fastTrackAvailMask_l() &= ~(1 << i);
}
mServerLatencySupported = checkServerLatencySupported(format, flags);
@@ -758,7 +852,7 @@
mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
}
-AudioFlinger::PlaybackThread::Track::~Track()
+Track::~Track()
{
ALOGV("%s(%d)", __func__, mId);
@@ -771,7 +865,7 @@
}
}
-status_t AudioFlinger::PlaybackThread::Track::initCheck() const
+status_t Track::initCheck() const
{
status_t status = TrackBase::initCheck();
if (status == NO_ERROR && mCblk == nullptr) {
@@ -780,7 +874,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::Track::destroy()
+void Track::destroy()
{
// NOTE: destroyTrack_l() can remove a strong reference to this Track
// by removing it from mTracks vector, so there is a risk that this Tracks's
@@ -793,10 +887,10 @@
sp<Track> keep(this);
{ // scope for mLock
bool wasActive = false;
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ audio_utils::lock_guard _l(thread->mutex());
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
wasActive = playbackThread->destroyTrack_l(this);
}
if (isExternalTrack() && !wasActive) {
@@ -806,7 +900,7 @@
forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
}
-void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
+void Track::appendDumpHeader(String8& result) const
{
result.appendFormat("Type Id Active Client Session Port Id S Flags "
" Format Chn mask SRate "
@@ -817,7 +911,7 @@
isServerLatencySupported() ? " Latency" : "");
}
-void AudioFlinger::PlaybackThread::Track::appendDump(String8& result, bool active)
+void Track::appendDump(String8& result, bool active) const
{
char trackType;
switch (mType) {
@@ -859,7 +953,7 @@
}
char fillingStatus;
- switch (mFillingUpStatus) {
+ switch (mFillingStatus) {
case FS_INVALID:
fillingStatus = 'I';
break;
@@ -945,12 +1039,12 @@
result.append("\n");
}
-uint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const {
+uint32_t Track::sampleRate() const {
return mAudioTrackServerProxy->getSampleRate();
}
// AudioBufferProvider interface
-status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
{
ServerProxy::Buffer buf;
size_t desiredFrames = buffer->frameCount;
@@ -968,14 +1062,14 @@
return status;
}
-void AudioFlinger::PlaybackThread::Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
{
interceptBuffer(*buffer);
TrackBase::releaseBuffer(buffer);
}
// TODO: compensate for time shift between HW modules.
-void AudioFlinger::PlaybackThread::Track::interceptBuffer(
+void Track::interceptBuffer(
const AudioBufferProvider::Buffer& sourceBuffer) {
auto start = std::chrono::steady_clock::now();
const size_t frameCount = sourceBuffer.frameCount;
@@ -985,12 +1079,12 @@
// does not allow 0 frame size request contrary to getNextBuffer
}
for (auto& teePatch : mTeePatches) {
- RecordThread::PatchRecord* patchRecord = teePatch.patchRecord.get();
+ IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
const size_t framesWritten = patchRecord->writeFrames(
sourceBuffer.i8, frameCount, mFrameSize);
const size_t framesLeft = frameCount - framesWritten;
ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
- "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->mId,
+ "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
framesWritten, frameCount, framesLeft);
}
auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
@@ -1006,7 +1100,7 @@
// from a different thread than the one calling Proxy->obtainBuffer() and
// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
// AudioTrackServerProxy so be especially careful calling with FastTracks.
-size_t AudioFlinger::PlaybackThread::Track::framesReady() const {
+size_t Track::framesReady() const {
if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
// Static tracks return zero frames immediately upon stopping (for FastTracks).
// The remainder of the buffer is not drained.
@@ -1015,12 +1109,12 @@
return mAudioTrackServerProxy->framesReady();
}
-int64_t AudioFlinger::PlaybackThread::Track::framesReleased() const
+int64_t Track::framesReleased() const
{
return mAudioTrackServerProxy->framesReleased();
}
-void AudioFlinger::PlaybackThread::Track::onTimestamp(const ExtendedTimestamp ×tamp)
+void Track::onTimestamp(const ExtendedTimestamp ×tamp)
{
// This call comes from a FastTrack and should be kept lockless.
// The server side frames are already translated to client frames.
@@ -1037,14 +1131,14 @@
}
// Don't call for fast tracks; the framesReady() could result in priority inversion
-bool AudioFlinger::PlaybackThread::Track::isReady() const {
- if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
+bool Track::isReady() const {
+ if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
return true;
}
if (isStopping()) {
if (framesReady() > 0) {
- mFillingUpStatus = FS_FILLED;
+ mFillingStatus = FS_FILLED;
}
return true;
}
@@ -1058,33 +1152,33 @@
if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
__func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
- mFillingUpStatus = FS_FILLED;
+ mFillingStatus = FS_FILLED;
android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
return true;
}
return false;
}
-status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused,
+status_t Track::start(AudioSystem::sync_event_t event __unused,
audio_session_t triggerSession __unused)
{
status_t status = NO_ERROR;
ALOGV("%s(%d): calling pid %d session %d",
__func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
if (isOffloaded()) {
- Mutex::Autolock _laf(thread->mAudioFlinger->mLock);
- Mutex::Autolock _lth(thread->mLock);
- sp<EffectChain> ec = thread->getEffectChain_l(mSessionId);
- if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
+ audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
+ audio_utils::lock_guard _lth(thread->mutex());
+ sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
+ if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
(ec != 0 && ec->isNonOffloadableEnabled())) {
invalidate();
return PERMISSION_DENIED;
}
}
- Mutex::Autolock _lth(thread->mLock);
+ audio_utils::lock_guard _lth(thread->mutex());
track_state state = mState;
// here the track could be either new, or restarted
// in both cases "unstop" the track
@@ -1116,7 +1210,7 @@
__func__, mId, (int)mThreadIoHandle);
}
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
// states to reset position info for pcm tracks
if (audio_is_linear_pcm(mFormat)
@@ -1183,7 +1277,8 @@
forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
// send format to AudioManager for playback activity monitoring
- sp<IAudioManager> audioManager = thread->mAudioFlinger->getOrCreateAudioManager();
+ const sp<IAudioManager> audioManager =
+ thread->afThreadCallback()->getOrCreateAudioManager();
if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
std::unique_ptr<os::PersistableBundle> bundle =
std::make_unique<os::PersistableBundle>();
@@ -1202,17 +1297,17 @@
return status;
}
-void AudioFlinger::PlaybackThread::Track::stop()
+void Track::stop()
{
ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
+ audio_utils::lock_guard _l(thread->mutex());
track_state state = mState;
if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
// If the track is not active (PAUSED and buffers full), flush buffers
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
+ if (!playbackThread->isTrackActive(this)) {
reset();
mState = STOPPED;
} else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
@@ -1224,7 +1319,7 @@
// move to STOPPING_2 when drain completes and then STOPPED
mState = STOPPING_1;
if (isOffloaded()) {
- mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload;
+ mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
}
}
playbackThread->broadcast_l();
@@ -1235,13 +1330,13 @@
forEachTeePatchTrack([](auto patchTrack) { patchTrack->stop(); });
}
-void AudioFlinger::PlaybackThread::Track::pause()
+void Track::pause()
{
ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ audio_utils::lock_guard _l(thread->mutex());
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
switch (mState) {
case STOPPING_1:
case STOPPING_2:
@@ -1272,18 +1367,18 @@
forEachTeePatchTrack([](auto patchTrack) { patchTrack->pause(); });
}
-void AudioFlinger::PlaybackThread::Track::flush()
+void Track::flush()
{
ALOGV("%s(%d)", __func__, mId);
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ audio_utils::lock_guard _l(thread->mutex());
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
// Flush the ring buffer now if the track is not active in the PlaybackThread.
// Otherwise the flush would not be done until the track is resumed.
// Requires FastTrack removal be BLOCK_UNTIL_ACKED
- if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+ if (!playbackThread->isTrackActive(this)) {
(void)mServerProxy->flushBufferIfNeeded();
}
@@ -1322,7 +1417,7 @@
if (isDirect()) {
mFlushHwPending = true;
}
- if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+ if (!playbackThread->isTrackActive(this)) {
reset();
}
}
@@ -1336,7 +1431,7 @@
}
// must be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::flushAck()
+void Track::flushAck()
{
if (!isOffloaded() && !isDirect()) {
return;
@@ -1349,12 +1444,12 @@
mFlushHwPending = false;
}
-void AudioFlinger::PlaybackThread::Track::pauseAck()
+void Track::pauseAck()
{
mPauseHwPending = false;
}
-void AudioFlinger::PlaybackThread::Track::reset()
+void Track::reset()
{
// Do not reset twice to avoid discarding data written just after a flush and before
// the audioflinger thread detects the track is stopped.
@@ -1362,7 +1457,7 @@
// Force underrun condition to avoid false underrun callback until first data is
// written to buffer
android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
- mFillingUpStatus = FS_FILLING;
+ mFillingStatus = FS_FILLING;
mResetDone = true;
if (mState == FLUSHED) {
mState = IDLE;
@@ -1370,34 +1465,35 @@
}
}
-status_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyValuePairs)
+status_t Track::setParameters(const String8& keyValuePairs)
{
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread == 0) {
ALOGE("%s(%d): thread is dead", __func__, mId);
return FAILED_TRANSACTION;
- } else if ((thread->type() == ThreadBase::DIRECT) ||
- (thread->type() == ThreadBase::OFFLOAD)) {
+ } else if (thread->type() == IAfThreadBase::DIRECT
+ || thread->type() == IAfThreadBase::OFFLOAD) {
return thread->setParameters(keyValuePairs);
} else {
return PERMISSION_DENIED;
}
}
-status_t AudioFlinger::PlaybackThread::Track::selectPresentation(int presentationId,
+status_t Track::selectPresentation(int presentationId,
int programId) {
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread == 0) {
ALOGE("thread is dead");
return FAILED_TRANSACTION;
- } else if ((thread->type() == ThreadBase::DIRECT) || (thread->type() == ThreadBase::OFFLOAD)) {
- DirectOutputThread *directOutputThread = static_cast<DirectOutputThread*>(thread.get());
+ } else if (thread->type() == IAfThreadBase::DIRECT
+ || thread->type() == IAfThreadBase::OFFLOAD) {
+ auto directOutputThread = thread->asIAfDirectOutputThread().get();
return directOutputThread->selectPresentation(presentationId, programId);
}
return INVALID_OPERATION;
}
-VolumeShaper::Status AudioFlinger::PlaybackThread::Track::applyVolumeShaper(
+VolumeShaper::Status Track::applyVolumeShaper(
const sp<VolumeShaper::Configuration>& configuration,
const sp<VolumeShaper::Operation>& operation)
{
@@ -1405,16 +1501,16 @@
if (isOffloadedOrDirect()) {
// Signal thread to fetch new volume.
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
+ audio_utils::lock_guard _l(thread->mutex());
thread->broadcast_l();
}
}
return status;
}
-sp<VolumeShaper::State> AudioFlinger::PlaybackThread::Track::getVolumeShaperState(int id)
+sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
{
// Note: We don't check if Thread exists.
@@ -1422,7 +1518,7 @@
return mVolumeHandler->getVolumeShaperState(id);
}
-void AudioFlinger::PlaybackThread::Track::setFinalVolume(float volumeLeft, float volumeRight)
+void Track::setFinalVolume(float volumeLeft, float volumeRight)
{
mFinalVolumeLeft = volumeLeft;
mFinalVolumeRight = volumeRight;
@@ -1438,7 +1534,7 @@
}
}
-void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
+void Track::copyMetadataTo(MetadataInserter& backInserter) const
{
// Do not forward metadata for PatchTrack with unspecified stream type
if (mStreamType == AUDIO_STREAM_PATCH) {
@@ -1510,7 +1606,7 @@
*backInserter++ = metadata;
}
-void AudioFlinger::PlaybackThread::Track::updateTeePatches() {
+void Track::updateTeePatches() {
if (mTeePatchesToUpdate.has_value()) {
forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
mTeePatches = mTeePatchesToUpdate.value();
@@ -1522,14 +1618,14 @@
}
}
-void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
+void Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
ALOGW_IF(mTeePatchesToUpdate.has_value(),
"%s, existing tee patches to update will be ignored", __func__);
mTeePatchesToUpdate = std::move(teePatchesToUpdate);
}
// must be called with player thread lock held
-void AudioFlinger::PlaybackThread::Track::processMuteEvent_l(const sp<
+void Track::processMuteEvent_l(const sp<
IAudioManager>& audioManager, mute_state_t muteState)
{
if (mMuteState == muteState) {
@@ -1561,31 +1657,32 @@
}
}
-status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp)
+status_t Track::getTimestamp(AudioTimestamp& timestamp)
{
if (!isOffloaded() && !isDirect()) {
return INVALID_OPERATION; // normal tracks handled through SSQ
}
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread == 0) {
return INVALID_OPERATION;
}
- Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ audio_utils::lock_guard _l(thread->mutex());
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
return playbackThread->getTimestamp_l(timestamp);
}
-status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
+status_t Track::attachAuxEffect(int EffectId)
{
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread == nullptr) {
return DEAD_OBJECT;
}
- sp<PlaybackThread> dstThread = (PlaybackThread *)thread.get();
- sp<PlaybackThread> srcThread; // srcThread is initialized by call to moveAuxEffectToIo()
- sp<AudioFlinger> af = mClient->audioFlinger();
+ auto dstThread = thread->asIAfPlaybackThread();
+ // srcThread is initialized by call to moveAuxEffectToIo()
+ sp<IAfPlaybackThread> srcThread;
+ const auto& af = mClient->afClientCallback();
status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
if (EffectId != 0 && status == NO_ERROR) {
@@ -1601,14 +1698,14 @@
return status;
}
-void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
+void Track::setAuxBuffer(int EffectId, int32_t *buffer)
{
mAuxEffectId = EffectId;
mAuxBuffer = buffer;
}
// presentationComplete verified by frames, used by Mixed tracks.
-bool AudioFlinger::PlaybackThread::Track::presentationComplete(
+bool Track::presentationComplete(
int64_t framesWritten, size_t audioHalFrames)
{
// TODO: improve this based on FrameMap if it exists, to ensure full drain.
@@ -1651,7 +1748,7 @@
}
// presentationComplete checked by time, used by DirectTracks.
-bool AudioFlinger::PlaybackThread::Track::presentationComplete(uint32_t latencyMs)
+bool Track::presentationComplete(uint32_t latencyMs)
{
// For Offloaded or Direct tracks.
@@ -1683,14 +1780,14 @@
return false;
}
-void AudioFlinger::PlaybackThread::Track::notifyPresentationComplete()
+void Track::notifyPresentationComplete()
{
// This only triggers once. TODO: should we enforce this?
triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
mAudioTrackServerProxy->setStreamEndDone();
}
-void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
+void Track::triggerEvents(AudioSystem::sync_event_t type)
{
for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
if ((*it)->type() == type) {
@@ -1705,7 +1802,7 @@
// implement VolumeBufferProvider interface
-gain_minifloat_packed_t AudioFlinger::PlaybackThread::Track::getVolumeLR()
+gain_minifloat_packed_t Track::getVolumeLR() const
{
// called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
@@ -1730,7 +1827,7 @@
return vlr;
}
-status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(
+status_t Track::setSyncEvent(
const sp<audioflinger::SyncEvent>& event)
{
if (isTerminated() || mState == PAUSED ||
@@ -1746,19 +1843,19 @@
return NO_ERROR;
}
-void AudioFlinger::PlaybackThread::Track::invalidate()
+void Track::invalidate()
{
TrackBase::invalidate();
signalClientFlag(CBLK_INVALID);
}
-void AudioFlinger::PlaybackThread::Track::disable()
+void Track::disable()
{
// TODO(b/142394888): the filling status should also be reset to filling
signalClientFlag(CBLK_DISABLED);
}
-void AudioFlinger::PlaybackThread::Track::signalClientFlag(int32_t flag)
+void Track::signalClientFlag(int32_t flag)
{
// FIXME should use proxy, and needs work
audio_track_cblk_t* cblk = mCblk;
@@ -1768,25 +1865,25 @@
(void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
}
-void AudioFlinger::PlaybackThread::Track::signal()
+void Track::signal()
{
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- PlaybackThread *t = (PlaybackThread *)thread.get();
- Mutex::Autolock _l(t->mLock);
+ auto* const t = thread->asIAfPlaybackThread().get();
+ audio_utils::lock_guard _l(t->mutex());
t->broadcast_l();
}
}
-status_t AudioFlinger::PlaybackThread::Track::getDualMonoMode(audio_dual_mono_mode_t* mode)
+status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- PlaybackThread *t = (PlaybackThread *)thread.get();
- Mutex::Autolock _l(t->mLock);
- status = t->mOutput->stream->getDualMonoMode(mode);
+ auto* const t = thread->asIAfPlaybackThread().get();
+ audio_utils::lock_guard _l(t->mutex());
+ status = t->getOutput_l()->stream->getDualMonoMode(mode);
ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
"%s: mode %d inconsistent", __func__, mDualMonoMode);
}
@@ -1794,15 +1891,15 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::Track::setDualMonoMode(audio_dual_mono_mode_t mode)
+status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
- Mutex::Autolock lock(t->mLock);
- status = t->mOutput->stream->setDualMonoMode(mode);
+ auto* const t = thread->asIAfPlaybackThread().get();
+ audio_utils::lock_guard lock(t->mutex());
+ status = t->getOutput_l()->stream->setDualMonoMode(mode);
if (status == NO_ERROR) {
mDualMonoMode = mode;
}
@@ -1811,15 +1908,15 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::Track::getAudioDescriptionMixLevel(float* leveldB)
+status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
- Mutex::Autolock lock(t->mLock);
- status = t->mOutput->stream->getAudioDescriptionMixLevel(leveldB);
+ auto* const t = thread->asIAfPlaybackThread().get();
+ audio_utils::lock_guard lock(t->mutex());
+ status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
"%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
}
@@ -1827,15 +1924,15 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::Track::setAudioDescriptionMixLevel(float leveldB)
+status_t Track::setAudioDescriptionMixLevel(float leveldB)
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
- Mutex::Autolock lock(t->mLock);
- status = t->mOutput->stream->setAudioDescriptionMixLevel(leveldB);
+ auto* const t = thread->asIAfPlaybackThread().get();
+ audio_utils::lock_guard lock(t->mutex());
+ status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
if (status == NO_ERROR) {
mAudioDescriptionMixLevel = leveldB;
}
@@ -1844,16 +1941,16 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::Track::getPlaybackRateParameters(
- audio_playback_rate_t* playbackRate)
+status_t Track::getPlaybackRateParameters(
+ audio_playback_rate_t* playbackRate) const
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
- Mutex::Autolock lock(t->mLock);
- status = t->mOutput->stream->getPlaybackRateParameters(playbackRate);
+ auto* const t = thread->asIAfPlaybackThread().get();
+ audio_utils::lock_guard lock(t->mutex());
+ status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
ALOGD_IF((status == NO_ERROR) &&
!isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
"%s: playbackRate inconsistent", __func__);
@@ -1862,16 +1959,16 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::Track::setPlaybackRateParameters(
+status_t Track::setPlaybackRateParameters(
const audio_playback_rate_t& playbackRate)
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
- Mutex::Autolock lock(t->mLock);
- status = t->mOutput->stream->setPlaybackRateParameters(playbackRate);
+ auto* const t = thread->asIAfPlaybackThread().get();
+ audio_utils::lock_guard lock(t->mutex());
+ status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
if (status == NO_ERROR) {
mPlaybackRateParameters = playbackRate;
}
@@ -1881,7 +1978,7 @@
}
//To be called with thread lock held
-bool AudioFlinger::PlaybackThread::Track::isResumePending() {
+bool Track::isResumePending() const {
if (mState == RESUMING) {
return true;
}
@@ -1895,7 +1992,7 @@
}
//To be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::resumeAck() {
+void Track::resumeAck() {
if (mState == RESUMING) {
mState = ACTIVE;
}
@@ -1909,7 +2006,7 @@
}
//To be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::updateTrackFrameInfo(
+void Track::updateTrackFrameInfo(
int64_t trackFramesReleased, int64_t sinkFramesWritten,
uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
// Make the kernel frametime available.
@@ -1989,14 +2086,14 @@
}
}
-bool AudioFlinger::PlaybackThread::Track::AudioVibrationController::setMute(bool muted) {
- sp<ThreadBase> thread = mTrack->mThread.promote();
+bool Track::AudioVibrationController::setMute(bool muted) {
+ const sp<IAfThreadBase> thread = mTrack->mThread.promote();
if (thread != 0) {
// Lock for updating mHapticPlaybackEnabled.
- Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ audio_utils::lock_guard _l(thread->mutex());
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
- && playbackThread->mHapticChannelCount > 0) {
+ && playbackThread->hapticChannelCount() > 0) {
ALOGD("%s, haptic playback was %s for track %d",
__func__, muted ? "muted" : "unmuted", mTrack->id());
mTrack->setHapticPlaybackEnabled(!muted);
@@ -2006,13 +2103,13 @@
return false;
}
-binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::mute(
+binder::Status Track::AudioVibrationController::mute(
/*out*/ bool *ret) {
*ret = setMute(true);
return binder::Status::ok();
}
-binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::unmute(
+binder::Status Track::AudioVibrationController::unmute(
/*out*/ bool *ret) {
*ret = setMute(false);
return binder::Status::ok();
@@ -2022,9 +2119,28 @@
#undef LOG_TAG
#define LOG_TAG "AF::OutputTrack"
-AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
- PlaybackThread *playbackThread,
- DuplicatingThread *sourceThread,
+/* static */
+sp<IAfOutputTrack> IAfOutputTrack::create(
+ IAfPlaybackThread* playbackThread,
+ IAfDuplicatingThread* sourceThread,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount,
+ const AttributionSourceState& attributionSource) {
+ return sp<OutputTrack>::make(
+ playbackThread,
+ sourceThread,
+ sampleRate,
+ format,
+ channelMask,
+ frameCount,
+ attributionSource);
+}
+
+OutputTrack::OutputTrack(
+ IAfPlaybackThread* playbackThread,
+ IAfDuplicatingThread* sourceThread,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@@ -2041,7 +2157,7 @@
if (mCblk != NULL) {
mOutBuffer.frameCount = 0;
- playbackThread->mTracks.add(this);
+ playbackThread->addOutputTrack_l(this);
ALOGV("%s(): mCblk %p, mBuffer %p, "
"frameCount %zu, mChannelMask 0x%08x",
__func__, mCblk, mBuffer,
@@ -2059,13 +2175,13 @@
}
}
-AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
+OutputTrack::~OutputTrack()
{
clearBufferQueue();
// superclass destructor will now delete the server proxy and shared memory both refer to
}
-status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
+status_t OutputTrack::start(AudioSystem::sync_event_t event,
audio_session_t triggerSession)
{
status_t status = Track::start(event, triggerSession);
@@ -2078,7 +2194,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::OutputTrack::stop()
+void OutputTrack::stop()
{
Track::stop();
clearBufferQueue();
@@ -2086,11 +2202,11 @@
mActive = false;
}
-ssize_t AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames)
+ssize_t OutputTrack::write(void* data, uint32_t frames)
{
if (!mActive && frames != 0) {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != nullptr && thread->standby()) {
+ const sp<IAfThreadBase> thread = mThread.promote();
+ if (thread != nullptr && thread->inStandby()) {
// preload one silent buffer to trigger mixer on start()
ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
status_t status = mClientProxy->obtainBuffer(&buf);
@@ -2108,7 +2224,7 @@
// If another OutputTrack has already started it can underrun but this is OK
// as only silence has been played so far and the retry count is very high on
// OutputTrack.
- auto pt = static_cast<PlaybackThread *>(thread.get());
+ auto* const pt = thread->asIAfPlaybackThread().get();
if (!pt->waitForHalStart()) {
ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
stop();
@@ -2197,8 +2313,8 @@
// If we could not write all frames, allocate a buffer and queue it for next time.
if (inBuffer.frameCount) {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0 && !thread->standby()) {
+ const sp<IAfThreadBase> thread = mThread.promote();
+ if (thread != nullptr && !thread->inStandby()) {
queueBuffer(inBuffer);
}
}
@@ -2212,7 +2328,7 @@
return frames - inBuffer.frameCount; // number of frames consumed.
}
-void AudioFlinger::PlaybackThread::OutputTrack::queueBuffer(Buffer& inBuffer) {
+void OutputTrack::queueBuffer(Buffer& inBuffer) {
if (mBufferQueue.size() < kMaxOverFlowBuffers) {
Buffer *pInBuffer = new Buffer;
@@ -2235,22 +2351,22 @@
}
}
-void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
{
- std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
+ audio_utils::lock_guard lock(trackMetadataMutex());
backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
}
-void AudioFlinger::PlaybackThread::OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
+void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
{
- std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
+ audio_utils::lock_guard lock(trackMetadataMutex());
mTrackMetadatas = metadatas;
}
// No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
setMetadataHasChanged();
}
-status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
+status_t OutputTrack::obtainBuffer(
AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
{
ClientProxy::Buffer buf;
@@ -2264,7 +2380,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
+void OutputTrack::clearBufferQueue()
{
size_t size = mBufferQueue.size();
@@ -2276,7 +2392,7 @@
mBufferQueue.clear();
}
-void AudioFlinger::PlaybackThread::OutputTrack::restartIfDisabled()
+void OutputTrack::restartIfDisabled()
{
int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
if (mActive && (flags & CBLK_DISABLED)) {
@@ -2288,7 +2404,38 @@
#undef LOG_TAG
#define LOG_TAG "AF::PatchTrack"
-AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThread,
+/* static */
+sp<IAfPatchTrack> IAfPatchTrack::create(
+ IAfPlaybackThread* playbackThread,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_channel_mask_t channelMask,
+ audio_format_t format,
+ size_t frameCount,
+ void* buffer,
+ size_t bufferSize,
+ audio_output_flags_t flags,
+ const Timeout& timeout,
+ size_t frameCountToBeReady /** Default behaviour is to start
+ * as soon as possible to have
+ * the lowest possible latency
+ * even if it might glitch. */)
+{
+ return sp<PatchTrack>::make(
+ playbackThread,
+ streamType,
+ sampleRate,
+ channelMask,
+ format,
+ frameCount,
+ buffer,
+ bufferSize,
+ flags,
+ timeout,
+ frameCountToBeReady);
+}
+
+PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
@@ -2307,7 +2454,7 @@
TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
: nullptr,
- *playbackThread, timeout)
+ playbackThread, timeout)
{
ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
__func__, mId, sampleRate,
@@ -2315,12 +2462,12 @@
(int)(mPeerTimeout.tv_nsec / 1000000));
}
-AudioFlinger::PlaybackThread::PatchTrack::~PatchTrack()
+PatchTrack::~PatchTrack()
{
ALOGV("%s(%d)", __func__, mId);
}
-size_t AudioFlinger::PlaybackThread::PatchTrack::framesReady() const
+size_t PatchTrack::framesReady() const
{
if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
return std::numeric_limits<size_t>::max();
@@ -2329,7 +2476,7 @@
}
}
-status_t AudioFlinger::PlaybackThread::PatchTrack::start(AudioSystem::sync_event_t event,
+status_t PatchTrack::start(AudioSystem::sync_event_t event,
audio_session_t triggerSession)
{
status_t status = Track::start(event, triggerSession);
@@ -2341,7 +2488,7 @@
}
// AudioBufferProvider interface
-status_t AudioFlinger::PlaybackThread::PatchTrack::getNextBuffer(
+status_t PatchTrack::getNextBuffer(
AudioBufferProvider::Buffer* buffer)
{
ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
@@ -2367,7 +2514,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
{
ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Proxy::Buffer buf;
@@ -2377,7 +2524,7 @@
TrackBase::releaseBuffer(buffer); // Note: this is the base class.
}
-status_t AudioFlinger::PlaybackThread::PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
+status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
const struct timespec *timeOut)
{
status_t status = NO_ERROR;
@@ -2394,7 +2541,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
+void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
{
mProxy->releaseBuffer(buffer);
restartIfDisabled();
@@ -2403,23 +2550,23 @@
// If not, prevent an underrun from occurring by moving the track into FS_FILLING;
// this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
// TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
- if (mFillingUpStatus == FS_ACTIVE
+ if (mFillingStatus == FS_ACTIVE
&& audio_is_linear_pcm(mFormat)
&& !isOffloadedOrDirect()) {
- if (sp<ThreadBase> thread = mThread.promote();
+ if (const sp<IAfThreadBase> thread = mThread.promote();
thread != 0) {
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
const size_t frameCount = playbackThread->frameCount() * sampleRate()
/ playbackThread->sampleRate();
if (framesReady() < frameCount) {
ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
- mFillingUpStatus = FS_FILLING;
+ mFillingStatus = FS_FILLING;
}
}
}
}
-void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
+void PatchTrack::restartIfDisabled()
{
if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
@@ -2435,55 +2582,83 @@
#undef LOG_TAG
#define LOG_TAG "AF::RecordHandle"
-AudioFlinger::RecordHandle::RecordHandle(
- const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
+class RecordHandle : public android::media::BnAudioRecord {
+public:
+ explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
+ ~RecordHandle() override;
+ binder::Status start(int /*AudioSystem::sync_event_t*/ event,
+ int /*audio_session_t*/ triggerSession) final;
+ binder::Status stop() final;
+ binder::Status getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
+ binder::Status setPreferredMicrophoneDirection(
+ int /*audio_microphone_direction_t*/ direction) final;
+ binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
+ binder::Status shareAudioHistory(
+ const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
+
+private:
+ const sp<IAfRecordTrack> mRecordTrack;
+
+ // for use from destructor
+ void stop_nonvirtual();
+};
+
+/* static */
+sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
+ const sp<IAfRecordTrack>& recordTrack) {
+ return sp<RecordHandle>::make(recordTrack);
+}
+
+RecordHandle::RecordHandle(
+ const sp<IAfRecordTrack>& recordTrack)
: BnAudioRecord(),
mRecordTrack(recordTrack)
{
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
-AudioFlinger::RecordHandle::~RecordHandle() {
+RecordHandle::~RecordHandle() {
stop_nonvirtual();
mRecordTrack->destroy();
}
-binder::Status AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
+binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
int /*audio_session_t*/ triggerSession) {
ALOGV("%s()", __func__);
return binderStatusFromStatusT(
mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
}
-binder::Status AudioFlinger::RecordHandle::stop() {
+binder::Status RecordHandle::stop() {
stop_nonvirtual();
return binder::Status::ok();
}
-void AudioFlinger::RecordHandle::stop_nonvirtual() {
+void RecordHandle::stop_nonvirtual() {
ALOGV("%s()", __func__);
mRecordTrack->stop();
}
-binder::Status AudioFlinger::RecordHandle::getActiveMicrophones(
+binder::Status RecordHandle::getActiveMicrophones(
std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
ALOGV("%s()", __func__);
return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
}
-binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneDirection(
+binder::Status RecordHandle::setPreferredMicrophoneDirection(
int /*audio_microphone_direction_t*/ direction) {
ALOGV("%s()", __func__);
return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
static_cast<audio_microphone_direction_t>(direction)));
}
-binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
+binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
ALOGV("%s()", __func__);
return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
}
-binder::Status AudioFlinger::RecordHandle::shareAudioHistory(
+binder::Status RecordHandle::shareAudioHistory(
const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
return binderStatusFromStatusT(
mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
@@ -2493,9 +2668,47 @@
#undef LOG_TAG
#define LOG_TAG "AF::RecordTrack"
+
+/* static */
+sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
+ const sp<Client>& client,
+ const audio_attributes_t& attr,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount,
+ void* buffer,
+ size_t bufferSize,
+ audio_session_t sessionId,
+ pid_t creatorPid,
+ const AttributionSourceState& attributionSource,
+ audio_input_flags_t flags,
+ track_type type,
+ audio_port_handle_t portId,
+ int32_t startFrames)
+{
+ return sp<RecordTrack>::make(
+ thread,
+ client,
+ attr,
+ sampleRate,
+ format,
+ channelMask,
+ frameCount,
+ buffer,
+ bufferSize,
+ sessionId,
+ creatorPid,
+ attributionSource,
+ flags,
+ type,
+ portId,
+ startFrames);
+}
+
// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
-AudioFlinger::RecordThread::RecordTrack::RecordTrack(
- RecordThread *thread,
+RecordTrack::RecordTrack(
+ IAfRecordThread* thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
@@ -2534,7 +2747,7 @@
if (!isDirect()) {
mRecordBufferConverter = new RecordBufferConverter(
- thread->mChannelMask, thread->mFormat, thread->mSampleRate,
+ thread->channelMask(), thread->format(), thread->sampleRate(),
channelMask, format, sampleRate);
// Check if the RecordBufferConverter construction was successful.
// If not, don't continue with construction.
@@ -2554,8 +2767,8 @@
mResamplerBufferProvider = new ResamplerBufferProvider(this);
if (flags & AUDIO_INPUT_FLAG_FAST) {
- ALOG_ASSERT(thread->mFastTrackAvail);
- thread->mFastTrackAvail = false;
+ ALOG_ASSERT(thread->fastTrackAvailable());
+ thread->setFastTrackAvailable(false);
} else {
// TODO: only Normal Record has timestamps (Fast Record does not).
mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
@@ -2570,14 +2783,14 @@
mTrackMetrics.logConstructor(creatorPid, uid(), id());
}
-AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
+RecordTrack::~RecordTrack()
{
ALOGV("%s()", __func__);
delete mRecordBufferConverter;
delete mResamplerBufferProvider;
}
-status_t AudioFlinger::RecordThread::RecordTrack::initCheck() const
+status_t RecordTrack::initCheck() const
{
status_t status = TrackBase::initCheck();
if (status == NO_ERROR && mServerProxy == 0) {
@@ -2587,7 +2800,7 @@
}
// AudioBufferProvider interface
-status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
{
ServerProxy::Buffer buf;
buf.mFrameCount = buffer->frameCount;
@@ -2601,12 +2814,12 @@
return status;
}
-status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
+status_t RecordTrack::start(AudioSystem::sync_event_t event,
audio_session_t triggerSession)
{
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = thread->asIAfRecordThread().get();
return recordThread->start(this, event, triggerSession);
} else {
ALOGW("%s track %d: thread was destroyed", __func__, portId());
@@ -2614,27 +2827,27 @@
}
}
-void AudioFlinger::RecordThread::RecordTrack::stop()
+void RecordTrack::stop()
{
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = thread->asIAfRecordThread().get();
if (recordThread->stop(this) && isExternalTrack()) {
AudioSystem::stopInput(mPortId);
}
}
}
-void AudioFlinger::RecordThread::RecordTrack::destroy()
+void RecordTrack::destroy()
{
- // see comments at AudioFlinger::PlaybackThread::Track::destroy()
+ // see comments at Track::destroy()
sp<RecordTrack> keep(this);
{
track_state priorState = mState;
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- RecordThread *recordThread = (RecordThread *) thread.get();
+ audio_utils::lock_guard _l(thread->mutex());
+ auto* const recordThread = thread->asIAfRecordThread().get();
priorState = mState;
if (!mSharedAudioPackageName.empty()) {
recordThread->resetAudioHistory_l();
@@ -2665,7 +2878,7 @@
}
}
-void AudioFlinger::RecordThread::RecordTrack::invalidate()
+void RecordTrack::invalidate()
{
TrackBase::invalidate();
// FIXME should use proxy, and needs work
@@ -2677,7 +2890,7 @@
}
-void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
+void RecordTrack::appendDumpHeader(String8& result) const
{
result.appendFormat("Active Id Client Session Port Id S Flags "
" Format Chn mask SRate Source "
@@ -2685,7 +2898,7 @@
isServerLatencySupported() ? " Latency" : "");
}
-void AudioFlinger::RecordThread::RecordTrack::appendDump(String8& result, bool active)
+void RecordTrack::appendDump(String8& result, bool active) const
{
result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
"%08X %08X %6u %6X "
@@ -2724,26 +2937,26 @@
}
// This is invoked by SyncEvent callback.
-void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(
+void RecordTrack::handleSyncStartEvent(
const sp<audioflinger::SyncEvent>& event)
{
size_t framesToDrop = 0;
- sp<ThreadBase> threadBase = mThread.promote();
+ const sp<IAfThreadBase> threadBase = mThread.promote();
if (threadBase != 0) {
// TODO: use actual buffer filling status instead of 2 buffers when info is available
// from audio HAL
- framesToDrop = threadBase->mFrameCount * 2;
+ framesToDrop = threadBase->frameCount() * 2;
}
mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
}
-void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent()
+void RecordTrack::clearSyncStartEvent()
{
mSynchronizedRecordState.clear();
}
-void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo(
+void RecordTrack::updateTrackFrameInfo(
int64_t trackFramesReleased, int64_t sourceFramesRead,
uint32_t halSampleRate, const ExtendedTimestamp ×tamp)
{
@@ -2783,40 +2996,40 @@
mServerLatencyMs.store(latencyMs);
}
-status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones)
+status_t RecordTrack::getActiveMicrophones(
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
{
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = thread->asIAfRecordThread().get();
return recordThread->getActiveMicrophones(activeMicrophones);
} else {
return BAD_VALUE;
}
}
-status_t AudioFlinger::RecordThread::RecordTrack::setPreferredMicrophoneDirection(
+status_t RecordTrack::setPreferredMicrophoneDirection(
audio_microphone_direction_t direction) {
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = thread->asIAfRecordThread().get();
return recordThread->setPreferredMicrophoneDirection(direction);
} else {
return BAD_VALUE;
}
}
-status_t AudioFlinger::RecordThread::RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
- sp<ThreadBase> thread = mThread.promote();
+status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = thread->asIAfRecordThread().get();
return recordThread->setPreferredMicrophoneFieldDimension(zoom);
} else {
return BAD_VALUE;
}
}
-status_t AudioFlinger::RecordThread::RecordTrack::shareAudioHistory(
+status_t RecordTrack::shareAudioHistory(
const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
@@ -2833,9 +3046,9 @@
return PERMISSION_DENIED;
}
- sp<ThreadBase> thread = mThread.promote();
+ const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = thread->asIAfRecordThread().get();
status_t status = recordThread->shareAudioHistory(
sharedAudioPackageName, mSessionId, sharedAudioStartMs);
if (status == NO_ERROR) {
@@ -2847,7 +3060,7 @@
}
}
-void AudioFlinger::RecordThread::RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
{
// Do not forward PatchRecord metadata with unspecified audio source
@@ -2871,7 +3084,33 @@
#undef LOG_TAG
#define LOG_TAG "AF::PatchRecord"
-AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,
+/* static */
+sp<IAfPatchRecord> IAfPatchRecord::create(
+ IAfRecordThread* recordThread,
+ uint32_t sampleRate,
+ audio_channel_mask_t channelMask,
+ audio_format_t format,
+ size_t frameCount,
+ void *buffer,
+ size_t bufferSize,
+ audio_input_flags_t flags,
+ const Timeout& timeout,
+ audio_source_t source)
+{
+ return sp<PatchRecord>::make(
+ recordThread,
+ sampleRate,
+ channelMask,
+ format,
+ frameCount,
+ buffer,
+ bufferSize,
+ flags,
+ timeout,
+ source);
+}
+
+PatchRecord::PatchRecord(IAfRecordThread* recordThread,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
audio_format_t format,
@@ -2888,7 +3127,7 @@
audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
: nullptr,
- *recordThread, timeout)
+ recordThread, timeout)
{
ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
__func__, mId, sampleRate,
@@ -2896,7 +3135,7 @@
(int)(mPeerTimeout.tv_nsec / 1000000));
}
-AudioFlinger::RecordThread::PatchRecord::~PatchRecord()
+PatchRecord::~PatchRecord()
{
ALOGV("%s(%d)", __func__, mId);
}
@@ -2920,7 +3159,7 @@
}
// static
-size_t AudioFlinger::RecordThread::PatchRecord::writeFrames(
+size_t PatchRecord::writeFrames(
AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
{
size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
@@ -2935,7 +3174,7 @@
}
// AudioBufferProvider interface
-status_t AudioFlinger::RecordThread::PatchRecord::getNextBuffer(
+status_t PatchRecord::getNextBuffer(
AudioBufferProvider::Buffer* buffer)
{
ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
@@ -2957,7 +3196,7 @@
return status;
}
-void AudioFlinger::RecordThread::PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
{
ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Proxy::Buffer buf;
@@ -2967,13 +3206,13 @@
TrackBase::releaseBuffer(buffer);
}
-status_t AudioFlinger::RecordThread::PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
+status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
const struct timespec *timeOut)
{
return mProxy->obtainBuffer(buffer, timeOut);
}
-void AudioFlinger::RecordThread::PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
{
mProxy->releaseBuffer(buffer);
}
@@ -2988,8 +3227,28 @@
return {ptr, free};
}
-AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord(
- RecordThread *recordThread,
+/* static */
+sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
+ IAfRecordThread* recordThread,
+ uint32_t sampleRate,
+ audio_channel_mask_t channelMask,
+ audio_format_t format,
+ size_t frameCount,
+ audio_input_flags_t flags,
+ audio_source_t source)
+{
+ return sp<PassthruPatchRecord>::make(
+ recordThread,
+ sampleRate,
+ channelMask,
+ format,
+ frameCount,
+ flags,
+ source);
+}
+
+PassthruPatchRecord::PassthruPatchRecord(
+ IAfRecordThread* recordThread,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
audio_format_t format,
@@ -3005,18 +3264,18 @@
memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
}
-sp<StreamInHalInterface> AudioFlinger::RecordThread::PassthruPatchRecord::obtainStream(
- sp<ThreadBase>* thread)
+sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
+ sp<IAfThreadBase>* thread)
{
*thread = mThread.promote();
if (!*thread) return nullptr;
- RecordThread *recordThread = static_cast<RecordThread*>((*thread).get());
- Mutex::Autolock _l(recordThread->mLock);
- return recordThread->mInput ? recordThread->mInput->stream : nullptr;
+ auto* const recordThread = (*thread)->asIAfRecordThread().get();
+ audio_utils::lock_guard _l(recordThread->mutex());
+ return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
}
// PatchProxyBufferProvider methods are called on DirectOutputThread
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::obtainBuffer(
+status_t PassthruPatchRecord::obtainBuffer(
Proxy::Buffer* buffer, const struct timespec* timeOut)
{
if (mUnconsumedFrames) {
@@ -3034,7 +3293,7 @@
const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
buffer->mFrameCount = 0;
buffer->mRaw = nullptr;
- sp<ThreadBase> thread;
+ sp<IAfThreadBase> thread;
sp<StreamInHalInterface> stream = obtainStream(&thread);
if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
@@ -3048,7 +3307,7 @@
}
{
- std::lock_guard<std::mutex> lock(mReadLock);
+ audio_utils::lock_guard lock(readMutex());
mReadBytes += bytesRead;
mReadError = NO_ERROR;
}
@@ -3075,14 +3334,14 @@
stream_error:
stream->standby();
{
- std::lock_guard<std::mutex> lock(mReadLock);
+ audio_utils::lock_guard lock(readMutex());
mReadError = result;
}
mReadCV.notify_one();
return result;
}
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
{
if (buffer->mFrameCount <= mUnconsumedFrames) {
mUnconsumedFrames -= buffer->mFrameCount;
@@ -3099,12 +3358,12 @@
// and 'releaseBuffer' are stubbed out and ignore their input.
// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
// until we copy it.
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::read(
+status_t PassthruPatchRecord::read(
void* buffer, size_t bytes, size_t* read)
{
bytes = std::min(bytes, mFrameCount * mFrameSize);
{
- std::unique_lock<std::mutex> lock(mReadLock);
+ audio_utils::unique_lock lock(readMutex());
mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
if (mReadError != NO_ERROR) {
mLastReadFrames = 0;
@@ -3118,15 +3377,15 @@
return 0;
}
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::getCapturePosition(
+status_t PassthruPatchRecord::getCapturePosition(
int64_t* frames, int64_t* time)
{
- sp<ThreadBase> thread;
+ sp<IAfThreadBase> thread;
sp<StreamInHalInterface> stream = obtainStream(&thread);
return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
}
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::standby()
+status_t PassthruPatchRecord::standby()
{
// RecordThread issues 'standby' command in two major cases:
// 1. Error on read--this case is handled in 'obtainBuffer'.
@@ -3138,7 +3397,7 @@
}
// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::getNextBuffer(
+status_t PassthruPatchRecord::getNextBuffer(
AudioBufferProvider::Buffer* buffer)
{
buffer->frameCount = mLastReadFrames;
@@ -3146,7 +3405,7 @@
return NO_ERROR;
}
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(
+void PassthruPatchRecord::releaseBuffer(
AudioBufferProvider::Buffer* buffer)
{
buffer->frameCount = 0;
@@ -3157,7 +3416,32 @@
#undef LOG_TAG
#define LOG_TAG "AF::MmapTrack"
-AudioFlinger::MmapThread::MmapTrack::MmapTrack(ThreadBase *thread,
+/* static */
+sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
+ const audio_attributes_t& attr,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_session_t sessionId,
+ bool isOut,
+ const android::content::AttributionSourceState& attributionSource,
+ pid_t creatorPid,
+ audio_port_handle_t portId)
+{
+ return sp<MmapTrack>::make(
+ thread,
+ attr,
+ sampleRate,
+ format,
+ channelMask,
+ sessionId,
+ isOut,
+ attributionSource,
+ creatorPid,
+ portId);
+}
+
+MmapTrack::MmapTrack(IAfThreadBase* thread,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
@@ -3183,27 +3467,27 @@
mTrackMetrics.logConstructor(creatorPid, uid(), id());
}
-AudioFlinger::MmapThread::MmapTrack::~MmapTrack()
+MmapTrack::~MmapTrack()
{
}
-status_t AudioFlinger::MmapThread::MmapTrack::initCheck() const
+status_t MmapTrack::initCheck() const
{
return NO_ERROR;
}
-status_t AudioFlinger::MmapThread::MmapTrack::start(AudioSystem::sync_event_t event __unused,
+status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
audio_session_t triggerSession __unused)
{
return NO_ERROR;
}
-void AudioFlinger::MmapThread::MmapTrack::stop()
+void MmapTrack::stop()
{
}
// AudioBufferProvider interface
-status_t AudioFlinger::MmapThread::MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
{
buffer->frameCount = 0;
buffer->raw = nullptr;
@@ -3211,21 +3495,20 @@
}
// ExtendedAudioBufferProvider interface
-size_t AudioFlinger::MmapThread::MmapTrack::framesReady() const {
+size_t MmapTrack::framesReady() const {
return 0;
}
-int64_t AudioFlinger::MmapThread::MmapTrack::framesReleased() const
+int64_t MmapTrack::framesReleased() const
{
return 0;
}
-void AudioFlinger::MmapThread::MmapTrack::onTimestamp(const ExtendedTimestamp ×tamp __unused)
+void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
{
}
-void AudioFlinger::MmapThread::MmapTrack::processMuteEvent_l(const sp<
- IAudioManager>& audioManager, mute_state_t muteState)
+void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
{
if (mMuteState == muteState) {
// mute state did not change, do nothing
@@ -3256,13 +3539,13 @@
}
}
-void AudioFlinger::MmapThread::MmapTrack::appendDumpHeader(String8& result)
+void MmapTrack::appendDumpHeader(String8& result) const
{
result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
isOut() ? "Usg CT": "Source");
}
-void AudioFlinger::MmapThread::MmapTrack::appendDump(String8& result, bool active __unused)
+void MmapTrack::appendDump(String8& result, bool active __unused) const
{
result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
mPid,
diff --git a/services/audioflinger/afutils/Android.bp b/services/audioflinger/afutils/Android.bp
index 1580b8f..5e29ce9 100644
--- a/services/audioflinger/afutils/Android.bp
+++ b/services/audioflinger/afutils/Android.bp
@@ -39,18 +39,24 @@
"AudioWatchdog.cpp",
"BufLog.cpp",
"NBAIO_Tee.cpp",
+ "Permission.cpp",
"PropertyUtils.cpp",
"TypedLogger.cpp",
+ "Vibrator.cpp",
],
shared_libs: [
+ "framework-permission-aidl-cpp",
+ "libaudioclient_aidl_conversion",
"libaudioutils",
"libbase",
+ "libbinder",
"libcutils", // property_get_int32
"liblog",
"libnbaio",
"libnblog",
"libutils",
+ "libvibrator",
],
static_libs: [
diff --git a/services/audioflinger/afutils/DumpTryLock.h b/services/audioflinger/afutils/DumpTryLock.h
new file mode 100644
index 0000000..e4ad112
--- /dev/null
+++ b/services/audioflinger/afutils/DumpTryLock.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <audio_utils/mutex.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+
+namespace android::afutils {
+
+inline bool dumpTryLock(Mutex& mutex)
+{
+ static constexpr int kDumpLockTimeoutNs = 1'000'000'000;
+ const status_t err = mutex.timedLock(kDumpLockTimeoutNs);
+ return err == NO_ERROR;
+}
+
+// Note: the std::timed_mutex try_lock_for and try_lock_until methods are inefficient.
+// It is better to use std::mutex and call this method.
+//
+inline bool dumpTryLock(audio_utils::mutex& mutex) TRY_ACQUIRE(true, mutex)
+{
+ static constexpr int64_t kDumpLockTimeoutNs = 1'000'000'000;
+
+ const int64_t timeoutNs = kDumpLockTimeoutNs + systemTime(SYSTEM_TIME_REALTIME);
+ const struct timespec ts = {
+ .tv_sec = static_cast<time_t>(timeoutNs / 1000000000),
+ .tv_nsec = static_cast<long>(timeoutNs % 1000000000),
+ };
+ return pthread_mutex_timedlock(mutex.native_handle(), &ts) == 0;
+}
+
+} // android::afutils
diff --git a/services/audioflinger/afutils/Permission.cpp b/services/audioflinger/afutils/Permission.cpp
new file mode 100644
index 0000000..35448e3
--- /dev/null
+++ b/services/audioflinger/afutils/Permission.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Permission"
+//#define LOG_NDEBUG 0
+
+#include "Permission.h"
+
+#include <binder/PermissionController.h>
+#include <media/AidlConversionCppNdk.h>
+#include <utils/Log.h>
+
+namespace android::afutils {
+
+// TODO b/182392769: use attribution source util
+content::AttributionSourceState checkAttributionSourcePackage(
+ const content::AttributionSourceState& attributionSource) {
+ Vector<String16> packages;
+ PermissionController{}.getPackagesForUid(attributionSource.uid, packages);
+
+ content::AttributionSourceState checkedAttributionSource = attributionSource;
+ if (!attributionSource.packageName.has_value()
+ || attributionSource.packageName.value().size() == 0) {
+ if (!packages.isEmpty()) {
+ checkedAttributionSource.packageName =
+ std::move(legacy2aidl_String16_string(packages[0]).value());
+ }
+ } else {
+ const String16 opPackageLegacy = VALUE_OR_FATAL(
+ aidl2legacy_string_view_String16(attributionSource.packageName.value_or("")));
+ if (std::find_if(packages.begin(), packages.end(),
+ [&opPackageLegacy](const auto& package) {
+ return opPackageLegacy == package; }) == packages.end()) {
+ ALOGW("The package name(%s) provided does not correspond to the uid %d",
+ attributionSource.packageName.value_or("").c_str(), attributionSource.uid);
+ }
+ }
+ return checkedAttributionSource;
+}
+
+} // namespace android::afutils
diff --git a/services/audioflinger/afutils/Permission.h b/services/audioflinger/afutils/Permission.h
new file mode 100644
index 0000000..97c7ff9
--- /dev/null
+++ b/services/audioflinger/afutils/Permission.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/content/AttributionSourceState.h>
+
+namespace android::afutils {
+
+content::AttributionSourceState checkAttributionSourcePackage(
+ const content::AttributionSourceState& attributionSource);
+
+} // namespace android::afutils
diff --git a/services/audioflinger/afutils/Vibrator.cpp b/services/audioflinger/afutils/Vibrator.cpp
new file mode 100644
index 0000000..25fcc6a
--- /dev/null
+++ b/services/audioflinger/afutils/Vibrator.cpp
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioFlinger::Vibrator"
+//#define LOG_NDEBUG 0
+
+#include "Vibrator.h"
+
+#include <android/os/IExternalVibratorService.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <mutex>
+
+namespace android::afutils {
+
+static sp<os::IExternalVibratorService> getExternalVibratorService() {
+ static std::mutex m;
+ static sp<os::IExternalVibratorService> sExternalVibratorService;
+
+ std::lock_guard l(m);
+ if (sExternalVibratorService == nullptr) {
+ const sp<IBinder> binder = defaultServiceManager()->getService(
+ String16("external_vibrator_service"));
+ if (binder != nullptr) {
+ sExternalVibratorService = interface_cast<os::IExternalVibratorService>(binder);
+ }
+ }
+ return sExternalVibratorService;
+}
+
+os::HapticScale onExternalVibrationStart(const sp<os::ExternalVibration>& externalVibration) {
+ const sp<os::IExternalVibratorService> evs = getExternalVibratorService();
+ if (evs != nullptr) {
+ int32_t ret;
+ binder::Status status = evs->onExternalVibrationStart(*externalVibration, &ret);
+ if (status.isOk()) {
+ ALOGD("%s, start external vibration with intensity as %d", __func__, ret);
+ return os::ExternalVibration::externalVibrationScaleToHapticScale(ret);
+ }
+ }
+ ALOGD("%s, start external vibration with intensity as MUTE due to %s",
+ __func__,
+ evs == nullptr ? "external vibration service not found"
+ : "error when querying intensity");
+ return os::HapticScale::MUTE;
+}
+
+void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration) {
+ const sp<os::IExternalVibratorService> evs = getExternalVibratorService();
+ if (evs != nullptr) {
+ ALOGD("%s, stop external vibration", __func__);
+ evs->onExternalVibrationStop(*externalVibration);
+ }
+}
+
+} // namespace android::afutils
diff --git a/services/audioflinger/afutils/Vibrator.h b/services/audioflinger/afutils/Vibrator.h
new file mode 100644
index 0000000..4354872
--- /dev/null
+++ b/services/audioflinger/afutils/Vibrator.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vibrator/ExternalVibration.h>
+#include <vibrator/ExternalVibrationUtils.h>
+
+namespace android::afutils {
+
+os::HapticScale onExternalVibrationStart(const sp<os::ExternalVibration>& externalVibration);
+
+void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
+
+} // namespace android::afutils
diff --git a/services/audioflinger/datapath/AudioStreamIn.h b/services/audioflinger/datapath/AudioStreamIn.h
new file mode 100644
index 0000000..604a4e4
--- /dev/null
+++ b/services/audioflinger/datapath/AudioStreamIn.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "AudioHwDevice.h"
+#include <media/audiohal/DeviceHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+
+namespace android {
+
+// Abstraction for the Audio Source for the RecordThread (HAL or PassthruPatchRecord).
+struct Source {
+ virtual ~Source() = default;
+ // The following methods have the same signatures as in StreamHalInterface.
+ virtual status_t read(void* buffer, size_t bytes, size_t* read) = 0;
+ virtual status_t getCapturePosition(int64_t* frames, int64_t* time) = 0;
+ virtual status_t standby() = 0;
+};
+
+// AudioStreamIn is immutable, so its fields are const.
+// The methods must not be const to match StreamHalInterface signature.
+
+struct AudioStreamIn : public Source {
+ const AudioHwDevice* const audioHwDev;
+ const sp<StreamInHalInterface> stream;
+ const audio_input_flags_t flags;
+
+ AudioStreamIn(
+ const AudioHwDevice* dev, const sp<StreamInHalInterface>& in,
+ audio_input_flags_t flags)
+ : audioHwDev(dev), stream(in), flags(flags) {}
+
+ status_t read(void* buffer, size_t bytes, size_t* read) final {
+ return stream->read(buffer, bytes, read);
+ }
+
+ status_t getCapturePosition(int64_t* frames, int64_t* time) final {
+ return stream->getCapturePosition(frames, time);
+ }
+
+ status_t standby() final { return stream->standby(); }
+
+ sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
+};
+
+} // namespace android
diff --git a/services/audioflinger/datapath/ThreadMetrics.h b/services/audioflinger/datapath/ThreadMetrics.h
index 5493b3c..c643a57 100644
--- a/services/audioflinger/datapath/ThreadMetrics.h
+++ b/services/audioflinger/datapath/ThreadMetrics.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_AUDIO_THREADMETRICS_H
#define ANDROID_AUDIO_THREADMETRICS_H
+#include <media/MediaMetricsItem.h>
+
#include <mutex>
namespace android {
diff --git a/services/audioflinger/datapath/TrackMetrics.h b/services/audioflinger/datapath/TrackMetrics.h
index f3425df..2b44acb 100644
--- a/services/audioflinger/datapath/TrackMetrics.h
+++ b/services/audioflinger/datapath/TrackMetrics.h
@@ -20,6 +20,8 @@
#include <binder/IActivityManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <media/MediaMetricsItem.h>
+
#include <mutex>
namespace android {
diff --git a/services/audioflinger/datapath/VolumeInterface.h b/services/audioflinger/datapath/VolumeInterface.h
new file mode 100644
index 0000000..1564fe1
--- /dev/null
+++ b/services/audioflinger/datapath/VolumeInterface.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <system/audio.h>
+
+namespace android {
+
+class VolumeInterface : public virtual RefBase {
+public:
+ virtual void setMasterVolume(float value) = 0;
+ virtual void setMasterBalance(float balance) = 0;
+ virtual void setMasterMute(bool muted) = 0;
+ virtual void setStreamVolume(audio_stream_type_t stream, float value) = 0;
+ virtual void setStreamMute(audio_stream_type_t stream, bool muted) = 0;
+ // TODO(b/290699744) add "get" prefix for getter below.
+ virtual float streamVolume(audio_stream_type_t stream) const = 0;
+};
+
+} // namespace android
diff --git a/services/audioflinger/fastpath/FastMixerState.h b/services/audioflinger/fastpath/FastMixerState.h
index c70e42a..8ab6d25 100644
--- a/services/audioflinger/fastpath/FastMixerState.h
+++ b/services/audioflinger/fastpath/FastMixerState.h
@@ -35,7 +35,7 @@
class VolumeProvider {
public:
// The provider implementation is responsible for validating that the return value is in range.
- virtual gain_minifloat_packed_t getVolumeLR() = 0;
+ virtual gain_minifloat_packed_t getVolumeLR() const = 0;
protected:
VolumeProvider() = default;
virtual ~VolumeProvider() = default;
diff --git a/services/audioflinger/timing/SyncEvent.h b/services/audioflinger/timing/SyncEvent.h
index b5a3b40..ededb26 100644
--- a/services/audioflinger/timing/SyncEvent.h
+++ b/services/audioflinger/timing/SyncEvent.h
@@ -16,6 +16,7 @@
#pragma once
+#include <any>
#include <functional>
#include <mutex>
@@ -33,7 +34,7 @@
audio_session_t triggerSession,
audio_session_t listenerSession,
const SyncEventCallback& callBack,
- const wp<RefBase>& cookie)
+ const std::any& cookie)
: mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
mCookie(cookie), mCallback(callBack)
{}
@@ -56,13 +57,13 @@
AudioSystem::sync_event_t type() const { return mType; }
audio_session_t triggerSession() const { return mTriggerSession; }
audio_session_t listenerSession() const { return mListenerSession; }
- const wp<RefBase>& cookie() const { return mCookie; }
+ const std::any& cookie() const { return mCookie; }
private:
const AudioSystem::sync_event_t mType;
const audio_session_t mTriggerSession;
const audio_session_t mListenerSession;
- const wp<RefBase> mCookie;
+ const std::any mCookie;
mutable std::mutex mLock;
SyncEventCallback mCallback GUARDED_BY(mLock);
};
diff --git a/services/audioflinger/timing/tests/mediasyncevent_tests.cpp b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
index 8a6cf68..ab2d88f 100644
--- a/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
+++ b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
@@ -56,7 +56,7 @@
ASSERT_EQ(type, syncEvent->type());
ASSERT_EQ(triggerSession, syncEvent->triggerSession());
ASSERT_EQ(listenerSession, syncEvent->listenerSession());
- ASSERT_EQ(cookie, syncEvent->cookie());
+ ASSERT_EQ(cookie, std::any_cast<decltype(cookie)>(syncEvent->cookie()));
ASSERT_FALSE(triggered);
syncEvent->trigger();
diff --git a/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
index e9e1edf..82df059 100644
--- a/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
+++ b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
@@ -59,6 +59,7 @@
ASSERT_EQ(0, recordState.updateRecordFrames(1'000'000'000));
ASSERT_FALSE(triggered);
ASSERT_TRUE(syncEvent->isCancelled());
+ ASSERT_EQ(cookie, std::any_cast<decltype(cookie)>(syncEvent->cookie()));
// Check count down after track is complete.
syncEvent = sp<SyncEvent>::make(