[automerger skipped] Merge changes from topic "am-92def43caac0462a8e67863e0310a4b5" into android13-tests-dev am: 5355dd1224 -s ours am: 1c5a228a84 -s ours am: eed57e550b -s ours am: 14a7e548bd -s ours am: 9ad1829b6e -s ours am: c640910e7f -s ours am: 4cabb5a4af -s ours
am skip reason: Merged-In I3707d883d0daa4ffd2baa9bd69aebf4bf9ddef4e with SHA-1 5c6daae040 is already in history
Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/2066387
Change-Id: I1fe55c4fc15fe1d9328c70a04082476317d52e9b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/camera/Android.bp b/camera/Android.bp
index b3f70f4..a3fd7f9 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -144,6 +144,7 @@
srcs: [
"aidl/android/hardware/CameraExtensionSessionStats.aidl",
"aidl/android/hardware/ICameraService.aidl",
+ "aidl/android/hardware/CameraIdRemapping.aidl",
"aidl/android/hardware/ICameraServiceListener.aidl",
"aidl/android/hardware/ICameraServiceProxy.aidl",
"aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl",
diff --git a/camera/aidl/android/hardware/CameraIdRemapping.aidl b/camera/aidl/android/hardware/CameraIdRemapping.aidl
new file mode 100644
index 0000000..e875c53
--- /dev/null
+++ b/camera/aidl/android/hardware/CameraIdRemapping.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package android.hardware;
+
+/**
+ * Specifies a remapping of Camera Ids.
+ *
+ * Example: For a given package, a remapping of camera id0 to id1 specifies
+ * that any operation to perform on id0 should instead be performed on id1.
+ *
+ * @hide
+ */
+parcelable CameraIdRemapping {
+ /**
+ * Specifies remapping of Camera Ids per package.
+ */
+ parcelable PackageIdRemapping {
+ /** Package Name (e.g. com.android.xyz). */
+ String packageName;
+ /**
+ * Ordered list of Camera Ids to replace. Only Camera Ids present in this list will be
+ * affected.
+ */
+ List<String> cameraIdsToReplace;
+ /**
+ * Ordered list of updated Camera Ids, where updatedCameraIds[i] corresponds to
+ * the updated camera id for cameraIdsToReplace[i].
+ */
+ List<String> updatedCameraIds;
+ }
+
+ /**
+ * List of Camera Id remappings to perform.
+ */
+ List<PackageIdRemapping> packageIdRemappings;
+}
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index f8e1631..01b8ff8 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -29,6 +29,7 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.ICameraServiceListener;
import android.hardware.CameraInfo;
+import android.hardware.CameraIdRemapping;
import android.hardware.CameraStatus;
import android.hardware.CameraExtensionSessionStats;
@@ -131,6 +132,22 @@
int targetSdkVersion);
/**
+ * Remap Camera Ids in the CameraService.
+ *
+ * Once this is in effect, all binder calls in the ICameraService that
+ * use logicalCameraId should consult remapping state to arrive at the
+ * correct cameraId to perform the operation on.
+ *
+ * Note: Before the new cameraIdRemapping state is applied, the previous
+ * state is cleared.
+ *
+ * @param cameraIdRemapping the camera ids to remap. Sending an unpopulated
+ * cameraIdRemapping object will result in clearing of any previous
+ * cameraIdRemapping state in the camera service.
+ */
+ void remapCameraIds(in CameraIdRemapping cameraIdRemapping);
+
+ /**
* Remove listener for changes to camera device and flashlight state.
*/
void removeListener(ICameraServiceListener listener);
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/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 86fd8ab..a75ce70 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -46,6 +46,7 @@
#include <media/stagefright/BufferProducerWrapper.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/PersistentSurface.h>
+#include <media/stagefright/RenderedFrameInfo.h>
#include <utils/NativeHandle.h>
#include "C2OMXNode.h"
@@ -672,8 +673,7 @@
}
void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) override {
- mCodec->mCallback->onOutputFramesRendered(
- {RenderedFrameInfo(mediaTimeUs, renderTimeNs)});
+ mCodec->mCallback->onOutputFramesRendered({RenderedFrameInfo(mediaTimeUs, renderTimeNs)});
}
void onOutputBuffersChanged() override {
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/aidl/android/media/ISoundDose.aidl b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
index 6cb22ef..d80b6bf 100644
--- a/media/libaudioclient/aidl/android/media/ISoundDose.aidl
+++ b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
@@ -55,6 +55,30 @@
*/
oneway void setCsdEnabled(boolean enabled);
+ /**
+ * Structure containing a device identifier by address and type together with
+ * the categorization whether it is a headphone or not.
+ */
+ @JavaDerive(toString = true)
+ parcelable AudioDeviceCategory {
+ @utf8InCpp String address;
+ int internalAudioType;
+ boolean csdCompatible;
+ }
+
+ /**
+ * Resets the list of stored device categories for the native layer. Should
+ * only be called once at boot time after parsing the existing AudioDeviceCategories.
+ */
+ oneway void initCachedAudioDeviceCategories(in AudioDeviceCategory[] audioDevices);
+
+ /**
+ * Sets whether a device for a given address and type is a headphone or not.
+ * This is used to determine whether we compute the CSD on the given device
+ * since we can not rely completely on the device annotations.
+ */
+ oneway void setAudioDeviceCategory(in AudioDeviceCategory audioDevice);
+
/* -------------------------- Test API methods --------------------------
/** Get the currently used RS2 upper bound. */
float getOutputRs2UpperBound();
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/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
index 5d0d08d..a1726ad 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.cpp
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -223,8 +223,7 @@
deltaSamples = kMaxCaptureBufSize;
}
- int32_t capturePoint;
- //capturePoint = (int32_t)mCaptureIdx - deltaSamples;
+ int32_t capturePoint, captureSamples = mCaptureSamples;
__builtin_sub_overflow((int32_t) mCaptureIdx, deltaSamples, &capturePoint);
// a negative capturePoint means we wrap the buffer.
if (capturePoint < 0) {
@@ -232,13 +231,14 @@
if (size > mCaptureSamples) {
size = mCaptureSamples;
}
+ // first part of two stages copy, capture to the end of buffer and reset the size/point
result.insert(result.end(), &mCaptureBuf[kMaxCaptureBufSize + capturePoint],
&mCaptureBuf[kMaxCaptureBufSize + capturePoint + size]);
- mCaptureSamples -= size;
+ captureSamples -= size;
capturePoint = 0;
}
result.insert(result.end(), &mCaptureBuf[capturePoint],
- &mCaptureBuf[capturePoint + mCaptureSamples]);
+ &mCaptureBuf[capturePoint + captureSamples]);
mLastCaptureIdx = mCaptureIdx;
return result;
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index a91b24a..2223f24 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -43,6 +43,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/PersistentSurface.h>
+#include <media/stagefright/RenderedFrameInfo.h>
#include <media/stagefright/SurfaceUtils.h>
#include <media/hardware/HardwareAPI.h>
#include <media/MediaBufferHolder.h>
@@ -64,11 +65,14 @@
#include "include/SharedMemoryBuffer.h"
#include <media/stagefright/omx/OMXUtils.h>
+#include <server_configurable_flags/get_flags.h>
+
namespace android {
typedef hardware::media::omx::V1_0::IGraphicBufferSource HGraphicBufferSource;
using hardware::media::omx::V1_0::Status;
+using server_configurable_flags::GetServerConfigurableFlag;
enum {
kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles
@@ -81,6 +85,11 @@
}
+static bool areRenderMetricsEnabled() {
+ std::string v = GetServerConfigurableFlag("media_native", "render_metrics_enabled", "false");
+ return v == "true";
+}
+
// OMX errors are directly mapped into status_t range if
// there is no corresponding MediaError status code.
// Use the statusFromOMXError(int32_t omxError) function.
@@ -563,6 +572,9 @@
ACodec::ACodec()
: mSampleRate(0),
mNodeGeneration(0),
+ mAreRenderMetricsEnabled(areRenderMetricsEnabled()),
+ mIsWindowToDisplay(false),
+ mHasPresentFenceTimes(false),
mUsingNativeWindow(false),
mNativeWindowUsageBits(0),
mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN),
@@ -634,7 +646,8 @@
if (!mBufferChannel) {
mBufferChannel = std::make_shared<ACodecBufferChannel>(
new AMessage(kWhatInputBufferFilled, this),
- new AMessage(kWhatOutputBufferDrained, this));
+ new AMessage(kWhatOutputBufferDrained, this),
+ new AMessage(kWhatPollForRenderedBuffers, this));
}
return mBufferChannel;
}
@@ -744,6 +757,7 @@
// if we have not yet started the codec, we can simply set the native window
if (mBuffers[kPortIndexInput].size() == 0) {
mNativeWindow = surface;
+ initializeFrameTracking();
return OK;
}
@@ -852,6 +866,7 @@
mNativeWindow = nativeWindow;
mNativeWindowUsageBits = usageBits;
+ initializeFrameTracking();
return OK;
}
@@ -962,7 +977,6 @@
BufferInfo info;
info.mStatus = BufferInfo::OWNED_BY_US;
info.mFenceFd = -1;
- info.mRenderInfo = NULL;
info.mGraphicBuffer = NULL;
info.mNewGraphicBuffer = false;
@@ -1230,6 +1244,7 @@
*bufferCount = def.nBufferCountActual;
*bufferSize = def.nBufferSize;
+ initializeFrameTracking();
return err;
}
@@ -1268,7 +1283,6 @@
info.mStatus = BufferInfo::OWNED_BY_US;
info.mFenceFd = fenceFd;
info.mIsReadFence = false;
- info.mRenderInfo = NULL;
info.mGraphicBuffer = graphicBuffer;
info.mNewGraphicBuffer = false;
info.mDequeuedAt = mDequeueCounter;
@@ -1345,7 +1359,6 @@
BufferInfo info;
info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
info.mFenceFd = -1;
- info.mRenderInfo = NULL;
info.mGraphicBuffer = NULL;
info.mNewGraphicBuffer = false;
info.mDequeuedAt = mDequeueCounter;
@@ -1441,42 +1454,6 @@
return err;
}
-void ACodec::updateRenderInfoForDequeuedBuffer(
- ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) {
-
- info->mRenderInfo =
- mRenderTracker.updateInfoForDequeuedBuffer(
- buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]);
-
- // check for any fences already signaled
- notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo);
-}
-
-void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
- if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) {
- mRenderTracker.dumpRenderQueue();
- }
-}
-
-void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) {
- std::list<FrameRenderTracker::Info> done =
- mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete);
-
- // unlink untracked frames
- for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
- it != done.cend(); ++it) {
- ssize_t index = it->getIndex();
- if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
- mBuffers[kPortIndexOutput][index].mRenderInfo = NULL;
- } else if (index >= 0) {
- // THIS SHOULD NEVER HAPPEN
- ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
- }
- }
-
- mCallback->onOutputFramesRendered(done);
-}
-
void ACodec::onFirstTunnelFrameReady() {
mCallback->onFirstTunnelFrameReady();
}
@@ -1531,7 +1508,6 @@
info->mStatus = BufferInfo::OWNED_BY_US;
info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow");
- updateRenderInfoForDequeuedBuffer(buf, fenceFd, info);
return info;
}
}
@@ -1576,18 +1552,96 @@
oldest->mNewGraphicBuffer = true;
oldest->mStatus = BufferInfo::OWNED_BY_US;
oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest");
- mRenderTracker.untrackFrame(oldest->mRenderInfo);
- oldest->mRenderInfo = NULL;
ALOGV("replaced oldest buffer #%u with age %u, graphicBuffer %p",
(unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
mDequeueCounter - oldest->mDequeuedAt,
oldest->mGraphicBuffer->handle);
-
- updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
return oldest;
}
+void ACodec::initializeFrameTracking() {
+ mTrackedFrames.clear();
+
+ int isWindowToDisplay = 0;
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
+ &isWindowToDisplay);
+ mIsWindowToDisplay = isWindowToDisplay == 1;
+ // No frame tracking is needed if we're not sending frames to the display
+ if (!mIsWindowToDisplay) {
+ // Return early so we don't call into SurfaceFlinger (requiring permissions)
+ return;
+ }
+
+ int hasPresentFenceTimes = 0;
+ mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT,
+ &hasPresentFenceTimes);
+ mHasPresentFenceTimes = hasPresentFenceTimes == 1;
+ if (!mHasPresentFenceTimes) {
+ ALOGI("Using latch times for frame rendered signals - present fences not supported");
+ }
+
+ status_t err = native_window_enable_frame_timestamps(mNativeWindow.get(), true);
+ if (err) {
+ ALOGE("Failed to enable frame timestamps (%d)", err);
+ }
+}
+
+void ACodec::trackReleasedFrame(int64_t frameId, int64_t mediaTimeUs, int64_t desiredRenderTimeNs) {
+ // If the render time is earlier than now, then we're suggesting it should be rendered ASAP,
+ // so track the frame as if the desired render time is now.
+ int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ if (desiredRenderTimeNs < nowNs) {
+ desiredRenderTimeNs = nowNs;
+ }
+ // We've just queued a frame to the surface, so keep track of it and later check to see if it is
+ // actually rendered.
+ TrackedFrame frame;
+ frame.id = frameId;
+ frame.mediaTimeUs = mediaTimeUs;
+ frame.desiredRenderTimeNs = desiredRenderTimeNs;
+ mTrackedFrames.push_back(frame);
+}
+
+void ACodec::pollForRenderedFrames() {
+ std::list<RenderedFrameInfo> renderedFrameInfos;
+ // Scan all frames and check to see if the frames that SHOULD have been rendered by now, have,
+ // in fact, been rendered.
+ int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ while (!mTrackedFrames.empty()) {
+ TrackedFrame & frame = mTrackedFrames.front();
+ // Frames that should have been rendered at least 100ms in the past are checked
+ if (frame.desiredRenderTimeNs > nowNs - 100*1000*1000LL) {
+ break;
+ }
+
+ status_t err;
+ nsecs_t latchOrPresentTimeNs = NATIVE_WINDOW_TIMESTAMP_INVALID;
+ err = native_window_get_frame_timestamps(mNativeWindow.get(), frame.id,
+ /* outRequestedPresentTime */ nullptr, /* outAcquireTime */ nullptr,
+ mHasPresentFenceTimes ? nullptr : &latchOrPresentTimeNs, // latch time
+ /* outFirstRefreshStartTime */ nullptr, /* outLastRefreshStartTime */ nullptr,
+ /* outGpuCompositionDoneTime */ nullptr,
+ mHasPresentFenceTimes ? &latchOrPresentTimeNs : nullptr, // display present time,
+ /* outDequeueReadyTime */ nullptr, /* outReleaseTime */ nullptr);
+ if (err) {
+ ALOGE("Failed to get frame timestamps for %lld: %d", (long long) frame.id, err);
+ }
+ // If we don't have a render time by now, then consider the frame as dropped
+ if (latchOrPresentTimeNs != NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ latchOrPresentTimeNs != NATIVE_WINDOW_TIMESTAMP_INVALID) {
+ renderedFrameInfos.push_back(RenderedFrameInfo(frame.mediaTimeUs,
+ latchOrPresentTimeNs));
+ }
+
+ mTrackedFrames.pop_front();
+ }
+
+ if (!renderedFrameInfos.empty()) {
+ mCallback->onOutputFramesRendered(renderedFrameInfos);
+ }
+}
+
status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
if (portIndex == kPortIndexInput) {
mBufferChannel->setInputBufferArray({});
@@ -1663,11 +1717,6 @@
::close(info->mFenceFd);
}
- if (portIndex == kPortIndexOutput) {
- mRenderTracker.untrackFrame(info->mRenderInfo, i);
- info->mRenderInfo = NULL;
- }
-
// remove buffer even if mOMXNode->freeBuffer fails
mBuffers[portIndex].erase(mBuffers[portIndex].begin() + i);
return err;
@@ -6032,22 +6081,10 @@
sp<RefBase> obj;
CHECK(msg->findObject("messages", &obj));
sp<MessageList> msgList = static_cast<MessageList *>(obj.get());
-
- bool receivedRenderedEvents = false;
for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin();
it != msgList->getList().cend(); ++it) {
(*it)->setWhat(ACodec::kWhatOMXMessageItem);
mCodec->handleMessage(*it);
- int32_t type;
- CHECK((*it)->findInt32("type", &type));
- if (type == omx_message::FRAME_RENDERED) {
- receivedRenderedEvents = true;
- }
- }
-
- if (receivedRenderedEvents) {
- // NOTE: all buffers are rendered in this case
- mCodec->notifyOfRenderedFrames();
}
return true;
}
@@ -6609,15 +6646,6 @@
info->mDequeuedAt = ++mCodec->mDequeueCounter;
info->mStatus = BufferInfo::OWNED_BY_US;
- if (info->mRenderInfo != NULL) {
- // The fence for an emptied buffer must have signaled, but there still could be queued
- // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,
- // as we will soon requeue this buffer to the surface. While in theory we could still keep
- // track of buffers that are requeued to the surface, it is better to add support to the
- // buffer-queue to notify us of released buffers and their fences (in the future).
- mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);
- }
-
// byte buffers cannot take fences, so wait for any fence now
if (mCodec->mNativeWindow == NULL) {
(void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");
@@ -6824,14 +6852,6 @@
mCodec->mLastHdr10PlusBuffer = hdr10PlusInfo;
}
- // save buffers sent to the surface so we can get render time when they return
- int64_t mediaTimeUs = -1;
- buffer->meta()->findInt64("timeUs", &mediaTimeUs);
- if (mediaTimeUs >= 0) {
- mCodec->mRenderTracker.onFrameQueued(
- mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
- }
-
int64_t timestampNs = 0;
if (!msg->findInt64("timestampNs", ×tampNs)) {
// use media timestamp if client did not request a specific render timestamp
@@ -6845,11 +6865,25 @@
err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
+ uint64_t frameId;
+ err = native_window_get_next_frame_id(mCodec->mNativeWindow.get(), &frameId);
+
info->checkReadFence("onOutputBufferDrained before queueBuffer");
err = mCodec->mNativeWindow->queueBuffer(
mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
- // TODO(b/266211548): Poll the native window for rendered buffers, since when queueing
- // buffers, the frame event history delta is retrieved.
+
+ int64_t mediaTimeUs = -1;
+ buffer->meta()->findInt64("timeUs", &mediaTimeUs);
+ if (mCodec->mAreRenderMetricsEnabled && mCodec->mIsWindowToDisplay) {
+ mCodec->trackReleasedFrame(frameId, mediaTimeUs, timestampNs);
+ mCodec->pollForRenderedFrames();
+ } else {
+ // When the surface is an intermediate surface, onFrameRendered is triggered immediately
+ // when the frame is queued to the non-display surface
+ mCodec->mCallback->onOutputFramesRendered({RenderedFrameInfo(mediaTimeUs,
+ timestampNs)});
+ }
+
info->mFenceFd = -1;
if (err == OK) {
info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
@@ -7076,7 +7110,6 @@
++mCodec->mNodeGeneration;
mCodec->mComponentName = componentName;
- mCodec->mRenderTracker.setComponentName(componentName);
mCodec->mFlags = 0;
if (componentName.endsWith(".secure")) {
@@ -7713,7 +7746,6 @@
void ACodec::ExecutingState::stateEntered() {
ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
- mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
mCodec->processDeferredMessages();
}
@@ -7824,7 +7856,15 @@
mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
}
}
- return true;
+ handled = true;
+ break;
+ }
+
+ case kWhatPollForRenderedBuffers:
+ {
+ mCodec->pollForRenderedFrames();
+ handled = true;
+ break;
}
default:
@@ -8520,7 +8560,7 @@
}
bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
- mCodec->onFrameRendered(mediaTimeUs, systemNano);
+ mCodec->mCallback->onOutputFramesRendered({RenderedFrameInfo(mediaTimeUs, systemNano)});
return true;
}
@@ -8694,7 +8734,7 @@
bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered(
int64_t mediaTimeUs, nsecs_t systemNano) {
- mCodec->onFrameRendered(mediaTimeUs, systemNano);
+ mCodec->mCallback->onOutputFramesRendered({RenderedFrameInfo(mediaTimeUs, systemNano)});
return true;
}
@@ -8725,10 +8765,6 @@
OMX_CommandPortEnable, kPortIndexOutput);
}
- // Clear the RenderQueue in which queued GraphicBuffers hold the
- // actual buffer references in order to free them early.
- mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
-
if (err == OK) {
err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
@@ -9112,8 +9148,6 @@
// the native window for rendering. Let's get those back as well.
mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
- mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
-
mCodec->mCallback->onFlushCompleted();
mCodec->mPortEOS[kPortIndexInput] =
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 8f2bed2..ad42813 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -32,6 +32,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/ACodec.h>
#include <media/stagefright/MediaCodec.h>
#include <media/MediaCodecBuffer.h>
#include <system/window.h>
@@ -87,9 +88,11 @@
}
ACodecBufferChannel::ACodecBufferChannel(
- const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
+ const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained,
+ const sp<AMessage> &pollForRenderedBuffers)
: mInputBufferFilled(inputBufferFilled),
mOutputBufferDrained(outputBufferDrained),
+ mPollForRenderedBuffers(pollForRenderedBuffers),
mHeapSeqNum(-1) {
}
@@ -488,7 +491,7 @@
}
void ACodecBufferChannel::pollForRenderedBuffers() {
- // TODO(b/266211548): Poll the native window for rendered buffers.
+ mPollForRenderedBuffers->post();
}
status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 91286b9..ea24126 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -79,6 +79,7 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/PersistentSurface.h>
+#include <media/stagefright/RenderedFrameInfo.h>
#include <media/stagefright/SurfaceUtils.h>
#include <nativeloader/dlext_namespaces.h>
#include <private/android_filesystem_config.h>
@@ -210,6 +211,7 @@
// Render metrics
static const char *kCodecPlaybackDurationSec = "android.media.mediacodec.playback-duration-sec";
static const char *kCodecFirstRenderTimeUs = "android.media.mediacodec.first-render-time-us";
+static const char *kCodecLastRenderTimeUs = "android.media.mediacodec.last-render-time-us";
static const char *kCodecFramesReleased = "android.media.mediacodec.frames-released";
static const char *kCodecFramesRendered = "android.media.mediacodec.frames-rendered";
static const char *kCodecFramesDropped = "android.media.mediacodec.frames-dropped";
@@ -879,7 +881,7 @@
const sp<AMessage> &outputFormat) override;
virtual void onInputSurfaceDeclined(status_t err) override;
virtual void onSignaledInputEOS(status_t err) override;
- virtual void onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) override;
+ virtual void onOutputFramesRendered(const std::list<RenderedFrameInfo> &done) override;
virtual void onOutputBuffersChanged() override;
virtual void onFirstTunnelFrameReady() override;
private:
@@ -988,7 +990,7 @@
notify->post();
}
-void CodecCallback::onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) {
+void CodecCallback::onOutputFramesRendered(const std::list<RenderedFrameInfo> &done) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatOutputFramesRendered);
if (MediaCodec::CreateFramesRenderedMessage(done, notify)) {
@@ -1297,6 +1299,7 @@
const VideoRenderQualityMetrics &m = mVideoRenderQualityTracker.getMetrics();
if (m.frameReleasedCount > 0) {
mediametrics_setInt64(mMetricsHandle, kCodecFirstRenderTimeUs, m.firstRenderTimeUs);
+ mediametrics_setInt64(mMetricsHandle, kCodecLastRenderTimeUs, m.lastRenderTimeUs);
mediametrics_setInt64(mMetricsHandle, kCodecFramesReleased, m.frameReleasedCount);
mediametrics_setInt64(mMetricsHandle, kCodecFramesRendered, m.frameRenderedCount);
mediametrics_setInt64(mMetricsHandle, kCodecFramesSkipped, m.frameSkippedCount);
@@ -6087,12 +6090,10 @@
return onQueueInputBuffer(msg);
}
-//static
-size_t MediaCodec::CreateFramesRenderedMessage(
- const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
+template<typename T>
+static size_t CreateFramesRenderedMessageInternal(const std::list<T> &done, sp<AMessage> &msg) {
size_t index = 0;
- for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
- it != done.cend(); ++it) {
+ for (typename std::list<T>::const_iterator it = done.cbegin(); it != done.cend(); ++it) {
if (it->getRenderTimeNs() < 0) {
continue; // dropped frame from tracking
}
@@ -6103,6 +6104,18 @@
return index;
}
+//static
+size_t MediaCodec::CreateFramesRenderedMessage(
+ const std::list<RenderedFrameInfo> &done, sp<AMessage> &msg) {
+ return CreateFramesRenderedMessageInternal(done, msg);
+}
+
+//static
+size_t MediaCodec::CreateFramesRenderedMessage(
+ const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
+ return CreateFramesRenderedMessageInternal(done, msg);
+}
+
status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
size_t index;
CHECK(msg->findSize("index", &index));
@@ -6194,7 +6207,9 @@
// presentation timestamp is used instead, which almost certainly occurs in the past,
// since it's almost always a zero-based offset from the start of the stream. In these
// scenarios, we expect the frame to be rendered with no delay.
- int64_t delayUs = noRenderTime ? 0 : renderTimeNs / 1000 - ALooper::GetNowUs();
+ int64_t nowUs = ALooper::GetNowUs();
+ int64_t renderTimeUs = renderTimeNs / 1000;
+ int64_t delayUs = renderTimeUs < nowUs ? 0 : renderTimeUs - nowUs;
delayUs += 100 * 1000; /* 100ms in microseconds */
status_t err =
mMsgPollForRenderedBuffers->postUnique(/* token= */ mMsgPollForRenderedBuffers,
diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp
index fbd8577..e920bd1 100644
--- a/media/libstagefright/VideoRenderQualityTracker.cpp
+++ b/media/libstagefright/VideoRenderQualityTracker.cpp
@@ -455,6 +455,8 @@
if (mMetrics.firstRenderTimeUs == 0) {
mMetrics.firstRenderTimeUs = actualRenderTimeUs;
}
+ // Capture the timestamp at which the last frame was rendered
+ mMetrics.lastRenderTimeUs = actualRenderTimeUs;
mMetrics.frameRenderedCount++;
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 903280f..a464504 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -29,6 +29,7 @@
#include <media/IOMX.h>
namespace android {
+ struct ACodec;
namespace hardware {
class HidlMemory;
};
@@ -63,7 +64,8 @@
};
ACodecBufferChannel(
- const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained);
+ const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained,
+ const sp<AMessage> &pollForRenderedBuffers);
virtual ~ACodecBufferChannel();
// BufferChannelBase interface
@@ -138,6 +140,7 @@
const sp<AMessage> mInputBufferFilled;
const sp<AMessage> mOutputBufferDrained;
+ const sp<AMessage> mPollForRenderedBuffers;
sp<MemoryDealer> mDealer;
sp<IMemory> mDecryptDestination;
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index e535d5d..f876bc6 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -19,7 +19,7 @@
#include <set>
#include <stdint.h>
-#include <list>
+#include <deque>
#include <vector>
#include <android/native_window.h>
#include <media/hardware/MetadataBufferType.h>
@@ -27,9 +27,9 @@
#include <media/IOMX.h>
#include <media/stagefright/AHierarchicalStateMachine.h>
#include <media/stagefright/CodecBase.h>
-#include <media/stagefright/FrameRenderTracker.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/SkipCutBuffer.h>
+#include <ui/GraphicBuffer.h>
#include <utils/NativeHandle.h>
#include <OMX_Audio.h>
#include <hardware/gralloc.h>
@@ -156,6 +156,7 @@
kWhatForceStateTransition = 'fstt',
kWhatCheckIfStuck = 'Cstk',
kWhatSubmitExtraOutputMetadataBuffer = 'sbxo',
+ kWhatPollForRenderedBuffers = 'pfrb',
};
enum {
@@ -177,6 +178,13 @@
| static_cast<uint64_t>(BufferUsage::VIDEO_DECODER),
};
+ struct TrackedFrame {
+ int64_t id;
+ int64_t mediaTimeUs;
+ int64_t desiredRenderTimeNs;
+ nsecs_t renderTimeNs;
+ };
+
struct BufferInfo {
enum Status {
OWNED_BY_US,
@@ -204,7 +212,6 @@
sp<GraphicBuffer> mGraphicBuffer;
bool mNewGraphicBuffer;
int mFenceFd;
- FrameRenderTracker::Info *mRenderInfo;
// The following field and 4 methods are used for debugging only
bool mIsReadFence;
@@ -251,6 +258,11 @@
int32_t mNodeGeneration;
sp<TAllocator> mAllocator[2];
+ std::deque<TrackedFrame> mTrackedFrames; // render information for buffers sent to a window
+ bool mAreRenderMetricsEnabled;
+ bool mIsWindowToDisplay;
+ bool mHasPresentFenceTimes;
+
bool mUsingNativeWindow;
sp<ANativeWindow> mNativeWindow;
int mNativeWindowUsageBits;
@@ -267,7 +279,6 @@
// format updates. This will equal to mOutputFormat until the first actual frame is received.
sp<AMessage> mBaseOutputFormat;
- FrameRenderTracker mRenderTracker; // render information for buffers rendered by ACodec
std::vector<BufferInfo> mBuffers[2];
bool mPortEOS[2];
status_t mInputEOSResult;
@@ -349,6 +360,10 @@
status_t freeOutputBuffersNotOwnedByComponent();
BufferInfo *dequeueBufferFromNativeWindow();
+ void initializeFrameTracking();
+ void trackReleasedFrame(int64_t frameId, int64_t mediaTimeUs, int64_t desiredRenderTimeNs);
+ void pollForRenderedFrames();
+
inline bool storingMetadataInDecodedBuffers() {
return (mPortMode[kPortIndexOutput] == IOMX::kPortModeDynamicANWBuffer) && !mIsEncoder;
}
@@ -571,21 +586,6 @@
void processDeferredMessages();
void onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
- // called when we have dequeued a buffer |buf| from the native window to track render info.
- // |fenceFd| is the dequeue fence, and |info| points to the buffer info where this buffer is
- // stored.
- void updateRenderInfoForDequeuedBuffer(
- ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info);
-
- // Checks to see if any frames have rendered up until |until|, and to notify client
- // (MediaCodec) of rendered frames up-until the frame pointed to by |until| or the first
- // unrendered frame. These frames are removed from the render queue.
- // If |dropIncomplete| is true, unrendered frames up-until |until| will be dropped from the
- // queue, allowing all rendered framed up till then to be notified of.
- // (This will effectively clear the render queue up-until (and including) |until|.)
- // If |until| is NULL, or is not in the rendered queue, this method will check all frames.
- void notifyOfRenderedFrames(
- bool dropIncomplete = false, FrameRenderTracker::Info *until = NULL);
void onFirstTunnelFrameReady();
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index 916d41e..90347f9 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -41,7 +41,7 @@
struct BufferProducerWrapper;
class MediaCodecBuffer;
struct PersistentSurface;
-struct RenderedFrameInfo;
+class RenderedFrameInfo;
class Surface;
struct ICrypto;
class IMemory;
diff --git a/media/libstagefright/include/media/stagefright/FrameRenderTracker.h b/media/libstagefright/include/media/stagefright/FrameRenderTracker.h
index c14755a..cab7ecc 100644
--- a/media/libstagefright/include/media/stagefright/FrameRenderTracker.h
+++ b/media/libstagefright/include/media/stagefright/FrameRenderTracker.h
@@ -32,61 +32,59 @@
namespace android {
-// Tracks the render information about a frame. Frames go through several states while
-// the render information is tracked:
-//
-// 1. queued frame: mMediaTime and mGraphicBuffer are set for the frame. mFence is the
-// queue fence (read fence). mIndex is negative, and mRenderTimeNs is invalid.
-// Key characteristics: mFence is not NULL and mIndex is negative.
-//
-// 2. dequeued frame: mFence is updated with the dequeue fence (write fence). mIndex is set.
-// Key characteristics: mFence is not NULL and mIndex is non-negative. mRenderTime is still
-// invalid.
-//
-// 3. rendered frame or frame: mFence is cleared, mRenderTimeNs is set.
-// Key characteristics: mFence is NULL.
-//
-struct RenderedFrameInfo {
- // set by client during onFrameQueued or onFrameRendered
- int64_t getMediaTimeUs() const { return mMediaTimeUs; }
-
- // -1 if frame is not yet rendered
- nsecs_t getRenderTimeNs() const { return mRenderTimeNs; }
-
- // set by client during updateRenderInfoForDequeuedBuffer; -1 otherwise
- ssize_t getIndex() const { return mIndex; }
-
- // creates information for a queued frame
- RenderedFrameInfo(int64_t mediaTimeUs, const sp<GraphicBuffer> &graphicBuffer,
- const sp<Fence> &fence)
- : mMediaTimeUs(mediaTimeUs),
- mRenderTimeNs(-1),
- mIndex(-1),
- mGraphicBuffer(graphicBuffer),
- mFence(fence) {
- }
-
- // creates information for a frame rendered on a tunneled surface
- RenderedFrameInfo(int64_t mediaTimeUs, nsecs_t renderTimeNs)
- : mMediaTimeUs(mediaTimeUs),
- mRenderTimeNs(renderTimeNs),
- mIndex(-1),
- mGraphicBuffer(NULL),
- mFence(NULL) {
- }
-
-private:
- int64_t mMediaTimeUs;
- nsecs_t mRenderTimeNs;
- ssize_t mIndex; // to be used by client
- sp<GraphicBuffer> mGraphicBuffer;
- sp<Fence> mFence;
-
- friend struct FrameRenderTracker;
-};
-
struct FrameRenderTracker {
- typedef RenderedFrameInfo Info;
+ // Tracks the render information about a frame. Frames go through several states while
+ // the render information is tracked:
+ //
+ // 1. queued frame: mMediaTime and mGraphicBuffer are set for the frame. mFence is the
+ // queue fence (read fence). mIndex is negative, and mRenderTimeNs is invalid.
+ // Key characteristics: mFence is not NULL and mIndex is negative.
+ //
+ // 2. dequeued frame: mFence is updated with the dequeue fence (write fence). mIndex is set.
+ // Key characteristics: mFence is not NULL and mIndex is non-negative. mRenderTime is still
+ // invalid.
+ //
+ // 3. rendered frame or frame: mFence is cleared, mRenderTimeNs is set.
+ // Key characteristics: mFence is NULL.
+ //
+ struct Info {
+ // set by client during onFrameQueued or onFrameRendered
+ int64_t getMediaTimeUs() const { return mMediaTimeUs; }
+
+ // -1 if frame is not yet rendered
+ nsecs_t getRenderTimeNs() const { return mRenderTimeNs; }
+
+ // set by client during updateRenderInfoForDequeuedBuffer; -1 otherwise
+ ssize_t getIndex() const { return mIndex; }
+
+ // creates information for a queued frame
+ Info(int64_t mediaTimeUs, const sp<GraphicBuffer> &graphicBuffer,
+ const sp<Fence> &fence)
+ : mMediaTimeUs(mediaTimeUs),
+ mRenderTimeNs(-1),
+ mIndex(-1),
+ mGraphicBuffer(graphicBuffer),
+ mFence(fence) {
+ }
+
+ // creates information for a frame rendered on a tunneled surface
+ Info(int64_t mediaTimeUs, nsecs_t renderTimeNs)
+ : mMediaTimeUs(mediaTimeUs),
+ mRenderTimeNs(renderTimeNs),
+ mIndex(-1),
+ mGraphicBuffer(NULL),
+ mFence(NULL) {
+ }
+
+ private:
+ int64_t mMediaTimeUs;
+ nsecs_t mRenderTimeNs;
+ ssize_t mIndex; // to be used by client
+ sp<GraphicBuffer> mGraphicBuffer;
+ sp<Fence> mFence;
+
+ friend struct FrameRenderTracker;
+ };
FrameRenderTracker();
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index bc0f6c5..ceba7d7 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -64,6 +64,7 @@
class MediaCodecBuffer;
class IMemory;
struct PersistentSurface;
+class RenderedFrameInfo;
class SoftwareRenderer;
class Surface;
namespace hardware {
@@ -281,6 +282,8 @@
// by adding rendered frame information to a base notification message. Returns the number
// of frames that were rendered.
static size_t CreateFramesRenderedMessage(
+ const std::list<RenderedFrameInfo> &done, sp<AMessage> &msg);
+ static size_t CreateFramesRenderedMessage(
const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg);
static status_t CanFetchLinearBlock(
diff --git a/media/libstagefright/include/media/stagefright/RenderedFrameInfo.h b/media/libstagefright/include/media/stagefright/RenderedFrameInfo.h
new file mode 100644
index 0000000..4b8a58d
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/RenderedFrameInfo.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 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 RENDERED_FRAME_INFO_H
+#define RENDERED_FRAME_INFO_H
+
+namespace android {
+
+class RenderedFrameInfo {
+public:
+ RenderedFrameInfo(int64_t mediaTimeUs, int64_t renderTimeNs)
+ : mMediaTimeUs(mediaTimeUs), mRenderTimeNs(renderTimeNs) {}
+
+ int64_t getMediaTimeUs() const { return mMediaTimeUs; }
+ nsecs_t getRenderTimeNs() const { return mRenderTimeNs;}
+
+private:
+ int64_t mMediaTimeUs;
+ nsecs_t mRenderTimeNs;
+};
+
+} // android
+
+#endif // RENDERED_FRAME_INFO_H
\ No newline at end of file
diff --git a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
index 82ba81c..a656e6e 100644
--- a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
+++ b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
@@ -38,6 +38,9 @@
// The render time of the first video frame.
int64_t firstRenderTimeUs;
+ // The render time of the last video frame.
+ int64_t lastRenderTimeUs;
+
// The number of frames released to be rendered.
int64_t frameReleasedCount;
diff --git a/media/utils/BatteryNotifier.cpp b/media/utils/BatteryNotifier.cpp
index 09bc042..7762c24 100644
--- a/media/utils/BatteryNotifier.cpp
+++ b/media/utils/BatteryNotifier.cpp
@@ -85,8 +85,8 @@
void BatteryNotifier::noteStopAudio(uid_t uid) {
Mutex::Autolock _l(mLock);
- if (mAudioRefCounts.find(uid) == mAudioRefCounts.end()) {
- ALOGW("%s: audio refcount is broken for uid(%d).", __FUNCTION__, (int)uid);
+ if (mAudioRefCounts.find(uid) == mAudioRefCounts.end() || (mAudioRefCounts[uid] == 0)) {
+ ALOGE("%s: audio refcount is broken for uid(%d).", __FUNCTION__, (int)uid);
return;
}
diff --git a/media/utils/include/mediautils/BatteryNotifier.h b/media/utils/include/mediautils/BatteryNotifier.h
index 3812d7a..73bed4a 100644
--- a/media/utils/include/mediautils/BatteryNotifier.h
+++ b/media/utils/include/mediautils/BatteryNotifier.h
@@ -68,6 +68,38 @@
sp<IBatteryStats> getBatteryService_l();
};
+namespace mediautils {
+class BatteryStatsAudioHandle {
+ public:
+ static constexpr uid_t INVALID_UID = static_cast<uid_t>(-1);
+
+ explicit BatteryStatsAudioHandle(uid_t uid) : mUid(uid) {
+ if (uid != INVALID_UID) {
+ BatteryNotifier::getInstance().noteStartAudio(mUid);
+ }
+ }
+
+ BatteryStatsAudioHandle(BatteryStatsAudioHandle&& other) : mUid(other.mUid) {
+ other.mUid = INVALID_UID;
+ }
+
+ BatteryStatsAudioHandle(const BatteryStatsAudioHandle& other) = delete;
+
+ BatteryStatsAudioHandle& operator=(const BatteryStatsAudioHandle& other) = delete;
+
+ BatteryStatsAudioHandle& operator=(BatteryStatsAudioHandle&& other) = delete;
+
+ ~BatteryStatsAudioHandle() {
+ if (mUid != INVALID_UID) {
+ BatteryNotifier::getInstance().noteStopAudio(mUid);
+ }
+ }
+
+ private:
+ // Logically const
+ uid_t mUid = INVALID_UID;
+};
+} // namespace mediautils
} // namespace android
#endif // MEDIA_BATTERY_NOTIFIER_H
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 a0985c7..4842d0b 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -86,7 +86,9 @@
#include <private/android_filesystem_config.h>
//#define BUFLOG_NDEBUG 0
+#include <afutils/DumpTryLock.h>
#include <afutils/BufLog.h>
+#include <afutils/Permission.h>
#include <afutils/TypedLogger.h>
// ----------------------------------------------------------------------------
@@ -126,8 +128,6 @@
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);
@@ -269,33 +269,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) {
@@ -328,10 +301,7 @@
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)
{
@@ -405,7 +375,8 @@
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 +384,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) {
@@ -433,9 +407,9 @@
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();
+ Mutex::Autolock _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);
@@ -476,12 +450,12 @@
return NO_ERROR;
}
-int32_t AudioFlinger::getAAudioMixerBurstCount() {
+int32_t AudioFlinger::getAAudioMixerBurstCount() const {
Mutex::Autolock _l(mLock);
return mAAudioBurstsPerBuffer;
}
-int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() {
+int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() const {
Mutex::Autolock _l(mLock);
return mAAudioHwBurstMinMicros;
}
@@ -527,7 +501,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 {};
}
@@ -638,7 +612,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) {
@@ -678,9 +652,9 @@
// 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;
@@ -857,12 +831,6 @@
write(fd, result.string(), 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,7 +838,7 @@
dumpPermissionDenial(fd, args);
} else {
// get state of hardware lock
- bool hardwareLocked = dumpTryLock(mHardwareLock);
+ const bool hardwareLocked = afutils::dumpTryLock(mHardwareLock);
if (!hardwareLocked) {
String8 result(kHardwareLockedString);
write(fd, result.string(), result.size());
@@ -878,7 +846,7 @@
mHardwareLock.unlock();
}
- const bool locked = dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mLock);
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
@@ -886,7 +854,7 @@
write(fd, result.string(), result.size());
}
- bool clientLocked = dumpTryLock(mClientLock);
+ const bool clientLocked = afutils::dumpTryLock(mClientLock);
if (!clientLocked) {
String8 result(kClientLockedString);
write(fd, result.string(), result.size());
@@ -934,7 +902,7 @@
dev->dump(fd, args);
}
- mPatchPanel.dump(fd);
+ mPatchPanel->dump(fd);
mDeviceEffectManager->dump(fd);
@@ -1036,7 +1004,7 @@
// (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);
}
@@ -1107,7 +1075,7 @@
CreateTrackInput input = VALUE_OR_RETURN_STATUS(CreateTrackInput::fromAidl(_input));
CreateTrackOutput output;
- sp<PlaybackThread::Track> track;
+ sp<IAfTrack> track;
sp<Client> client;
status_t lStatus;
audio_stream_type_t streamType;
@@ -1144,7 +1112,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,7 +1159,7 @@
{
Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output.outputId);
+ IAfPlaybackThread* thread = checkPlaybackThread_l(output.outputId);
if (thread == NULL) {
ALOGE("no playback thread found for output handle %d", output.outputId);
lStatus = BAD_VALUE;
@@ -1200,14 +1168,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,7 +1210,7 @@
if (lStatus == NO_ERROR) {
// no risk of deadlock because AudioFlinger::mLock is held
- Mutex::Autolock _dl(thread->mLock);
+ Mutex::Autolock _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.
@@ -1250,7 +1218,7 @@
// 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);
+ Mutex::Autolock _sl(effectThread->mutex());
if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
effectThreadId = thread->id();
effectIds = thread->getEffectIds_l(sessionId);
@@ -1297,7 +1265,7 @@
AudioSystem::moveEffectsToIo(effectIds, effectThreadId);
}
- output.audioTrack = PlaybackThread::Track::createIAudioTrackAdapter(track);
+ output.audioTrack = IAfTrack::createIAudioTrackAdapter(track);
_output = VALUE_OR_FATAL(output.toAidl());
Exit:
@@ -1310,7 +1278,7 @@
uint32_t AudioFlinger::sampleRate(audio_io_handle_t ioHandle) const
{
Mutex::Autolock _l(mLock);
- ThreadBase *thread = checkThread_l(ioHandle);
+ IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("sampleRate() unknown thread %d", ioHandle);
return 0;
@@ -1321,7 +1289,7 @@
audio_format_t AudioFlinger::format(audio_io_handle_t output) const
{
Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("format() unknown thread %d", output);
return AUDIO_FORMAT_INVALID;
@@ -1332,7 +1300,7 @@
size_t AudioFlinger::frameCount(audio_io_handle_t ioHandle) const
{
Mutex::Autolock _l(mLock);
- ThreadBase *thread = checkThread_l(ioHandle);
+ IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("frameCount() unknown thread %d", ioHandle);
return 0;
@@ -1345,7 +1313,7 @@
size_t AudioFlinger::frameCountHAL(audio_io_handle_t ioHandle) const
{
Mutex::Autolock _l(mLock);
- ThreadBase *thread = checkThread_l(ioHandle);
+ IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("frameCountHAL() unknown thread %d", ioHandle);
return 0;
@@ -1356,7 +1324,7 @@
uint32_t AudioFlinger::latency(audio_io_handle_t output) const
{
Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("latency(): no playback thread found for output handle %d", output);
return 0;
@@ -1585,7 +1553,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);
}
@@ -1661,7 +1629,7 @@
"AUDIO_STREAM_PATCH must have full scale volume");
AutoMutex lock(mLock);
- VolumeInterface *volumeInterface = getVolumeInterface_l(output);
+ sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
if (volumeInterface == NULL) {
return BAD_VALUE;
}
@@ -1676,7 +1644,7 @@
return BAD_VALUE;
}
AutoMutex lock(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == nullptr) {
return BAD_VALUE;
}
@@ -1684,12 +1652,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);
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == nullptr) {
return BAD_VALUE;
}
@@ -1711,7 +1679,7 @@
return status;
}
-status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool *enabled) {
+status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool* enabled) const {
if (enabled == nullptr) {
return BAD_VALUE;
}
@@ -1719,7 +1687,7 @@
return NO_ERROR;
}
-status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) {
+status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) const {
if (support == nullptr) {
return BAD_VALUE;
}
@@ -1735,7 +1703,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;
}
@@ -1764,7 +1732,7 @@
AutoMutex lock(mLock);
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,7 +1751,7 @@
}
AutoMutex lock(mLock);
- VolumeInterface *volumeInterface = getVolumeInterface_l(output);
+ sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
if (volumeInterface == NULL) {
return 0.0f;
}
@@ -1820,14 +1788,15 @@
// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock 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);
}
@@ -1839,7 +1808,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;
}
@@ -1953,8 +1922,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;
@@ -1962,7 +1931,7 @@
// 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);
thread = checkPlaybackThread_l(ioHandle);
@@ -2011,11 +1980,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("");
}
@@ -2111,7 +2080,7 @@
{
Mutex::Autolock _l(mLock);
- RecordThread *recordThread = checkRecordThread_l(ioHandle);
+ IAfRecordThread* const recordThread = checkRecordThread_l(ioHandle);
if (recordThread != NULL) {
return recordThread->getInputFramesLost();
}
@@ -2151,7 +2120,7 @@
{
Mutex::Autolock _l(mLock);
- PlaybackThread *playbackThread = checkPlaybackThread_l(output);
+ IAfPlaybackThread* const playbackThread = checkPlaybackThread_l(output);
if (playbackThread != NULL) {
return playbackThread->getRenderPosition(halFrames, dspFrames);
}
@@ -2274,10 +2243,10 @@
}
// getEffectThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::ThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
+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) {
@@ -2306,27 +2275,6 @@
return thread;
}
-
-
-// ----------------------------------------------------------------------------
-
-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
-Client::~Client()
-{
- mAudioFlinger->removeClient_l(mPid);
-}
-
-AllocatorFactory::ClientAllocator& Client::allocator()
-{
- return mClientAllocator;
-}
-
// ----------------------------------------------------------------------------
AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
@@ -2391,7 +2339,7 @@
CreateRecordInput input = VALUE_OR_RETURN_STATUS(CreateRecordInput::fromAidl(_input));
CreateRecordOutput output;
- sp<RecordThread::RecordTrack> recordTrack;
+ sp<IAfRecordTrack> recordTrack;
sp<Client> client;
status_t lStatus;
audio_session_t sessionId = input.sessionId;
@@ -2423,7 +2371,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)) {
@@ -2480,7 +2428,7 @@
{
Mutex::Autolock _l(mLock);
- RecordThread *thread = checkRecordThread_l(output.inputId);
+ IAfRecordThread* const thread = checkRecordThread_l(output.inputId);
if (thread == NULL) {
ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
lStatus = FAILED_TRANSACTION;
@@ -2536,7 +2484,7 @@
// session and move it to this thread.
sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l2(thread->mLock);
+ Mutex::Autolock _l2(thread->mutex());
thread->addEffectChain_l(chain);
}
break;
@@ -2549,7 +2497,7 @@
output.buffers = recordTrack->getBuffers();
output.portId = portId;
- output.audioRecord = RecordThread::RecordTrack::createIAudioRecordAdapter(recordTrack);
+ output.audioRecord = IAfRecordTrack::createIAudioRecordAdapter(recordTrack);
_output = VALUE_OR_FATAL(output.toAidl());
Exit:
@@ -2735,17 +2683,17 @@
// ----------------------------------------------------------------------------
-uint32_t AudioFlinger::getPrimaryOutputSamplingRate()
+uint32_t AudioFlinger::getPrimaryOutputSamplingRate() const
{
Mutex::Autolock _l(mLock);
- PlaybackThread *thread = fastPlaybackThread_l();
+ 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();
+ IAfPlaybackThread* const thread = fastPlaybackThread_l();
return thread != NULL ? thread->frameCountHAL() : 0;
}
@@ -2870,15 +2818,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;
}
}
@@ -2897,15 +2845,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();
}
@@ -2930,7 +2878,7 @@
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);
status_t status = INVALID_OPERATION;
@@ -2957,7 +2905,8 @@
}
// setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId)
+void AudioFlinger::setAudioHwSyncForSession_l(
+ IAfPlaybackThread* const thread, audio_session_t sessionId)
{
ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
if (index >= 0) {
@@ -2968,7 +2917,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(); });
}
}
@@ -2976,7 +2925,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,
@@ -3034,43 +2983,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,
+ 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,12 +3067,12 @@
Mutex::Autolock _l(mLock);
- 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
@@ -3139,8 +3090,7 @@
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(
@@ -3158,8 +3108,8 @@
audio_io_handle_t output2)
{
Mutex::Autolock _l(mLock);
- MixerThread *thread1 = checkMixerThread_l(output1);
- MixerThread *thread2 = checkMixerThread_l(output2);
+ 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,
@@ -3168,7 +3118,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
@@ -3185,8 +3136,8 @@
{
// 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);
playbackThread = checkPlaybackThread_l(output);
@@ -3195,12 +3146,12 @@
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());
}
}
}
@@ -3209,11 +3160,12 @@
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);
+ Mutex::Autolock _dl(dstThread->mutex());
+ Mutex::Autolock _sl(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(),
@@ -3222,7 +3174,8 @@
}
}
} 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;
}
@@ -3231,10 +3184,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();
@@ -3252,7 +3205,7 @@
return NO_ERROR;
}
-void AudioFlinger::closeOutputFinish(const sp<PlaybackThread>& thread)
+void AudioFlinger::closeOutputFinish(const sp<IAfPlaybackThread>& thread)
{
AudioStreamOut *out = thread->clearOutput();
ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
@@ -3260,9 +3213,9 @@
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);
}
@@ -3270,7 +3223,7 @@
status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
{
Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
return BAD_VALUE;
@@ -3285,7 +3238,7 @@
status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
{
Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
return BAD_VALUE;
@@ -3314,7 +3267,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,
@@ -3338,7 +3291,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,
@@ -3404,17 +3357,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;
@@ -3434,8 +3388,8 @@
{
// 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);
recordThread = checkRecordThread_l(input);
@@ -3450,8 +3404,8 @@
// new capture on the same session
sp<IAfEffectChain> chain;
{
- Mutex::Autolock _sl(recordThread->mLock);
- Vector< sp<IAfEffectChain> > effectChains = recordThread->getEffectChains_l();
+ Mutex::Autolock _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];
@@ -3463,12 +3417,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);
+ Mutex::Autolock _l2(t->mutex());
ALOGV("closeInput() found thread %d for effect session %d",
t->id(), chain->sessionId());
t->addEffectChain_l(chain);
@@ -3482,7 +3436,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;
}
@@ -3505,7 +3460,7 @@
return NO_ERROR;
}
-void AudioFlinger::closeInputFinish(const sp<RecordThread>& thread)
+void AudioFlinger::closeInputFinish(const sp<IAfRecordThread>& thread)
{
thread->exit();
AudioStreamIn *in = thread->clearInput();
@@ -3514,9 +3469,9 @@
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);
}
@@ -3526,7 +3481,7 @@
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;
@@ -3646,14 +3601,15 @@
ALOGV("purging stale effects");
- Vector< sp<IAfEffectChain> > chains;
+ 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<IAfEffectChain> ec = t->mEffectChains[j];
+ sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
+ Mutex::Autolock _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);
}
@@ -3661,19 +3617,21 @@
}
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<IAfEffectChain> ec = t->mEffectChains[j];
+ sp<IAfRecordThread> t = mRecordThreads.valueAt(i);
+ Mutex::Autolock _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<IAfEffectChain> ec = t->mEffectChains[j];
+ const sp<IAfMmapThread> t = mMmapThreads.valueAt(i);
+ Mutex::Autolock _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);
}
}
@@ -3682,7 +3640,7 @@
// clang-tidy suggests const ref
sp<IAfEffectChain> ec = chains[i]; // NOLINT(performance-unnecessary-copy-initialization)
int sessionid = ec->sessionId();
- sp<ThreadBase> t = sp<ThreadBase>::cast(ec->thread().promote()); // TODO(b/288339104)
+ const auto t = ec->thread().promote();
if (t == 0) {
continue;
}
@@ -3698,7 +3656,7 @@
}
}
if (!found) {
- Mutex::Autolock _l(t->mLock);
+ Mutex::Autolock _l(t->mutex());
// remove all effects from the chain
while (ec->numberOfEffects()) {
sp<IAfEffectModule> effect = ec->getEffectModule(0);
@@ -3715,7 +3673,7 @@
}
// dumpToThreadLog_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::dumpToThreadLog_l(const sp<ThreadBase> &thread)
+void AudioFlinger::dumpToThreadLog_l(const sp<IAfThreadBase> &thread)
{
constexpr int THREAD_DUMP_TIMEOUT_MS = 2;
audio_utils::FdToString fdToString("- ", THREAD_DUMP_TIMEOUT_MS);
@@ -3727,9 +3685,9 @@
}
// checkThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::ThreadBase *AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
+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:
@@ -3746,13 +3704,13 @@
}
// checkOutputThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::ThreadBase> AudioFlinger::checkOutputThread_l(audio_io_handle_t ioHandle) const
+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);
}
@@ -3760,41 +3718,41 @@
}
// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
+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
+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
+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
+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
+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;
}
}
@@ -3802,17 +3760,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;
@@ -3839,14 +3797,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);
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;
}
@@ -3860,7 +3818,7 @@
DeviceTypeSet AudioFlinger::primaryOutputDevice_l() const
{
- PlaybackThread *thread = primaryPlaybackThread_l();
+ IAfPlaybackThread* const thread = primaryPlaybackThread_l();
if (thread == NULL) {
return {};
@@ -3869,12 +3827,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 ||
@@ -3888,9 +3846,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;
}
@@ -3899,12 +3857,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;
@@ -3930,10 +3888,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);
+ [&] { Mutex::Autolock _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);
@@ -3946,7 +3904,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(),
@@ -3966,7 +3924,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(),
@@ -3989,14 +3947,14 @@
patchTrack->setPeerProxy(patchRecord, true /* holdReference */);
patchRecord->setPeerProxy(patchTrack, false /* holdReference */);
}
- track->setTeePatchesToUpdate(std::move(teePatches));
+ track->setTeePatchesToUpdate_l(std::move(teePatches));
}
sp<audioflinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
audio_session_t triggerSession,
audio_session_t listenerSession,
const audioflinger::SyncEventCallback& callBack,
- const wp<RefBase>& cookie)
+ const wp<IAfTrackBase>& cookie)
{
Mutex::Autolock _l(mLock);
@@ -4157,7 +4115,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,
@@ -4182,7 +4140,7 @@
lStatus = BAD_VALUE;
goto Exit;
}
- PlaybackThread *thread = checkPlaybackThread_l(io);
+ IAfPlaybackThread* const thread = checkPlaybackThread_l(io);
if (thread == nullptr) {
ALOGE("%s: invalid output %d specified for AUDIO_SESSION_OUTPUT_STAGE", __func__, io);
lStatus = BAD_VALUE;
@@ -4279,7 +4237,7 @@
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
@@ -4351,7 +4309,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");
@@ -4360,7 +4318,7 @@
}
}
}
- ThreadBase *thread = checkRecordThread_l(io);
+ IAfThreadBase* thread = checkRecordThread_l(io);
if (thread == NULL) {
thread = checkPlaybackThread_l(io);
if (thread == NULL) {
@@ -4376,7 +4334,7 @@
// session and used it instead of creating a new one.
sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l2(thread->mLock);
+ Mutex::Autolock _l2(thread->mutex());
thread->addEffectChain_l(chain);
}
}
@@ -4385,9 +4343,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;
@@ -4450,26 +4408,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);
+ ALOGV("%s() session %d, srcOutput %d, dstOutput %d",
+ __func__, sessionId, srcOutput, dstOutput);
Mutex::Autolock _l(mLock);
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);
+ Mutex::Autolock _dl(dstThread->mutex());
+ Mutex::Autolock _sl(srcThread->mutex());
return moveEffectChain_l(sessionId, srcThread, dstThread);
}
@@ -4480,11 +4438,11 @@
{
Mutex::Autolock _l(mLock);
- sp<ThreadBase> thread = getEffectThread_l(sessionId, effectId);
+ sp<IAfThreadBase> thread = getEffectThread_l(sessionId, effectId);
if (thread == nullptr) {
return;
}
- Mutex::Autolock _sl(thread->mLock);
+ Mutex::Autolock _sl(thread->mutex());
sp<IAfEffectModule> effect = thread->getEffect_l(sessionId, effectId);
thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
}
@@ -4492,8 +4450,7 @@
// 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)
+ IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
{
ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
@@ -4603,17 +4560,16 @@
}
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());
+ 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);
+ Mutex::Autolock _dl(dstThread->mutex());
+ Mutex::Autolock _sl(thread->mutex());
sp<IAfEffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
sp<IAfEffectChain> dstChain;
if (srcChain == 0) {
@@ -4652,7 +4608,7 @@
return status;
}
-bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
+bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l() const
NO_THREAD_SAFETY_ANALYSIS // thread lock for getEffectChain_l.
{
if (mGlobalEffectEnableTime != 0 &&
@@ -4677,8 +4633,8 @@
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);
}
}
@@ -4732,6 +4688,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
+{
+ Mutex::Autolock _l(mLock);
+ return mPatchPanel->listAudioPorts(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;
+ }
+
+ Mutex::Autolock _l(mLock);
+ return mPatchPanel->getAudioPort(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;
+ }
+
+ 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) const
+{
+ Mutex::Autolock _l(mLock);
+ return mPatchPanel->listAudioPatches(num_patches, patches);
+}
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ba6200f..12180f9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -74,6 +74,7 @@
#include <media/DeviceDescriptorBase.h>
#include <media/ExtendedAudioBufferProvider.h>
#include <media/VolumeShaper.h>
+#include <mediautils/BatteryNotifier.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/SharedMemoryAllocator.h>
#include <mediautils/Synchronization.h>
@@ -97,10 +98,12 @@
#include <timing/SynchronizedRecordState.h>
#include <datapath/AudioHwDevice.h>
+#include <datapath/AudioStreamIn.h>
#include <datapath/AudioStreamOut.h>
#include <datapath/SpdifStreamOut.h>
#include <datapath/ThreadMetrics.h>
#include <datapath/TrackMetrics.h>
+#include <datapath/VolumeInterface.h>
#include <fastpath/FastCapture.h>
#include <fastpath/FastMixer.h>
#include <media/nbaio/NBAIO.h>
@@ -118,9 +121,18 @@
#include "android/media/BnEffect.h"
#include "Client.h"
+#include "ResamplerBufferProvider.h"
// include AudioFlinger component interfaces
+#include "IAfPatchPanel.h" // this should be listed before other IAf* interfaces.
#include "IAfEffect.h"
+#include "IAfThread.h"
+#include "IAfTrack.h"
+
+// Classes that depend on IAf* interfaces but are not cross-dependent.
+#include "PatchCommandThread.h"
+#include "DeviceEffectManager.h"
+#include "MelReporter.h"
namespace android {
@@ -134,212 +146,332 @@
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
+struct stream_type_t {
+ float volume = 1.f;
+ bool mute = false;
+};
+
+class AudioFlinger
+ : public AudioFlingerServerAdapter::Delegate // IAudioFlinger client interface
+ , public IAfClientCallback
+ , public IAfDeviceEffectManagerCallback
+ , public IAfMelReporterCallback
+ , public IAfPatchPanelCallback
+ , public IAfThreadCallback
{
friend class sp<AudioFlinger>;
- friend class Client; // removeClient_l();
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;
+
status_t createTrack(const media::CreateTrackRequest& input,
- media::CreateTrackResponse& output) override;
+ media::CreateTrackResponse& output) final;
status_t createRecord(const media::CreateRecordRequest& input,
- media::CreateRecordResponse& output) override;
+ media::CreateRecordResponse& output) final;
- 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;
+ audio_format_t format(audio_io_handle_t output) const final;
+ size_t frameCount(audio_io_handle_t ioHandle) const final;
+ size_t frameCountHAL(audio_io_handle_t ioHandle) const final;
+ uint32_t latency(audio_io_handle_t output) const final;
- 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;
+ status_t setMasterMute(bool muted) final;
+ float masterVolume() const final;
+ bool masterMute() const final;
// 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;
+ status_t getMasterBalance(float* balance) const final;
- 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;
+ status_t setStreamMute(audio_stream_type_t stream, bool muted) final;
- 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;
+ bool streamMute(audio_stream_type_t stream) const final;
- virtual status_t setMode(audio_mode_t mode);
+ status_t setMode(audio_mode_t mode) final;
- virtual status_t setMicMute(bool state);
- virtual bool getMicMute() const;
+ status_t setMicMute(bool state) final;
+ bool getMicMute() const final;
- virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced);
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
- 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;
+ String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const final;
- virtual void registerClient(const sp<media::IAudioFlingerClient>& client);
+ void registerClient(const sp<media::IAudioFlingerClient>& client) final;
+ size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+ audio_channel_mask_t channelMask) const final;
- 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;
- 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;
- 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;
- virtual status_t closeOutput(audio_io_handle_t output);
+ status_t suspendOutput(audio_io_handle_t output) final;
- virtual status_t suspendOutput(audio_io_handle_t output);
+ status_t restoreOutput(audio_io_handle_t output) final;
- virtual status_t restoreOutput(audio_io_handle_t output);
+ status_t openInput(const media::OpenInputRequest& request,
+ media::OpenInputResponse* response) final;
- virtual status_t openInput(const media::OpenInputRequest& request,
- media::OpenInputResponse* response);
+ status_t closeInput(audio_io_handle_t input) final;
- virtual status_t closeInput(audio_io_handle_t input);
+ status_t setVoiceVolume(float volume) final;
- virtual status_t setVoiceVolume(float volume);
+ status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
+ audio_io_handle_t output) const final;
- 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;
// 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;
- 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;
- virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid);
+ void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) final;
- virtual status_t queryNumberEffects(uint32_t *numEffects) const;
+ status_t queryNumberEffects(uint32_t* numEffects) const final;
- virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor) const;
+ status_t queryEffect(uint32_t index, effect_descriptor_t* descriptor) const final;
- 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;
- virtual status_t createEffect(const media::CreateEffectRequest& request,
- media::CreateEffectResponse* response);
+ status_t createEffect(const media::CreateEffectRequest& request,
+ media::CreateEffectResponse* response) final;
- 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;
- void setEffectSuspended(int effectId,
- audio_session_t sessionId,
- bool suspended) override;
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) final;
- virtual audio_module_handle_t loadHwModule(const char *name);
+ audio_module_handle_t loadHwModule(const char* name) final;
- virtual uint32_t getPrimaryOutputSamplingRate();
- virtual size_t getPrimaryOutputFrameCount();
+ uint32_t getPrimaryOutputSamplingRate() const final;
+ size_t getPrimaryOutputFrameCount() const final;
- 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;
/* 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;
/* 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;
/* Release an audio patch */
- virtual status_t releaseAudioPatch(audio_patch_handle_t handle);
+ status_t releaseAudioPatch(audio_patch_handle_t handle) final;
/* 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;
/* Set audio port configuration */
- virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+ status_t setAudioPortConfig(const struct audio_port_config* config) final;
/* 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;
/* 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;
+ status_t audioPolicyReady() final { mAudioPolicyReady.store(true); return NO_ERROR; }
+ status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const final;
- virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
+ status_t setAudioHalPids(const std::vector<pid_t>& pids) final;
- virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
+ status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) final;
- virtual status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos);
+ status_t updateSecondaryOutputs(
+ const TrackSecondaryOutputsMap& trackSecondaryOutputs) final;
- 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;
- virtual int32_t getAAudioMixerBurstCount();
+ int32_t getAAudioMixerBurstCount() const final;
- virtual int32_t getAAudioHardwareBurstMinUsec();
+ int32_t getAAudioHardwareBurstMinUsec() const final;
- 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;
- virtual status_t setSimulateDeviceConnections(bool enabled);
+ status_t setSimulateDeviceConnections(bool enabled) final;
- 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;
- 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;
- virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
+ status_t setBluetoothVariableLatencyEnabled(bool enabled) final;
- virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled);
+ status_t isBluetoothVariableLatencyEnabled(bool* enabled) const final;
- virtual status_t supportsBluetoothVariableLatency(bool* support);
+ status_t supportsBluetoothVariableLatency(bool* support) const final;
- 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;
- status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
+ status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) final;
- virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* config);
+ status_t getAudioPolicyConfig(media::AudioPolicyConfig* config) final;
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;
- // 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
+
+ Mutex& clientMutex() const final { return mClientLock; }
+ void removeClient_l(pid_t pid) final;
+ void removeNotificationClient(pid_t pid) final;
+ status_t moveAuxEffectToIo(
+ int effectId,
+ const sp<IAfPlaybackThread>& dstThread,
+ sp<IAfPlaybackThread>* srcThread) final;
+
+ // ---- 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;
+ status_t removeEffectFromHal(
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final;
+
+ // ---- end of IAfDeviceEffectManagerCallback interface
+
+ // ---- begin IAfMelReporterCallback interface
+
+ // below also used by IAfThreadCallback
+ Mutex& mutex() const final { return mLock; }
+ sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const final REQUIRES(mLock);
+
+ // ---- end of IAfMelReporterCallback interface
+
+ // ---- begin IAfPatchPanelCallback interface
+
+ void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) final;
+ void closeThreadInternal_l(const sp<IAfRecordThread>& thread) final;
+ // return thread associated with primary hardware device, or NULL
+ IAfPlaybackThread* primaryPlaybackThread_l() const final;
+ IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const final;
+ IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const final;
+ IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const final;
+ void lock() const final ACQUIRE(mLock) { mLock.lock(); }
+ void unlock() const final RELEASE(mLock) { mLock.unlock(); }
+ 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;
+ 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;
+ const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+ getAudioHwDevs_l() const final { return mAudioHwDevs; }
+ void updateDownStreamPatches_l(const struct audio_patch* patch,
+ const std::set<audio_io_handle_t>& streams) final;
+ void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final;
+
+ // ---- end of IAfPatchPanelCallback interface
+
+ // ----- begin IAfThreadCallback interface
+
+ bool isNonOffloadableGlobalEffectEnabled_l() const final;
+ bool btNrecIsOff() const final { return mBtNrecIsOff.load(); }
+ float masterVolume_l() const final;
+ bool masterMute_l() const final;
+ float getMasterBalance_l() const;
+ // no range check, AudioFlinger::mLock held
+ bool streamMute_l(audio_stream_type_t stream) const final { 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;
+ 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;
+
+ status_t moveEffectChain_l(audio_session_t sessionId,
+ IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final;
+
+ // 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;
+ 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;
+
+ void ioConfigChanged(audio_io_config_event_t event,
+ const sp<AudioIoDescriptor>& ioDesc,
+ pid_t pid = 0) final;
+ void onNonOffloadableGlobalEffectEnable() final;
+ void onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) final;
+
+ // ---- end of IAfThreadCallback interface
+
+ /* List available audio ports and their attributes */
+ status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const;
+
sp<EffectsFactoryHalInterface> getEffectsFactory();
+public:
status_t openMmapStream(MmapStreamInterface::stream_direction_t direction,
const audio_attributes_t *attr,
audio_config_base_t *config,
@@ -354,16 +486,6 @@
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();
-
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;
@@ -373,50 +495,15 @@
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; }
-
AudioFlinger() ANDROID_API;
- virtual ~AudioFlinger();
+ ~AudioFlinger() override;
// call in any IAudioFlinger method that accesses mPrimaryHardwareDev
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);
@@ -426,6 +513,10 @@
// FCC_2 <= channels <= AudioMixer::MAX_NUM_CHANNELS.
static const bool kEnableExtendedChannels = true;
+public:
+ // Remove this when Oboeservice is updated to obtain handle directly.
+ static inline std::atomic<AudioFlinger*> gAudioFlinger = nullptr;
+
// 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)) {
@@ -478,27 +569,19 @@
// ro.audio.flinger_standbytime_ms or defaults to kDefaultStandbyTimeInNsecs
static nsecs_t mStandbyTimeInNsecs;
- // 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;
-
- // Internal dump utilities.
- static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
-public:
- // TODO(b/288339104) extract to afutils
- static bool dumpTryLock(Mutex& mutex);
private:
+
+ // incremented by 2 when screen state changes, bit 0 == 1 means "off"
+ // AudioFlinger::setParameters() updates with mLock.
+ std::atomic_uint32_t mScreenState{};
+
void dumpPermissionDenial(int fd, const Vector<String16>& args);
void dumpClients(int fd, const Vector<String16>& args);
void dumpInternals(int fd, const Vector<String16>& args);
SimpleLog mThreadLog{16}; // 16 Thread history limit
-public:
- // TODO(b/288339104)
- class ThreadBase;
-private:
- void dumpToThreadLog_l(const sp<ThreadBase> &thread);
+ void dumpToThreadLog_l(const sp<IAfThreadBase>& thread);
// --- Notification Client ---
class NotificationClient : public IBinder::DeathRecipient {
@@ -554,66 +637,6 @@
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();
-
- // TODO(b/288339104) replace these forward declaration classes with interfaces.
-public:
- class RecordThread;
- class PlaybackThread;
- class MixerThread;
- class DirectOutputThread;
- class OffloadThread;
- class DuplicatingThread;
- class AsyncCallbackThread;
- class BitPerfectThread;
-private:
- class Track;
- class RecordTrack;
- class DeviceEffectManager;
- // TODO(b/288339104) these should be separate files
-public:
- class PatchPanel;
- class DeviceEffectManagerCallback;
-private:
- 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 "DeviceEffectManager.h"
-
-#include "MelReporter.h"
-
// 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.
@@ -626,7 +649,7 @@
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.
}
}
@@ -634,67 +657,15 @@
return io;
}
- // 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();
+ IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const;
+ IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const;
- // 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;
+ sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const;
+ std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const;
- 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);
+ 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),
@@ -707,37 +678,24 @@
// 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;
// return the playback thread with smallest HAL buffer size, and prefer fast
- PlaybackThread *fastPlaybackThread_l() const;
+ IAfPlaybackThread* fastPlaybackThread_l() const;
- sp<ThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
+ sp<IAfThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
- ThreadBase *hapticPlaybackThread_l() const;
+ IAfThreadBase* hapticPlaybackThread_l() const;
void updateSecondaryOutputsForTrack_l(
- PlaybackThread::Track* track,
- PlaybackThread* thread,
+ IAfTrack* track,
+ IAfPlaybackThread* thread,
const std::vector<audio_io_handle_t>& secondaryOutputs) const;
-
- void removeClient_l(pid_t pid);
- void removeNotificationClient(pid_t pid);
- bool isNonOffloadableGlobalEffectEnabled_l();
- void onNonOffloadableGlobalEffectEnable();
bool isSessionAcquired_l(audio_session_t audioSession);
// Store an effect chain to mOrphanEffectChains keyed vector.
@@ -751,49 +709,13 @@
// 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<IAfEffectChain> 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.
-public:
-// TODO(b/288339104) suggest better grouping
- bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect);
-private:
+
std::vector< sp<IAfEffectModule> > purgeStaleEffects_l();
void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
- void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
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);
// for mAudioSessionRefs only
struct AudioSessionRef {
@@ -809,10 +731,9 @@
// 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.
-public:
- // TODO(b/288339104) access by getter,
- mutable Mutex mClientLock;
-private:
+
+ mutable Mutex mClientLock;
+
// protected by mClientLock
DefaultKeyedVector< pid_t, wp<Client> > mClients; // see ~Client()
@@ -859,7 +780,7 @@
mutable hardware_call_state mHardwareStatus; // for dump only
- DefaultKeyedVector< audio_io_handle_t, sp<PlaybackThread> > mPlaybackThreads;
+ DefaultKeyedVector<audio_io_handle_t, sp<IAfPlaybackThread>> mPlaybackThreads;
stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
// member variables below are protected by mLock
@@ -868,7 +789,7 @@
float mMasterBalance = 0.f;
// end of variables protected by mLock
- DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> > mRecordThreads;
+ DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads;
// protected by mClientLock
DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
@@ -882,9 +803,6 @@
// protected by mLock
Vector<AudioSessionRef*> mAudioSessionRefs;
- float masterVolume_l() const;
- float getMasterBalance_l() const;
- bool masterMute_l() const;
AudioHwDevice* loadHwModule_l(const char *name);
// sync events awaiting for a session to be created.
@@ -899,17 +817,14 @@
// 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;
-private:
sp<Client> registerPid(pid_t pid); // 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);
+ void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId);
status_t checkStreamType(audio_stream_type_t stream) const;
@@ -918,15 +833,10 @@
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;
@@ -935,16 +845,13 @@
nsecs_t mGlobalEffectEnableTime; // when a global effect was last enabled
- // protected by mLock
- PatchPanel mPatchPanel;
-public:
- // TODO(b/288339104) access by getter.
+ /* const */ sp<IAfPatchPanel> mPatchPanel;
+
sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
-private:
const sp<PatchCommandThread> mPatchCommandThread;
- sp<DeviceEffectManager> mDeviceEffectManager;
- sp<MelReporter> mMelReporter;
+ /* const */ sp<DeviceEffectManager> mDeviceEffectManager; // set onFirstRef
+ /* const */ sp<MelReporter> mMelReporter; // set onFirstRef
bool mSystemReady;
std::atomic_bool mAudioPolicyReady{};
@@ -959,8 +866,10 @@
static inline constexpr const char *mMetricsId = AMEDIAMETRICS_KEY_AUDIO_FLINGER;
+public:
// Keep in sync with java definition in media/java/android/media/AudioRecord.java
static constexpr int32_t kMaxSharedAudioHistoryMs = 5000;
+private:
std::map<media::audio::common::AudioMMapPolicyType,
std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos;
@@ -974,8 +883,6 @@
std::atomic_bool mBluetoothLatencyModesEnabled;
};
-#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);
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
index cb507fe..b2e3cf7 100644
--- a/services/audioflinger/Client.h
+++ b/services/audioflinger/Client.h
@@ -16,26 +16,42 @@
#pragma once
-// TODO(b/288339104) Move to nested namespace
+#include <afutils/AllocatorFactory.h>
+#include <android-base/macros.h> // DISALLOW_COPY_AND_ASSIGN
+#include <utils/Mutex.h>
+#include <utils/RefBase.h> // avoid transitive dependency
+
+// TODO(b/291318727) Move to nested namespace
namespace android {
-class AudioFlinger;
+class IAfPlaybackThread;
+
+class IAfClientCallback : public virtual RefBase {
+public:
+ virtual Mutex& clientMutex() const = 0;
+ virtual void removeClient_l(pid_t pid) = 0;
+ virtual void removeNotificationClient(pid_t pid) = 0;
+ virtual status_t moveAuxEffectToIo(
+ int effectId,
+ const sp<IAfPlaybackThread>& dstThread,
+ sp<IAfPlaybackThread>* srcThread) = 0; // used by indirectly by clients.
+};
class Client : public RefBase {
public:
- Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
+ 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; }
- sp<AudioFlinger> audioFlinger() const { return mAudioFlinger; }
+ const auto& afClientCallback() const { return mAfClientCallback; }
private:
DISALLOW_COPY_AND_ASSIGN(Client);
- const sp<AudioFlinger> mAudioFlinger;
+ const sp<IAfClientCallback> mAfClientCallback;
const pid_t mPid;
AllocatorFactory::ClientAllocator mClientAllocator;
};
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 366a7ab..ebb2428 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,20 +35,39 @@
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(new DeviceEffectManagerCallback(*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);
for (auto& effect : mDeviceEffects) {
- status_t status = effect.second->onCreatePatch(handle, &patch); // TODO(b/288339104) void*
+ status_t status = effect.second->onCreatePatch(handle, patch);
ALOGV("%s Effect onCreatePatch status %d", __func__, status);
ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
}
}
-void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
+void DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
ALOGV("%s", __func__);
Mutex::Autolock _l(mLock);
for (auto& effect : mDeviceEffects) {
@@ -56,12 +76,12 @@
}
// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
-sp<IAfEffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
+sp<IAfEffectHandle> DeviceEffectManager::createEffect_l(
effect_descriptor_t *descriptor,
const AudioDeviceTypeAddr& device,
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,
@@ -83,7 +103,8 @@
effect = iter->second;
} else {
effect = IAfDeviceEffectProxy::create(device, mMyCallback,
- descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
+ descriptor,
+ mAfDeviceEffectManagerCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
notifyFramesProcessed);
}
// create effect handle and connect it to effect module
@@ -93,7 +114,7 @@
if (lStatus == NO_ERROR) {
lStatus = effect->addHandle(handle.get());
if (lStatus == NO_ERROR) {
- lStatus = effect->init(&patches); // TODO(b/288339104) void*
+ lStatus = effect->init(patches);
if (lStatus == NAME_NOT_FOUND) {
lStatus = NO_ERROR;
}
@@ -110,7 +131,7 @@
return handle;
}
-status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
+status_t DeviceEffectManager::checkEffectCompatibility(
const effect_descriptor_t *desc) {
const sp<EffectsFactoryHalInterface> effectsFactory =
audioflinger::EffectConfiguration::getEffectsFactoryHal();
@@ -136,7 +157,7 @@
return NO_ERROR;
}
-status_t AudioFlinger::DeviceEffectManager::createEffectHal(
+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 +170,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(mLock);
if (!locked) {
String8 result("DeviceEffectManager may be deadlocked\n");
write(fd, result.string(), result.size());
@@ -173,15 +194,14 @@
}
}
-
-size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
+size_t DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
{
Mutex::Autolock _l(mLock);
mDeviceEffects.erase(effect->device());
return mDeviceEffects.size();
}
-bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
+bool DeviceEffectManagerCallback::disconnectEffectHandle(
IAfEffectHandle *handle, bool unpinIfLast) {
sp<IAfEffectBase> effectBase = handle->effect().promote();
if (effectBase == nullptr) {
@@ -203,4 +223,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 c589714..6111030 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -15,26 +15,41 @@
** 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"
+
+#include <utils/Mutex.h> // avoid transitive dependency
+
+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) = 0;
+ virtual status_t removeEffectFromHal(
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect) = 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<IAfEffectHandle> createEffect_l(effect_descriptor_t *descriptor,
const AudioDeviceTypeAddr& device,
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,
@@ -45,34 +60,29 @@
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;
+ void onReleaseAudioPatch(audio_patch_handle_t handle) final;
private:
status_t checkEffectCompatibility(const effect_descriptor_t *desc);
Mutex mLock;
- AudioFlinger &mAudioFlinger;
+ const sp<IAfDeviceEffectManagerCallback> mAfDeviceEffectManagerCallback;
const sp<DeviceEffectManagerCallback> mMyCallback;
std::map<AudioDeviceTypeAddr, sp<IAfDeviceEffectProxy>> mDeviceEffects;
};
-public: // TODO(b/288339104) extract inner class.
class DeviceEffectManagerCallback : public EffectCallbackInterface {
public:
explicit DeviceEffectManagerCallback(DeviceEffectManager& manager)
@@ -129,11 +139,9 @@
wp<IAfEffectChain> chain() const override { 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) {
@@ -146,4 +154,5 @@
private:
DeviceEffectManager& mManager;
};
-private:
+
+} // namespace android
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 1f26cb0..7590afd 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,22 +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 "Effects.h"
+#include <algorithm>
// ----------------------------------------------------------------------------
@@ -507,7 +509,7 @@
result.appendFormat("\tEffect ID %d:\n", mId);
- bool locked = AudioFlinger::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mLock);
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
result.append("\t\tCould not lock Fx mutex:\n");
@@ -1621,7 +1623,7 @@
EffectBase::dump(fd, args);
String8 result;
- bool locked = AudioFlinger::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mLock);
result.append("\t\tStatus Engine:\n");
result.appendFormat("\t\t%03d %p\n",
@@ -1637,7 +1639,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");
@@ -1647,7 +1649,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",
@@ -1886,7 +1888,7 @@
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
// Client destructor must run with AudioFlinger client mutex locked
- Mutex::Autolock _l2(mClient->audioFlinger()->mClientLock);
+ Mutex::Autolock _l2(mClient->afClientCallback()->clientMutex());
mClient.clear();
}
}
@@ -2095,7 +2097,7 @@
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(),
@@ -2116,34 +2118,25 @@
/* static */
sp<IAfEffectChain> IAfEffectChain::create(
- const wp<Thread /*ThreadBase*/>& wThread, // TODO(b/288339104) update type
+ const sp<IAfThreadBase>& thread,
audio_session_t sessionId)
{
- // TODO(b/288339104) no weak pointer cast.
- return sp<EffectChain>::make(sp<AudioFlinger::ThreadBase>::cast(wThread.promote()), sessionId);
+ return sp<EffectChain>::make(thread, sessionId);
}
-EffectChain::EffectChain(const wp<AudioFlinger::ThreadBase>& thread,
+EffectChain::EffectChain(const sp<IAfThreadBase>& thread,
audio_session_t sessionId)
: mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
{
- sp<AudioFlinger::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();
}
-EffectChain::~EffectChain()
-{
-}
-
-// getEffectFromDesc_l() must be called with AudioFlinger::ThreadBase::mLock held
+// getEffectFromDesc_l() must be called with IAfThreadBase::mutex() held
sp<IAfEffectModule> EffectChain::getEffectFromDesc_l(
effect_descriptor_t *descriptor) const
{
@@ -2157,7 +2150,7 @@
return 0;
}
-// getEffectFromId_l() must be called with AudioFlinger::ThreadBase::mLock held
+// getEffectFromId_l() must be called with IAfThreadBase::mutex() held
sp<IAfEffectModule> EffectChain::getEffectFromId_l(int id) const
{
size_t size = mEffects.size();
@@ -2171,7 +2164,7 @@
return 0;
}
-// getEffectFromType_l() must be called with AudioFlinger::ThreadBase::mLock held
+// getEffectFromType_l() must be called with IAfThreadBase::mutex() held
sp<IAfEffectModule> EffectChain::getEffectFromType_l(
const effect_uuid_t *type) const
{
@@ -2266,7 +2259,7 @@
}
}
-// createEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+// createEffect_l() must be called with IAfThreadBase::mutex() held
status_t EffectChain::createEffect_l(sp<IAfEffectModule>& effect,
effect_descriptor_t *desc,
int id,
@@ -2285,13 +2278,13 @@
return lStatus;
}
-// addEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+// addEffect_l() must be called with IAfThreadBase::mutex() held
status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
{
Mutex::Autolock _l(mLock);
return addEffect_ll(effect);
}
-// addEffect_l() must be called with AudioFlinger::ThreadBase::mLock and EffectChain::mLock held
+// addEffect_l() must be called with IAfThreadBase::mLock and EffectChain::mutex() held
status_t EffectChain::addEffect_ll(const sp<IAfEffectModule>& effect)
{
effect->setCallback(mEffectCallback);
@@ -2445,7 +2438,7 @@
return idx_insert;
}
-// removeEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+// removeEffect_l() must be called with IAfThreadBase::mutex() held
size_t EffectChain::removeEffect_l(const sp<IAfEffectModule>& effect,
bool release)
{
@@ -2493,7 +2486,7 @@
return mEffects.size();
}
-// setDevices_l() must be called with AudioFlinger::ThreadBase::mLock held
+// setDevices_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
{
size_t size = mEffects.size();
@@ -2502,7 +2495,7 @@
}
}
-// setInputDevice_l() must be called with AudioFlinger::ThreadBase::mLock held
+// setInputDevice_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
{
size_t size = mEffects.size();
@@ -2511,7 +2504,7 @@
}
}
-// setMode_l() must be called with AudioFlinger::ThreadBase::mLock held
+// setMode_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setMode_l(audio_mode_t mode)
{
size_t size = mEffects.size();
@@ -2520,7 +2513,7 @@
}
}
-// setAudioSource_l() must be called with AudioFlinger::ThreadBase::mLock held
+// setAudioSource_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setAudioSource_l(audio_source_t source)
{
size_t size = mEffects.size();
@@ -2536,7 +2529,7 @@
return false;
}
-// setVolume_l() must be called with AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+// setVolume_l() must be called with IAfThreadBase::mLock or EffectChain::mLock held
bool EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
{
uint32_t newLeft = *left;
@@ -2603,7 +2596,7 @@
return hasControl;
}
-// resetVolume_l() must be called with AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mLock held
void EffectChain::resetVolume_l()
{
if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
@@ -2614,7 +2607,7 @@
}
// containsHapticGeneratingEffect_l must be called with
-// AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+// IAfThreadBase::mutex() or EffectChain::mLock held
bool EffectChain::containsHapticGeneratingEffect_l()
{
for (size_t i = 0; i < mEffects.size(); ++i) {
@@ -2653,7 +2646,7 @@
result.appendFormat(" %zu effects for session %d\n", numEffects, mSessionId);
if (numEffects) {
- bool locked = AudioFlinger::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mLock);
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
result.append("\tCould not lock mutex:\n");
@@ -2683,7 +2676,7 @@
}
}
-// must be called with AudioFlinger::ThreadBase::mLock held
+// must be called with IAfThreadBase::mutex() held
void EffectChain::setEffectSuspended_l(
const effect_uuid_t *type, bool suspend)
{
@@ -2739,7 +2732,7 @@
}
}
-// must be called with AudioFlinger::ThreadBase::mLock held
+// must be called with IAfThreadBase::mutex() held
void EffectChain::setEffectSuspendedAll_l(bool suspend)
{
sp<SuspendedEffectDesc> desc;
@@ -2895,7 +2888,7 @@
return false;
}
-void EffectChain::setThread(const sp<AudioFlinger::ThreadBase>& thread)
+void EffectChain::setThread(const sp<IAfThreadBase>& thread)
{
Mutex::Autolock _l(mLock);
mEffectCallback->setThread(thread);
@@ -2962,7 +2955,7 @@
}
// isCompatibleWithThread_l() must be called with thread->mLock held
-bool EffectChain::isCompatibleWithThread_l(const sp<AudioFlinger::ThreadBase>& thread) const
+bool EffectChain::isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mEffects.size(); i++) {
@@ -2989,18 +2982,18 @@
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 EffectChain::EffectCallback::allocateHalBuffer(
size_t size, sp<EffectBufferHalInterface>* buffer) {
- return mAudioFlinger.mEffectsFactoryHal->allocateBuffer(size, buffer);
+ return mAfThreadCallback->getEffectsFactoryHal()->allocateBuffer(size, buffer);
}
status_t EffectChain::EffectCallback::addEffectToHal(
const sp<EffectHalInterface>& effect) {
status_t result = NO_INIT;
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return result;
}
@@ -3016,7 +3009,7 @@
status_t EffectChain::EffectCallback::removeEffectFromHal(
const sp<EffectHalInterface>& effect) {
status_t result = NO_INIT;
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return result;
}
@@ -3030,7 +3023,7 @@
}
audio_io_handle_t EffectChain::EffectCallback::io() const {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_IO_HANDLE_NONE;
}
@@ -3038,7 +3031,7 @@
}
bool EffectChain::EffectCallback::isOutput() const {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return true;
}
@@ -3046,19 +3039,19 @@
}
bool EffectChain::EffectCallback::isOffload() const {
- return mThreadType == AudioFlinger::ThreadBase::OFFLOAD;
+ return mThreadType == IAfThreadBase::OFFLOAD;
}
bool EffectChain::EffectCallback::isOffloadOrDirect() const {
- return mThreadType == AudioFlinger::ThreadBase::OFFLOAD
- || mThreadType == AudioFlinger::ThreadBase::DIRECT;
+ return mThreadType == IAfThreadBase::OFFLOAD
+ || mThreadType == IAfThreadBase::DIRECT;
}
bool EffectChain::EffectCallback::isOffloadOrMmap() const {
switch (mThreadType) {
- case AudioFlinger::ThreadBase::OFFLOAD:
- case AudioFlinger::ThreadBase::MMAP_PLAYBACK:
- case AudioFlinger::ThreadBase::MMAP_CAPTURE:
+ case IAfThreadBase::OFFLOAD:
+ case IAfThreadBase::MMAP_PLAYBACK:
+ case IAfThreadBase::MMAP_CAPTURE:
return true;
default:
return false;
@@ -3066,11 +3059,11 @@
}
bool EffectChain::EffectCallback::isSpatializer() const {
- return mThreadType == AudioFlinger::ThreadBase::SPATIALIZER;
+ return mThreadType == IAfThreadBase::SPATIALIZER;
}
uint32_t EffectChain::EffectCallback::sampleRate() const {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return 0;
}
@@ -3078,7 +3071,7 @@
}
audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
}
@@ -3087,7 +3080,7 @@
return AUDIO_CHANNEL_NONE;
}
- if (mThreadType == AudioFlinger::ThreadBase::SPATIALIZER) {
+ if (mThreadType == IAfThreadBase::SPATIALIZER) {
if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
if (c->isFirstEffect(id)) {
return t->mixerChannelMask();
@@ -3096,7 +3089,7 @@
}
} else if (!audio_is_global_session(c->sessionId())) {
if ((t->hasAudioSession_l(c->sessionId())
- & AudioFlinger::ThreadBase::SPATIALIZED_SESSION) != 0) {
+ & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
return t->mixerChannelMask();
} else {
return t->channelMask();
@@ -3114,7 +3107,7 @@
}
audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
}
@@ -3123,10 +3116,10 @@
return AUDIO_CHANNEL_NONE;
}
- if (mThreadType == AudioFlinger::ThreadBase::SPATIALIZER) {
+ if (mThreadType == IAfThreadBase::SPATIALIZER) {
if (!audio_is_global_session(c->sessionId())) {
if ((t->hasAudioSession_l(c->sessionId())
- & AudioFlinger::ThreadBase::SPATIALIZED_SESSION) != 0) {
+ & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
return t->mixerChannelMask();
} else {
return t->channelMask();
@@ -3144,7 +3137,7 @@
}
audio_channel_mask_t EffectChain::EffectCallback::hapticChannelMask() const {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
}
@@ -3152,7 +3145,7 @@
}
size_t EffectChain::EffectCallback::frameCount() const {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return 0;
}
@@ -3162,7 +3155,7 @@
uint32_t EffectChain::EffectCallback::latency() const
NO_THREAD_SAFETY_ANALYSIS // latency_l() access
{
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return 0;
}
@@ -3173,7 +3166,7 @@
void EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
NO_THREAD_SAFETY_ANALYSIS // setVolumeForOutput_l() access
{
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return;
}
@@ -3182,7 +3175,7 @@
void EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return;
}
@@ -3197,7 +3190,7 @@
}
void EffectChain::EffectCallback::onEffectEnable(const sp<IAfEffectBase>& effect) {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return;
}
@@ -3208,7 +3201,7 @@
void EffectChain::EffectCallback::onEffectDisable(const sp<IAfEffectBase>& effect) {
checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return;
}
@@ -3217,7 +3210,7 @@
bool EffectChain::EffectCallback::disconnectEffectHandle(IAfEffectHandle *handle,
bool unpinIfLast) {
- sp<AudioFlinger::ThreadBase> t = thread().promote();
+ const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return false;
}
@@ -3257,11 +3250,11 @@
/* static */
sp<IAfDeviceEffectProxy> IAfDeviceEffectProxy::create(
const AudioDeviceTypeAddr& device,
- const sp</* DeviceEffectManagerCallback */ RefBase>& callback, // TODO(b/288339104) type
+ const sp<DeviceEffectManagerCallback>& callback,
effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
{
return sp<DeviceEffectProxy>::make(device,
- sp<AudioFlinger::DeviceEffectManagerCallback>::cast(callback),
+ callback,
desc, id, notifyFramesProcessed);
}
@@ -3287,7 +3280,7 @@
}
status_t DeviceEffectProxy::init(
- const std::map <audio_patch_handle_t, AudioFlinger::PatchPanel::Patch>& patches) {
+ 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
@@ -3310,7 +3303,7 @@
}
status_t DeviceEffectProxy::onCreatePatch(
- audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch) {
+ audio_patch_handle_t patchHandle, const IAfPatchPanel::Patch& patch) {
status_t status = NAME_NOT_FOUND;
sp<IAfEffectHandle> handle;
// only consider source[0] as this is the only "true" source of a patch
@@ -3330,7 +3323,7 @@
return status;
}
-status_t DeviceEffectProxy::checkPort(const AudioFlinger::PatchPanel::Patch& patch,
+status_t DeviceEffectProxy::checkPort(const IAfPatchPanel::Patch& patch,
const struct audio_port_config *port, sp<IAfEffectHandle> *handle) {
ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
@@ -3376,7 +3369,7 @@
mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
}
} else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
- sp <AudioFlinger::ThreadBase> thread;
+ sp<IAfThreadBase> thread;
if (audio_port_config_has_input_direction(port)) {
if (patch.isSoftware()) {
thread = patch.mRecord.thread();
@@ -3489,7 +3482,7 @@
const Vector<String16> args;
EffectBase::dump(fd, args);
- const bool locked = AudioFlinger::dumpTryLock(mProxyLock);
+ const bool locked = afutils::dumpTryLock(mProxyLock);
if (!locked) {
String8 result("DeviceEffectProxy may be deadlocked\n");
write(fd, result.string(), result.size());
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 07790be..82ad486 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -15,6 +15,17 @@
** limitations under the License.
*/
+#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
@@ -382,8 +393,7 @@
// it also provide it's own input buffer used by the track as accumulation buffer.
class EffectChain : public IAfEffectChain {
public:
- EffectChain(const wp<AudioFlinger::ThreadBase>& wThread, audio_session_t sessionId);
- ~EffectChain() override;
+ EffectChain(const sp<IAfThreadBase>& thread, audio_session_t sessionId);
void process_l() final;
@@ -479,12 +489,7 @@
bool isBitPerfectCompatible() const final;
// isCompatibleWithThread_l() must be called with thread->mLock held
- // TODO(b/288339104) type
- bool isCompatibleWithThread_l(const sp<Thread>& thread) const final {
- return isCompatibleWithThread_l(sp<AudioFlinger::ThreadBase>::cast(thread));
- }
-
- bool isCompatibleWithThread_l(const sp<AudioFlinger::ThreadBase>& thread) const;
+ bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final;
bool containsHapticGeneratingEffect_l() final;
@@ -492,8 +497,7 @@
sp<EffectCallbackInterface> effectCallback() const final { return mEffectCallback; }
- // TODO(b/288339104) type
- wp<Thread> thread() const final { return mEffectCallback->thread(); }
+ wp<IAfThreadBase> thread() const final { return mEffectCallback->thread(); }
bool isFirstEffect(int id) const final {
return !mEffects.isEmpty() && id == mEffects[0]->id();
@@ -507,12 +511,7 @@
return mEffects[index];
}
- // TODO(b/288339104) type
- void setThread(const sp<Thread>& thread) final {
- setThread(sp<AudioFlinger::ThreadBase>::cast(thread));
- }
-
- void setThread(const sp<AudioFlinger::ThreadBase>& thread);
+ void setThread(const sp<IAfThreadBase>& thread) final;
private:
@@ -527,16 +526,11 @@
// 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<AudioFlinger::ThreadBase>& thread)
+ const sp<IAfThreadBase>& thread) // we take a sp<> but store a wp<>.
: mChain(owner)
- , mThread(thread)
- , mAudioFlinger(*AudioFlinger::gAudioFlinger) {
- sp<AudioFlinger::ThreadBase> base = thread.promote();
- if (base != nullptr) {
- mThreadType = base->type();
- } else {
- mThreadType = AudioFlinger::ThreadBase::MIXER; // assure a consistent value.
- }
+ , mThread(thread) {
+ mThreadType = thread->type();
+ mAfThreadCallback = thread->afThreadCallback();
}
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -577,21 +571,22 @@
wp<IAfEffectChain> chain() const final { return mChain; }
bool isAudioPolicyReady() const final {
- return mAudioFlinger.isAudioPolicyReady();
+ return mAfThreadCallback->isAudioPolicyReady();
}
- wp<AudioFlinger::ThreadBase> thread() const { return mThread.load(); }
+ wp<IAfThreadBase> thread() const { return mThread.load(); }
- void setThread(const sp<AudioFlinger::ThreadBase>& thread) {
+ void setThread(const sp<IAfThreadBase>& thread) {
mThread = thread;
mThreadType = thread->type();
+ mAfThreadCallback = thread->afThreadCallback();
}
private:
const wp<IAfEffectChain> mChain;
- mediautils::atomic_wp<AudioFlinger::ThreadBase> mThread;
- AudioFlinger &mAudioFlinger; // implementation detail: outer instance always exists.
- AudioFlinger::ThreadBase::type_t mThreadType;
+ mediautils::atomic_wp<IAfThreadBase> mThread;
+ sp<IAfThreadCallback> mAfThreadCallback;
+ IAfThreadBase::type_t mThreadType;
};
DISALLOW_COPY_AND_ASSIGN(EffectChain);
@@ -657,7 +652,7 @@
class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase {
public:
DeviceEffectProxy(const AudioDeviceTypeAddr& device,
- const sp<AudioFlinger::DeviceEffectManagerCallback>& callback,
+ const sp<DeviceEffectManagerCallback>& callback,
effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
: EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false),
mDevice(device), mManagerCallback(callback),
@@ -667,22 +662,11 @@
status_t setEnabled(bool enabled, bool fromHandle) final;
sp<IAfDeviceEffectProxy> asDeviceEffectProxy() final { return this; }
- // TODO(b/288339104) type
- status_t init(const /* std::map<audio_patch_handle_t,
- PatchPanel::Patch>& */ void * patches) final {
- return init(*reinterpret_cast<const std::map<
- audio_patch_handle_t, AudioFlinger::PatchPanel::Patch> *>(patches));
- }
- // TODO(b/288339104) type
- status_t onCreatePatch(audio_patch_handle_t patchHandle,
- /* const PatchPanel::Patch& */ const void * patch) final {
- return onCreatePatch(patchHandle,
- *reinterpret_cast<const AudioFlinger::PatchPanel::Patch *>(patch));
- }
+ status_t init(const std::map<audio_patch_handle_t,
+ IAfPatchPanel::Patch>& patches) final;
- status_t init(const std::map<audio_patch_handle_t, AudioFlinger::PatchPanel::Patch>& patches);
- status_t onCreatePatch(
- audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch);
+ status_t onCreatePatch(audio_patch_handle_t patchHandle,
+ const IAfPatchPanel::Patch& patch) final;
void onReleasePatch(audio_patch_handle_t patchHandle) final;
@@ -706,7 +690,7 @@
// Note: ctors taking a weak pointer to their owner must not promote it
// during construction (but may keep a reference for later promotion).
ProxyCallback(const wp<DeviceEffectProxy>& owner,
- const sp<AudioFlinger::DeviceEffectManagerCallback>& callback)
+ const sp<DeviceEffectManagerCallback>& callback)
: mProxy(owner), mManagerCallback(callback) {}
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -757,14 +741,14 @@
private:
const wp<DeviceEffectProxy> mProxy;
- const sp<AudioFlinger::DeviceEffectManagerCallback> mManagerCallback;
+ const sp<DeviceEffectManagerCallback> mManagerCallback;
};
- status_t checkPort(const AudioFlinger::PatchPanel::Patch& patch,
+ status_t checkPort(const IAfPatchPanel::Patch& patch,
const struct audio_port_config *port, sp<IAfEffectHandle> *handle);
const AudioDeviceTypeAddr mDevice;
- const sp<AudioFlinger::DeviceEffectManagerCallback> mManagerCallback;
+ const sp<DeviceEffectManagerCallback> mManagerCallback;
const sp<ProxyCallback> mMyCallback;
mutable Mutex mProxyLock;
diff --git a/services/audioflinger/IAfEffect.h b/services/audioflinger/IAfEffect.h
index 75112ca..7393448 100644
--- a/services/audioflinger/IAfEffect.h
+++ b/services/audioflinger/IAfEffect.h
@@ -16,13 +16,28 @@
#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 <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.
@@ -190,7 +205,7 @@
// Most of these methods are accessed from AudioFlinger::Thread
public:
static sp<IAfEffectChain> create(
- const wp<Thread /*ThreadBase*/>& wThread, // TODO(b/288339104) type
+ const sp<IAfThreadBase>& thread,
audio_session_t sessionId);
// special key used for an entry in mSuspendedEffects keyed vector
@@ -279,8 +294,7 @@
virtual bool isBitPerfectCompatible() const = 0;
// isCompatibleWithThread_l() must be called with thread->mLock held
- // TODO(b/288339104) type
- virtual bool isCompatibleWithThread_l(const sp<Thread>& thread) const = 0;
+ virtual bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const = 0;
virtual bool containsHapticGeneratingEffect_l() = 0;
@@ -288,8 +302,8 @@
virtual sp<EffectCallbackInterface> effectCallback() const = 0;
- virtual wp<Thread> thread() const = 0; // TODO(b/288339104) type
- virtual void setThread(const sp<Thread>& thread) = 0; // TODO(b/288339104) type
+ virtual wp<IAfThreadBase> thread() const = 0;
+ virtual void setThread(const sp<IAfThreadBase>& thread) = 0;
virtual bool isFirstEffect(int id) const = 0;
@@ -335,22 +349,21 @@
class IAfDeviceEffectProxy : public virtual IAfEffectBase {
public:
- // TODO(b/288339104) type
static sp<IAfDeviceEffectProxy> create(const AudioDeviceTypeAddr& device,
- const sp</* DeviceEffectManagerCallback */ RefBase>& callback,
+ const sp<DeviceEffectManagerCallback>& callback,
effect_descriptor_t *desc, int id, bool notifyFramesProcessed);
virtual status_t init(
- const /* std::map<audio_patch_handle_t,
- PatchPanel::Patch>& */ void * patches) = 0; // TODO(b/288339104) type
+ 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 PatchPanel::Patch& */ const void * patch) = 0;
+ 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/288339104) naming?
+ virtual void dump2(int fd, int spaces) const = 0; // TODO(b/291319101) naming?
private:
// used by DeviceEffectProxy
@@ -364,4 +377,4 @@
virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
};
-} // namespace android
+} // namespace android
diff --git a/services/audioflinger/IAfPatchPanel.h b/services/audioflinger/IAfPatchPanel.h
new file mode 100644
index 0000000..20e092d
--- /dev/null
+++ b/services/audioflinger/IAfPatchPanel.h
@@ -0,0 +1,293 @@
+/*
+ * 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;
+
+ // 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 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) = 0;
+ virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) = 0;
+ virtual IAfPlaybackThread* primaryPlaybackThread_l() const = 0;
+ virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const = 0;
+ virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const = 0;
+ virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const = 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) = 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) = 0;
+ virtual void lock() const = 0;
+ virtual void unlock() const = 0;
+ virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+ getAudioHwDevs_l() const = 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) = 0;
+ virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) = 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(const sp<IAfPatchPanel>& panel) {
+ if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
+ panel->releaseAudioPatch(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(const sp<IAfPatchPanel>& panel);
+ void clearConnections(const sp<IAfPatchPanel>& panel);
+ 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(unsigned int* num_ports, struct audio_port* ports) = 0;
+
+ /* Get supported attributes for a given audio port */
+ virtual status_t getAudioPort(struct audio_port_v7* port) = 0;
+
+ /* Create a patch between several source and sink ports */
+ virtual status_t createAudioPatch(
+ const struct audio_patch* patch,
+ audio_patch_handle_t* handle,
+ bool endpointPatch = false) = 0;
+
+ /* Release a patch */
+ virtual status_t releaseAudioPatch(audio_patch_handle_t handle) = 0;
+
+ /* List connected audio devices and they attributes */
+ virtual status_t listAudioPatches(unsigned int* num_patches, struct audio_patch* patches) = 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;
+
+ // Must be called under AudioFlinger::mLock
+
+ virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const = 0;
+
+ virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const = 0;
+
+ virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const = 0;
+};
+
+} // namespace android
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
new file mode 100644
index 0000000..235378b
--- /dev/null
+++ b/services/audioflinger/IAfThread.h
@@ -0,0 +1,592 @@
+/*
+ * 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/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/Mutex.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;
+
+// Note this is exposed through IAfThreadBase::afThreadCallback()
+// and hence may be used by the Effect / Track framework.
+class IAfThreadCallback : public virtual RefBase {
+public:
+ virtual Mutex& mutex() const = 0;
+ virtual bool isNonOffloadableGlobalEffectEnabled_l() const = 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 = 0;
+ virtual bool masterMute_l() const = 0;
+ virtual float getMasterBalance_l() const = 0;
+ virtual bool streamMute_l(audio_stream_type_t stream) const = 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 = 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) = 0;
+ virtual status_t moveEffectChain_l(audio_session_t sessionId,
+ IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) = 0;
+
+ virtual void requestLogMerge() = 0;
+ virtual sp<NBLog::Writer> newWriter_l(size_t size, const char *name) = 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) = 0;
+
+ virtual void ioConfigChanged(audio_io_config_event_t event,
+ const sp<AudioIoDescriptor>& ioDesc,
+ pid_t pid = 0) = 0;
+ virtual void onNonOffloadableGlobalEffectEnable() = 0;
+ virtual void onSupportedLatencyModesChanged(
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) = 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);
+ 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) = 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_l(const sp<IAfEffectModule>& effect) = 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 Mutex& mutex() const = 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) = 0;
+ virtual void stopMelComputation_l() = 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) = 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) = 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..2302e13
--- /dev/null
+++ b/services/audioflinger/IAfTrack.h
@@ -0,0 +1,607 @@
+/*
+ * 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;
+
+ /**
+ * Called when a track moves to active state to record its contribution to battery usage.
+ * Track state transitions should eventually be handled within the track class.
+ */
+ virtual void beginBatteryAttribution() = 0;
+
+ /**
+ * Called when a track moves out of the active state to record its contribution
+ * to battery usage.
+ */
+ virtual void endBatteryAttribution() = 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_l() = 0;
+
+ // Argument teePatchesToUpdate is by value, use std::move to optimize.
+ virtual void setTeePatchesToUpdate_l(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..64a5843 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,7 +63,7 @@
return true;
}
-void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
+void MelReporter::activateInternalSoundDoseComputation() {
{
std::lock_guard _l(mLock);
if (!mUseHalSoundDoseInterface) {
@@ -76,42 +76,20 @@
mSoundDoseManager->setHalSoundDoseInterface(nullptr);
}
-void AudioFlinger::MelReporter::onFirstRef() {
- mAudioFlinger.mPatchCommandThread->addListener(this);
+void MelReporter::onFirstRef() {
+ mAfMelReporterCallback->getPatchCommandThread()->addListener(this);
+
+ mSoundDoseManager = sp<SoundDoseManager>::make(sp<IMelReporterCallback>::fromExisting(this));
}
-bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
- if (!mSoundDoseManager->isCsdEnabled()) {
- ALOGV("%s csd is disabled", __func__);
- return false;
- }
- if (mSoundDoseManager->forceComputeCsdOnAllDevices()) {
- return true;
- }
-
- switch (device) {
- case AUDIO_DEVICE_OUT_WIRED_HEADSET:
- case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
- // TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets
- // case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
- case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
- case AUDIO_DEVICE_OUT_USB_HEADSET:
- case AUDIO_DEVICE_OUT_BLE_HEADSET:
- case AUDIO_DEVICE_OUT_BLE_BROADCAST:
- return true;
- default:
- return false;
- }
-}
-
-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 _laf(mAfMelReporterCallback->mutex());
std::lock_guard _l(mLock);
auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
if (!activeMelPatchId) {
@@ -127,21 +105,22 @@
}
auto activeMelPatchIt = mActiveMelPatches.find(activeMelPatchId.value());
- if (activeMelPatchIt != mActiveMelPatches.end()
- && shouldActivateCsd != activeMelPatchIt->second.csdActive) {
- if (activeMelPatchIt->second.csdActive) {
- ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle);
- stopMelComputationForPatch_l(activeMelPatchIt->second);
- } else {
- ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle);
- startMelComputationForActivePatch_l(activeMelPatchIt->second);
+ if (activeMelPatchIt != mActiveMelPatches.end()) {
+ if (shouldActivateCsd != activeMelPatchIt->second.csdActive) {
+ if (activeMelPatchIt->second.csdActive) {
+ ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle);
+ stopMelComputationForPatch_l(activeMelPatchIt->second);
+ } else {
+ ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle);
+ startMelComputationForActivePatch_l(activeMelPatchIt->second);
+ }
+ activeMelPatchIt->second.csdActive = shouldActivateCsd;
}
- activeMelPatchIt->second.csdActive = shouldActivateCsd;
}
}
-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;
@@ -159,53 +138,81 @@
audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
ActiveMelPatch newPatch;
newPatch.streamHandle = streamHandle;
+ newPatch.csdActive = false;
for (size_t i = 0; i < patch.mAudioPatch.num_sinks; ++i) {
- if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE
- && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
+ if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE &&
+ mSoundDoseManager->shouldComputeCsdForDeviceType(
+ patch.mAudioPatch.sinks[i].ext.device.type)) {
audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
- newPatch.deviceHandles.push_back(deviceId);
+ bool shouldComputeCsd = mSoundDoseManager->shouldComputeCsdForDeviceWithAddress(
+ patch.mAudioPatch.sinks[i].ext.device.type,
+ patch.mAudioPatch.sinks[i].ext.device.address);
+ newPatch.deviceStates.push_back({deviceId, shouldComputeCsd});
+ newPatch.csdActive |= shouldComputeCsd;
AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
patch.mAudioPatch.sinks[i].ext.device.address};
mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
}
}
- if (!newPatch.deviceHandles.empty()) {
- std::lock_guard _afl(mAudioFlinger.mLock);
+ if (!newPatch.deviceStates.empty() && newPatch.csdActive) {
+ std::lock_guard _afl(mAfMelReporterCallback->mutex());
std::lock_guard _l(mLock);
ALOGV("%s add patch handle %d to active devices", __func__, handle);
startMelComputationForActivePatch_l(newPatch);
- newPatch.csdActive = true;
mActiveMelPatches[handle] = newPatch;
}
}
-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;
}
- for (const auto& deviceHandle : patch.deviceHandles) {
- ++mActiveDevices[deviceHandle];
- ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
- patch.streamHandle, deviceHandle, mActiveDevices[deviceHandle]);
+ for (const auto& device : patch.deviceStates) {
+ if (device.second) {
+ ++mActiveDevices[device.first];
+ ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
+ patch.streamHandle, device.first, mActiveDevices[device.first]);
- if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
- outputThread->startMelComputation_l(mSoundDoseManager->getOrCreateProcessorForDevice(
- deviceHandle,
- patch.streamHandle,
- outputThread->mSampleRate,
- outputThread->mChannelCount,
- outputThread->mFormat));
+ if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
+ outputThread->startMelComputation_l(
+ mSoundDoseManager->getOrCreateProcessorForDevice(
+ device.first,
+ patch.streamHandle,
+ outputThread->sampleRate(),
+ outputThread->channelCount(),
+ outputThread->format()));
+ }
}
}
}
-void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
+void MelReporter::startMelComputationForDeviceId(audio_port_handle_t deviceId) {
+ ALOGV("%s(%d)", __func__, deviceId);
+ std::lock_guard _laf(mAfMelReporterCallback->mutex());
+ std::lock_guard _l(mLock);
+
+ for (auto& activeMelPatch : mActiveMelPatches) {
+ bool csdActive = false;
+ for (auto& device: activeMelPatch.second.deviceStates) {
+ if (device.first == deviceId && !device.second) {
+ device.second = true;
+ }
+ csdActive |= device.second;
+ }
+ if (csdActive && !activeMelPatch.second.csdActive) {
+ activeMelPatch.second.csdActive = csdActive;
+ startMelComputationForActivePatch_l(activeMelPatch.second);
+ }
+ }
+}
+
+void MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return;
@@ -226,53 +233,70 @@
mActiveMelPatches.erase(patchIt);
}
- std::lock_guard _afl(mAudioFlinger.mLock);
+ std::lock_guard _afl(mAfMelReporterCallback->mutex());
std::lock_guard _l(mLock);
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);
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) {
- // no need to stop CSD inactive patches
- 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) {
- if (mActiveDevices[deviceId] > 0) {
- --mActiveDevices[deviceId];
- if (mActiveDevices[deviceId] == 0) {
+ for (const auto& device : patch.deviceStates) {
+ if (mActiveDevices[device.first] > 0) {
+ --mActiveDevices[device.first];
+ if (mActiveDevices[device.first] == 0) {
// no stream is using deviceId anymore
- ALOGI("%s removing device %d from active CSD devices", __func__, deviceId);
- mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
+ ALOGI("%s removing device %d from active CSD devices", __func__, device.first);
+ mSoundDoseManager->clearMapDeviceIdEntries(device.first);
}
}
}
+ mSoundDoseManager->removeStreamProcessor(patch.streamHandle);
if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
outputThread->stopMelComputation_l();
}
}
+void MelReporter::stopMelComputationForDeviceId(audio_port_handle_t deviceId) {
+ ALOGV("%s(%d)", __func__, deviceId);
+ std::lock_guard _laf(mAfMelReporterCallback->mutex());
+ std::lock_guard _l(mLock);
-std::optional<audio_patch_handle_t> AudioFlinger::MelReporter::activePatchStreamHandle_l(
+ for (auto& activeMelPatch : mActiveMelPatches) {
+ bool csdActive = false;
+ for (auto& device: activeMelPatch.second.deviceStates) {
+ if (device.first == deviceId && device.second) {
+ device.second = false;
+ }
+ csdActive |= device.second;
+ }
+
+ if (!csdActive && activeMelPatch.second.csdActive) {
+ activeMelPatch.second.csdActive = csdActive;
+ stopMelComputationForPatch_l(activeMelPatch.second);
+ }
+ }
+
+}
+
+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,11 +306,11 @@
return std::nullopt;
}
-bool AudioFlinger::MelReporter::useHalSoundDoseInterface_l() {
+bool MelReporter::useHalSoundDoseInterface_l() {
return !mSoundDoseManager->forceUseFrameworkMel() & mUseHalSoundDoseInterface;
}
-std::string AudioFlinger::MelReporter::dump() {
+std::string MelReporter::dump() {
std::lock_guard _l(mLock);
std::string output("\nSound Dose:\n");
output.append(mSoundDoseManager->dump());
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index 2bc33f2..78c6c0c 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -15,25 +15,36 @@
** 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 "PatchCommandThread.h"
+
+#include <sounddose/SoundDoseManager.h>
#include <mutex>
-#include <sounddose/SoundDoseManager.h>
#include <unordered_map>
+namespace android {
+
constexpr static int kMaxTimestampDeltaInSec = 120;
+class IAfMelReporterCallback : public virtual RefBase {
+public:
+ virtual Mutex& mutex() const = 0;
+ virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+ virtual sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const = 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 {
+class MelReporter : public PatchCommandThread::PatchCommandListener,
+ public IMelReporterCallback {
public:
- explicit MelReporter(AudioFlinger& audioFlinger)
- : mAudioFlinger(audioFlinger),
- mSoundDoseManager(sp<SoundDoseManager>::make()) {}
+ explicit MelReporter(const sp<IAfMelReporterCallback>& afMelReporterCallback)
+ : mAfMelReporterCallback(afMelReporterCallback) {}
void onFirstRef() override;
@@ -65,10 +76,14 @@
std::string dump();
+ // IMelReporterCallback methods
+ void stopMelComputationForDeviceId(audio_port_handle_t deviceId) override;
+ void startMelComputationForDeviceId(audio_port_handle_t deviceId) override;
+
// 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;
+ void onReleaseAudioPatch(audio_patch_handle_t handle) final;
/**
* The new metadata can determine whether we should compute MEL for the given thread.
@@ -80,13 +95,15 @@
private:
struct ActiveMelPatch {
audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
- std::vector<audio_port_handle_t> deviceHandles;
+ /**
+ * Stores device ids and whether they are compatible for CSD calculation.
+ * The boolean value can change since BT audio device types are user-configurable
+ * to headphones/headsets or other device types.
+ */
+ std::vector<std::pair<audio_port_handle_t,bool>> deviceStates;
bool csdActive;
};
- /** Returns true if we should compute MEL for the given device. */
- bool shouldComputeMelForDeviceType(audio_devices_t device);
-
void stopInternalMelComputation();
/** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
@@ -100,7 +117,7 @@
bool useHalSoundDoseInterface_l() REQUIRES(mLock);
- AudioFlinger& mAudioFlinger; // does not own the object
+ const sp<IAfMelReporterCallback> mAfMelReporterCallback;
sp<SoundDoseManager> mSoundDoseManager;
@@ -109,9 +126,9 @@
* Locking order AudioFlinger::mLock -> PatchCommandThread::mLock -> MelReporter::mLock.
*/
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;
+ std::unordered_map<audio_patch_handle_t, ActiveMelPatch> mActiveMelPatches GUARDED_BY(mLock);
+ std::unordered_map<audio_port_handle_t, int> mActiveDevices GUARDED_BY(mLock);
+ bool mUseHalSoundDoseInterface GUARDED_BY(mLock) = 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..c3259f1 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);
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);
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,12 +53,12 @@
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()
+bool PatchCommandThread::threadLoop()
NO_THREAD_SAFETY_ANALYSIS // bug in clang compiler.
{
std::unique_lock _l(mLock);
@@ -119,14 +121,14 @@
return false;
}
-void AudioFlinger::PatchCommandThread::sendCommand(const sp<Command>& command) {
+void PatchCommandThread::sendCommand(const sp<Command>& command) {
std::lock_guard _l(mLock);
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,14 +138,14 @@
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);
diff --git a/services/audioflinger/PatchCommandThread.h b/services/audioflinger/PatchCommandThread.h
index b52e0a9..a312fb7 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,7 +43,7 @@
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;
};
@@ -44,7 +52,7 @@
void addListener(const sp<PatchCommandListener>& listener);
- void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
+ void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch);
void releaseAudioPatch(audio_patch_handle_t handle);
// Thread virtuals
@@ -54,7 +62,7 @@
void exit();
void createAudioPatchCommand(audio_patch_handle_t handle,
- const PatchPanel::Patch& patch);
+ const IAfPatchPanel::Patch& patch);
void releaseAudioPatchCommand(audio_patch_handle_t handle);
private:
@@ -75,11 +83,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 {
@@ -100,3 +108,5 @@
std::mutex mListenerLock;
std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(mListenerLock);
};
+
+} // namespace android
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index d0feba5..ec96de5 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(unsigned int* /* num_ports */,
struct audio_port *ports __unused)
{
ALOGV(__func__);
@@ -113,7 +91,7 @@
}
/* Get supported attributes for a given audio port */
-status_t AudioFlinger::PatchPanel::getAudioPort(struct audio_port_v7 *port)
+status_t PatchPanel::getAudioPort(struct audio_port_v7* port)
{
if (port->type != AUDIO_PORT_TYPE_DEVICE) {
// Only query the HAL when the port is a device.
@@ -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(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
@@ -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,13 +310,13 @@
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()));
+ newPatch.mRecord.setThread(thread->asIAfRecordThread().get());
status = newPatch.createConnections(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->unlock();
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
- mAudioFlinger.lock();
+ mAfPatchPanelCallback->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->unlock();
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
- mAudioFlinger.lock();
+ mAfPatchPanelCallback->lock();
if (status == NO_ERROR) {
newPatch.setThread(thread);
}
@@ -453,9 +433,10 @@
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);
}
@@ -466,13 +447,13 @@
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(const sp<IAfPatchPanel>& panel)
{
// create patch from source device to record thread input
status_t status = panel->createAudioPatch(
@@ -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,7 +617,7 @@
return status;
}
-void AudioFlinger::PatchPanel::Patch::clearConnections(PatchPanel *panel)
+void PatchPanel::Patch::clearConnections(const sp<IAfPatchPanel>& panel)
{
ALOGV("%s() mRecord.handle %d mPlayback.handle %d",
__func__, mRecord.handle(), mPlayback.handle());
@@ -647,7 +628,7 @@
mPlayback.closeConnections(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(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
@@ -767,18 +748,18 @@
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->unlock();
status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
- mAudioFlinger.lock();
+ mAfPatchPanelCallback->lock();
} else {
status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
}
@@ -790,18 +771,18 @@
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->unlock();
status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
- mAudioFlinger.lock();
+ mAfPatchPanelCallback->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(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(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(audio_module_handle_t module)
{
AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(module);
return audioHwDevice ? audioHwDevice->hwDevice() : nullptr;
}
-void AudioFlinger::PatchPanel::addSoftwarePatchToInsertedModules(
+void PatchPanel::addSoftwarePatchToInsertedModules(
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 2c5e47c..b8b7b79 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -15,217 +15,58 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
-public: // TODO(b/288339104) extract out of AudioFlinger class
-// PatchPanel is concealed within AudioFlinger, their lifetimes are the same.
-class PatchPanel {
+#include "IAfPatchPanel.h"
+
+#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);
+ struct audio_port* ports) final;
/* Get supported attributes for a given audio port */
- status_t getAudioPort(struct audio_port_v7 *port);
+ status_t getAudioPort(struct audio_port_v7* port) final;
/* Create a patch between several source and sink ports */
status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
- bool endpointPatch = false);
+ bool endpointPatch = false) final;
/* Release a patch */
- status_t releaseAudioPatch(audio_patch_handle_t handle);
+ status_t releaseAudioPatch(audio_patch_handle_t handle) final;
/* List connected audio devices and they attributes */
status_t listAudioPatches(unsigned int *num_patches,
- struct audio_patch *patches);
+ struct audio_patch* patches) final;
// Retrieves all currently estrablished 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;
-
- 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(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;
- };
+ void dump(int fd) const final;
// Call with AudioFlinger mLock held
- std::map<audio_patch_handle_t, Patch>& patches_l() { return mPatches; }
+ const std::map<audio_patch_handle_t, Patch>& patches_l() const final { return mPatches; }
+
+ // Must be called under AudioFlinger::mLock
+ status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final;
+
+ void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final;
private:
AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
@@ -236,7 +77,7 @@
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
@@ -266,4 +107,4 @@
std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
};
-private:
+} // namespace android
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 7ff2394..5f54e11 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -15,12 +15,15 @@
** 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/LinearMap.h>
+#include <binder/AppOpsManager.h>
+
+namespace android {
// Checks and monitors OP_PLAY_AUDIO
class OpPlayAudioMonitor : public RefBase {
@@ -30,13 +33,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 +60,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,16 +70,9 @@
};
// playback track
-class Track : public TrackBase, public VolumeProvider {
+class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider {
public:
- // 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 wrapper should be created per Track.
- static sp<media::IAudioTrack> createIAudioTrackAdapter(const sp<Track>& track);
-
- Track( PlaybackThread *thread,
+ Track(IAfPlaybackThread* thread,
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
@@ -99,72 +95,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;
}
@@ -172,21 +162,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);
@@ -195,16 +186,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_l() final;
+ void setTeePatchesToUpdate_l(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
@@ -215,29 +206,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);
@@ -246,38 +226,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;
}
@@ -288,25 +269,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;
@@ -349,8 +348,9 @@
private:
void interceptBuffer(const AudioBufferProvider::Buffer& buffer);
+ // Must hold thread lock to access tee patches
template <class F>
- void forEachTeePatchTrack(F f) {
+ void forEachTeePatchTrack_l(F f) {
for (auto& tp : mTeePatches) { f(tp.patchTrack); }
};
@@ -384,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;
@@ -398,7 +398,7 @@
// playback track, used by DuplicatingThread
-class OutputTrack : public Track {
+class OutputTrack : public Track, public IAfOutputTrack {
public:
class Buffer : public AudioBufferProvider::Buffer {
@@ -406,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;
@@ -439,7 +438,6 @@
// (with mTimeNs[] filled with -1's) is returned.
return timestamp;
}
-
private:
status_t obtainBuffer(AudioBufferProvider::Buffer* buffer,
uint32_t waitTimeMs);
@@ -454,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.
@@ -474,10 +472,9 @@
}; // 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,
@@ -491,23 +488,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 61f36a1..021add4 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -15,23 +15,19 @@
** 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 <datapath/AudioStreamIn.h> // struct Source
+
+namespace android {
// record track
-class RecordTrack : public TrackBase {
+class RecordTrack : public TrackBase, public virtual IAfRecordTrack {
public:
- // createIAudioRecordAdapter() is a static constructor which creates an
- // IAudioRecord AIDL interface wrapper from the RecordTrack object that
- // may be passed back to the client (if needed).
- //
- // Only one AIDL IAudioRecord interface wrapper should be created per RecordTrack.
- static sp<media::IAudioRecord> createIAudioRecordAdapter(const sp<RecordTrack>& recordTrack);
-
- RecordTrack(RecordThread *thread,
+ RecordTrack(IAfRecordThread* thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
@@ -47,67 +43,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
@@ -120,7 +119,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;
@@ -133,10 +132,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,
@@ -146,20 +144,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);
}
@@ -172,7 +170,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,
@@ -180,25 +178,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
@@ -215,7 +213,7 @@
PassthruPatchRecord& mPassthru;
};
- sp<StreamInHalInterface> obtainStream(sp<ThreadBase>* thread);
+ sp<StreamInHalInterface> obtainStream(sp<IAfThreadBase>* thread);
PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
std::unique_ptr<void, decltype(free)*> mSinkBuffer; // frame size aligned continuous buffer
@@ -227,3 +225,5 @@
status_t mReadError = NO_ERROR; // GUARDED_BY(mReadLock)
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 e1017f5..eb6b4f3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -76,6 +76,8 @@
#include <media/audiohal/StreamHalInterface.h>
#include "AudioFlinger.h"
+#include "Threads.h"
+
#include <mediautils/SchedulingPolicyService.h>
#include <mediautils/ServiceUtilities.h>
@@ -92,6 +94,8 @@
#include <fastpath/AutoPark.h>
#include <pthread.h>
+#include <afutils/DumpTryLock.h>
+#include <afutils/Permission.h>
#include <afutils/TypedLogger.h>
// ----------------------------------------------------------------------------
@@ -120,6 +124,7 @@
namespace android {
+using audioflinger::SyncEvent;
using media::IEffectClient;
using content::AttributionSourceState;
@@ -515,7 +520,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 +546,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 +569,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 +584,7 @@
sendStatistics(true /* force */);
}
-status_t AudioFlinger::ThreadBase::readyToRun()
+status_t ThreadBase::readyToRun()
{
status_t status = initCheck();
if (status == NO_ERROR) {
@@ -590,7 +595,7 @@
return status;
}
-void AudioFlinger::ThreadBase::exit()
+void ThreadBase::exit()
{
ALOGV("ThreadBase::exit");
// do any cleanup required for exit to succeed
@@ -614,7 +619,7 @@
requestExitAndWait();
}
-status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
+status_t ThreadBase::setParameters(const String8& keyValuePairs)
{
ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
Mutex::Autolock _l(mLock);
@@ -624,7 +629,7 @@
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from processConfigEvents_l().
-status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
+status_t ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
NO_THREAD_SAFETY_ANALYSIS // condition variable
{
status_t status = NO_ERROR;
@@ -652,7 +657,7 @@
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);
@@ -660,7 +665,7 @@
}
// sendIoConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid,
+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,14 +682,14 @@
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);
sendPrioConfigEvent_l(pid, tid, prio, forApp);
}
// sendPrioConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(
+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);
@@ -692,7 +697,7 @@
}
// sendSetParameterConfigEvent_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
+status_t ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
{
sp<ConfigEvent> configEvent;
AudioParameter param(keyValuePair);
@@ -710,7 +715,7 @@
return sendConfigEvent_l(configEvent);
}
-status_t AudioFlinger::ThreadBase::sendCreateAudioPatchConfigEvent(
+status_t ThreadBase::sendCreateAudioPatchConfigEvent(
const struct audio_patch *patch,
audio_patch_handle_t *handle)
{
@@ -725,7 +730,7 @@
return status;
}
-status_t AudioFlinger::ThreadBase::sendReleaseAudioPatchConfigEvent(
+status_t ThreadBase::sendReleaseAudioPatchConfigEvent(
const audio_patch_handle_t handle)
{
Mutex::Autolock _l(mLock);
@@ -733,7 +738,7 @@
return sendConfigEvent_l(configEvent);
}
-status_t AudioFlinger::ThreadBase::sendUpdateOutDeviceConfigEvent(
+status_t ThreadBase::sendUpdateOutDeviceConfigEvent(
const DeviceDescriptorBaseVector& outDevices)
{
if (type() != RECORD) {
@@ -745,7 +750,7 @@
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 +758,27 @@
sendConfigEvent_l(configEvent);
}
-void AudioFlinger::ThreadBase::sendCheckOutputStageEffectsEvent()
+void ThreadBase::sendCheckOutputStageEffectsEvent()
{
Mutex::Autolock _l(mLock);
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;
@@ -940,13 +945,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(mLock);
if (!locked) {
dprintf(fd, " Thread may be deadlocked\n");
}
@@ -978,7 +983,7 @@
}
}
-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");
@@ -1051,7 +1056,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];
@@ -1068,13 +1073,13 @@
}
}
-void AudioFlinger::ThreadBase::acquireWakeLock()
+void ThreadBase::acquireWakeLock()
{
Mutex::Autolock _l(mLock);
acquireWakeLock_l();
}
-String16 AudioFlinger::ThreadBase::getWakeLockTag()
+String16 ThreadBase::getWakeLockTag()
{
switch (mType) {
case MIXER:
@@ -1099,7 +1104,7 @@
}
}
-void AudioFlinger::ThreadBase::acquireWakeLock_l()
+void ThreadBase::acquireWakeLock_l()
{
getPowerManager_l();
if (mPowerManager != 0) {
@@ -1122,13 +1127,13 @@
gBoottime.getBoottimeOffset();
}
-void AudioFlinger::ThreadBase::releaseWakeLock()
+void ThreadBase::releaseWakeLock()
{
Mutex::Autolock _l(mLock);
releaseWakeLock_l();
}
-void AudioFlinger::ThreadBase::releaseWakeLock_l()
+void ThreadBase::releaseWakeLock_l()
{
gBoottime.release(mWakeLockToken);
if (mWakeLockToken != 0) {
@@ -1140,7 +1145,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 +1159,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 +1186,25 @@
}
}
-void AudioFlinger::ThreadBase::clearPowerManager()
+void ThreadBase::clearPowerManager()
{
Mutex::Autolock _l(mLock);
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,7 +1213,7 @@
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<IAfEffectChain> chain = getEffectChain_l(sessionId);
@@ -1223,7 +1228,7 @@
updateSuspendedSessions_l(type, suspend, sessionId);
}
-void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain)
+void ThreadBase::checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain)
{
ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
if (index < 0) {
@@ -1247,7 +1252,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)
{
@@ -1308,7 +1313,7 @@
}
}
-void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
+void ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
audio_session_t sessionId,
bool threadLocked)
NO_THREAD_SAFETY_ANALYSIS // manual locking
@@ -1334,7 +1339,7 @@
}
// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::RecordThread::checkEffectCompatibility_l(
+status_t RecordThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
// No global output effect sessions on record threads
@@ -1378,7 +1383,7 @@
}
// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::PlaybackThread::checkEffectCompatibility_l(
+status_t PlaybackThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
// no preprocessing on playback threads
@@ -1533,7 +1538,7 @@
}
// ThreadBase::createEffect_l() must be called with AudioFlinger::mLock held
-sp<IAfEffectHandle> AudioFlinger::ThreadBase::createEffect_l(
+sp<IAfEffectHandle> ThreadBase::createEffect_l(
const sp<Client>& client,
const sp<IEffectClient>& effectClient,
int32_t priority,
@@ -1585,7 +1590,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,14 +1601,14 @@
// 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);
@@ -1638,7 +1643,7 @@
return handle;
}
-void AudioFlinger::ThreadBase::disconnectEffectHandle(IAfEffectHandle *handle,
+void ThreadBase::disconnectEffectHandle(IAfEffectHandle* handle,
bool unpinIfLast)
{
bool remove = false;
@@ -1661,14 +1666,14 @@
sendCheckOutputStageEffectsEvent_l();
}
if (remove) {
- mAudioFlinger->updateOrphanEffectChains(effect);
+ mAfThreadCallback->updateOrphanEffectChains(effect);
if (handle->enabled()) {
effect->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
}
}
}
-void AudioFlinger::ThreadBase::onEffectEnable(const sp<IAfEffectModule>& effect) {
+void ThreadBase::onEffectEnable(const sp<IAfEffectModule>& effect) {
if (isOffloadOrMmap()) {
Mutex::Autolock _l(mLock);
broadcast_l();
@@ -1679,33 +1684,33 @@
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);
broadcast_l();
}
}
-sp<IAfEffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
- int effectId)
+sp<IAfEffectModule> ThreadBase::getEffect(audio_session_t sessionId,
+ int effectId) const
{
Mutex::Autolock _l(mLock);
return getEffect_l(sessionId, effectId);
}
-sp<IAfEffectModule> AudioFlinger::ThreadBase::getEffect_l(audio_session_t sessionId,
- int effectId)
+sp<IAfEffectModule> ThreadBase::getEffect_l(audio_session_t sessionId,
+ int effectId) const
{
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<IAfEffectChain> chain = getEffectChain_l(sessionId);
return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
@@ -1713,7 +1718,7 @@
// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
// PlaybackThread::mLock held
-status_t AudioFlinger::ThreadBase::addEffect_l(const sp<IAfEffectModule>& effect)
+status_t ThreadBase::addEffect_l(const sp<IAfEffectModule>& effect)
{
// check for existing effect chain with the requested audio session
audio_session_t sessionId = effect->sessionId();
@@ -1752,13 +1757,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<IAfEffectModule>& 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();
@@ -1777,7 +1782,7 @@
}
}
-void AudioFlinger::ThreadBase::lockEffectChains_l(
+void ThreadBase::lockEffectChains_l(
Vector<sp<IAfEffectChain>>& effectChains)
NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::lock()
{
@@ -1787,7 +1792,7 @@
}
}
-void AudioFlinger::ThreadBase::unlockEffectChains(
+void ThreadBase::unlockEffectChains(
const Vector<sp<IAfEffectChain>>& effectChains)
NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::unlock()
{
@@ -1796,13 +1801,13 @@
}
}
-sp<IAfEffectChain> AudioFlinger::ThreadBase::getEffectChain(audio_session_t sessionId)
+sp<IAfEffectChain> ThreadBase::getEffectChain(audio_session_t sessionId) const
{
Mutex::Autolock _l(mLock);
return getEffectChain_l(sessionId);
}
-sp<IAfEffectChain> AudioFlinger::ThreadBase::getEffectChain_l(audio_session_t sessionId)
+sp<IAfEffectChain> ThreadBase::getEffectChain_l(audio_session_t sessionId)
const
{
size_t size = mEffectChains.size();
@@ -1814,7 +1819,7 @@
return 0;
}
-void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
+void ThreadBase::setMode(audio_mode_t mode)
{
Mutex::Autolock _l(mLock);
size_t size = mEffectChains.size();
@@ -1823,7 +1828,7 @@
}
}
-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;
@@ -1834,7 +1839,7 @@
AUDIO_PORT_CONFIG_FORMAT;
}
-void AudioFlinger::ThreadBase::systemReady()
+void ThreadBase::systemReady()
{
Mutex::Autolock _l(mLock);
if (mSystemReady) {
@@ -1849,7 +1854,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());
@@ -1858,13 +1863,13 @@
logTrack("add", track);
mActiveTracksGeneration++;
mLatestActiveTrack = track;
- ++mBatteryCounter[track->uid()].second;
+ track->beginBatteryAttribution();
mHasChanged = true;
return mActiveTracks.add(track);
}
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());
@@ -1872,7 +1877,7 @@
}
logTrack("remove", track);
mActiveTracksGeneration++;
- --mBatteryCounter[track->uid()].second;
+ track->endBatteryAttribution();
// mLatestActiveTrack is not cleared even if is the same as track.
mHasChanged = true;
#ifdef TEE_SINK
@@ -1883,51 +1888,29 @@
}
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());
+ track->endBatteryAttribution();
logTrack("clear", track);
}
mLastActiveTracksGeneration = mActiveTracksGeneration;
if (!mActiveTracks.empty()) { mHasChanged = true; }
mActiveTracks.clear();
mLatestActiveTrack.clear();
- mBatteryCounter.clear();
}
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) {
thread->updateWakeLockUids_l(getWakeLockUids());
mLastActiveTracksGeneration = mActiveTracksGeneration;
}
-
- // Updates BatteryNotifier uids
- for (auto it = mBatteryCounter.begin(); it != mBatteryCounter.end();) {
- const uid_t uid = it->first;
- ssize_t &previous = it->second.first;
- ssize_t ¤t = it->second.second;
- if (current > 0) {
- if (previous == 0) {
- BatteryNotifier::getInstance().noteStartAudio(uid);
- }
- previous = current;
- ++it;
- } else if (current == 0) {
- if (previous > 0) {
- BatteryNotifier::getInstance().noteStopAudio(uid);
- }
- it = mBatteryCounter.erase(it); // std::map<> is stable on iterator erase.
- } else /* (current < 0) */ {
- LOG_ALWAYS_FATAL("negative battery count %zd", current);
- }
- }
}
template <typename T>
-bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
+bool ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
bool hasChanged = mHasChanged;
mHasChanged = false;
@@ -1940,7 +1923,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;
@@ -1949,7 +1932,7 @@
}
}
-void AudioFlinger::ThreadBase::broadcast_l()
+void ThreadBase::broadcast_l()
{
// Thread could be blocked waiting for async
// so signal it to handle state changes immediately
@@ -1961,7 +1944,7 @@
// Call only from threadLoop() or when it is idle.
// Do not call from high performance code as this may do binder rpc to the MediaMetrics service.
-void 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.
@@ -2024,16 +2007,16 @@
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(
+void ThreadBase::startMelComputation_l(
const sp<audio_utils::MelProcessor>& /*processor*/)
{
// Do nothing
@@ -2041,7 +2024,7 @@
}
// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::ThreadBase::stopMelComputation_l()
+void ThreadBase::stopMelComputation_l()
{
// Do nothing
ALOGW("%s: ThreadBase does not support CSD", __func__);
@@ -2051,13 +2034,13 @@
// 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),
mMixerBuffer(NULL),
@@ -2085,7 +2068,7 @@
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),
@@ -2094,7 +2077,7 @@
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
// it would be safer to explicitly pass initial masterVolume/masterMute as
@@ -2103,8 +2086,8 @@
// 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;
@@ -2142,7 +2125,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;
@@ -2151,9 +2134,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);
@@ -2162,7 +2145,7 @@
// Thread virtuals
-void AudioFlinger::PlaybackThread::onFirstRef()
+void PlaybackThread::onFirstRef()
{
if (!isStreamInitialized()) {
ALOGE("The stream is not open yet"); // This should not happen.
@@ -2177,7 +2160,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) {
@@ -2189,14 +2172,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;
@@ -2230,7 +2213,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) {
@@ -2250,7 +2233,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 */);
@@ -2261,7 +2244,7 @@
write(fd, result.string(), 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");
@@ -2297,7 +2280,7 @@
}
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
+sp<IAfTrack> PlaybackThread::createTrack_l(
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
@@ -2322,7 +2305,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;
@@ -2615,7 +2598,7 @@
// 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) {
@@ -2637,11 +2620,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;
@@ -2682,7 +2665,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);
@@ -2697,17 +2680,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);
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) {
@@ -2716,7 +2699,7 @@
return 0;
}
-void AudioFlinger::PlaybackThread::setMasterVolume(float value)
+void PlaybackThread::setMasterVolume(float value)
{
Mutex::Autolock _l(mLock);
// Don't apply master volume in SW if our HAL can do it for us.
@@ -2728,12 +2711,12 @@
}
}
-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;
@@ -2748,33 +2731,33 @@
}
}
-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);
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);
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);
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)
+status_t PlaybackThread::addTrack_l(const sp<IAfTrack>& track)
NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
status_t status = ALREADY_EXISTS;
@@ -2784,12 +2767,12 @@
// 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;
+ IAfTrackBase::track_state state = track->state();
mLock.unlock();
status = AudioSystem::startOutput(track->portId());
mLock.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();
AudioSystem::stopOutput(track->portId());
@@ -2815,15 +2798,15 @@
// 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<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
@@ -2839,8 +2822,8 @@
{
// 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());
+ Mutex::Autolock _l(mAfThreadCallback->mutex());
+ vibratorInfo = std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
}
mLock.lock();
track->setHapticIntensity(intensity);
@@ -2863,7 +2846,7 @@
}
}
- track->mResetDone = false;
+ track->setResetDone(false);
track->resetPresentationComplete();
mActiveTracks.add(track);
if (chain != 0) {
@@ -2880,25 +2863,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);
@@ -2912,12 +2895,12 @@
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<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
@@ -2925,7 +2908,7 @@
}
}
-String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
+String8 PlaybackThread::getParameters(const String8& keys)
{
Mutex::Autolock _l(mLock);
String8 out_s8;
@@ -2935,7 +2918,7 @@
return {};
}
-status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
+status_t DirectOutputThread::selectPresentation(int presentationId, int programId) {
Mutex::Autolock _l(mLock);
if (!isStreamInitialized()) {
return NO_INIT;
@@ -2943,7 +2926,7 @@
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;
@@ -2965,30 +2948,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;
@@ -3013,7 +2996,7 @@
}).detach();
}
-void AudioFlinger::PlaybackThread::resetWriteBlocked(uint32_t sequence)
+void PlaybackThread::resetWriteBlocked(uint32_t sequence)
{
Mutex::Autolock _l(mLock);
// reject out of sequence requests
@@ -3023,7 +3006,7 @@
}
}
-void AudioFlinger::PlaybackThread::resetDraining(uint32_t sequence)
+void PlaybackThread::resetDraining(uint32_t sequence)
{
Mutex::Autolock _l(mLock);
// reject out of sequence requests
@@ -3038,7 +3021,7 @@
}
}
-void AudioFlinger::PlaybackThread::readOutputParameters_l()
+void PlaybackThread::readOutputParameters_l()
{
// unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
const audio_config_base_t audioConfig = mOutput->getAudioProperties();
@@ -3047,7 +3030,7 @@
if (!audio_is_output_channel(mChannelMask)) {
LOG_ALWAYS_FATAL("HAL channel mask %#x not valid for output", mChannelMask);
}
- if (hasMixer() && !isValidPcmSinkChannelMask(mChannelMask)) {
+ if (hasMixer() && !AudioFlinger::isValidPcmSinkChannelMask(mChannelMask)) {
LOG_ALWAYS_FATAL("HAL channel mask %#x not supported for mixed output",
mChannelMask);
}
@@ -3070,7 +3053,7 @@
if (!audio_is_valid_format(mFormat)) {
LOG_ALWAYS_FATAL("HAL format %#x not valid for output", mFormat);
}
- if (hasMixer() && !isValidPcmSinkFormat(mFormat)) {
+ if (hasMixer() && !AudioFlinger::isValidPcmSinkFormat(mFormat)) {
LOG_FATAL("HAL format %#x not supported for mixed output",
mFormat);
}
@@ -3209,7 +3192,7 @@
// create a copy of mEffectChains as calling moveEffectChain_l() 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_l(effectChains[i]->sessionId(),
this/* srcThread */, this/* dstThread */);
}
@@ -3238,14 +3221,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);
}
@@ -3255,13 +3238,14 @@
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;
@@ -3288,7 +3272,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
@@ -3296,7 +3280,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());
}
@@ -3305,13 +3289,13 @@
}
-AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
+AudioStreamOut* PlaybackThread::getOutput() const
{
Mutex::Autolock _l(mLock);
return mOutput;
}
-AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
+AudioStreamOut* PlaybackThread::clearOutput()
{
Mutex::Autolock _l(mLock);
AudioStreamOut *output = mOutput;
@@ -3325,7 +3309,7 @@
}
// this method must always be called either with ThreadBase mLock held or inside the thread loop
-sp<StreamHalInterface> AudioFlinger::PlaybackThread::stream() const
+sp<StreamHalInterface> PlaybackThread::stream() const
{
if (mOutput == NULL) {
return NULL;
@@ -3333,12 +3317,12 @@
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;
@@ -3347,7 +3331,7 @@
Mutex::Autolock _l(mLock);
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;
@@ -3357,14 +3341,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.
@@ -3378,7 +3361,7 @@
#endif
}
-void AudioFlinger::PlaybackThread::checkSilentMode_l()
+void PlaybackThread::checkSilentMode_l()
{
if (!mMasterMute) {
char value[PROPERTY_VALUE_MAX];
@@ -3404,7 +3387,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;
@@ -3418,7 +3401,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();
@@ -3476,7 +3459,7 @@
}
// startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::startMelComputation_l(
+void PlaybackThread::startMelComputation_l(
const sp<audio_utils::MelProcessor>& processor)
{
auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
@@ -3486,7 +3469,7 @@
}
// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::stopMelComputation_l()
+void PlaybackThread::stopMelComputation_l()
{
auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
if (outputSink != nullptr) {
@@ -3494,7 +3477,7 @@
}
}
-void AudioFlinger::PlaybackThread::threadLoop_drain()
+void PlaybackThread::threadLoop_drain()
{
bool supportsDrain = false;
if (mOutput->stream->supportsDrain(&supportsDrain) == OK && supportsDrain) {
@@ -3510,12 +3493,12 @@
}
}
-void AudioFlinger::PlaybackThread::threadLoop_exit()
+void PlaybackThread::threadLoop_exit()
{
{
Mutex::Autolock _l(mLock);
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.
@@ -3546,7 +3529,7 @@
- idle sleep time
*/
-void AudioFlinger::PlaybackThread::cacheParameters_l()
+void PlaybackThread::cacheParameters_l()
{
mSinkBufferSize = mNormalFrameCount * mFrameSize;
mActiveSleepTimeUs = activeSleepTimeUs();
@@ -3563,14 +3546,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;
@@ -3579,22 +3562,22 @@
return trackMatch;
}
-void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
{
Mutex::Autolock _l(mLock);
invalidateTracks_l(streamType);
}
-void AudioFlinger::PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
+void PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
Mutex::Autolock _l(mLock);
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());
@@ -3608,7 +3591,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) {
@@ -3618,7 +3601,7 @@
return nullptr;
}
-status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
+status_t PlaybackThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
{
audio_session_t session = chain->sessionId();
sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
@@ -3639,12 +3622,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);
@@ -3659,10 +3642,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;
@@ -3671,7 +3654,7 @@
}
}
} else {
- status_t result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+ status_t result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
mEffectBufferEnabled ? mEffectBuffer : mSinkBuffer,
mEffectBufferEnabled ? mEffectBufferSize : mSinkBufferSize,
&halInBuffer);
@@ -3687,7 +3670,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;
@@ -3702,7 +3686,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);
@@ -3712,7 +3696,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);
@@ -3754,7 +3738,7 @@
return NO_ERROR;
}
-size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
+size_t PlaybackThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
{
audio_session_t session = chain->sessionId();
@@ -3764,7 +3748,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);
@@ -3774,7 +3758,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();
@@ -3786,15 +3770,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);
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;
@@ -3816,22 +3800,22 @@
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;
+ Vector<sp<IAfTrack>> tracksToRemove;
mStandbyTimeNs = systemTime();
int64_t lastLoopCountWritten = -2; // never matches "previous" loop, when loopCount = 0.
@@ -3879,14 +3863,14 @@
{
// 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<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.
//
@@ -3894,12 +3878,13 @@
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().tryLock() == NO_ERROR) {
+ 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();
@@ -3920,7 +3905,7 @@
}
mDownstreamLatencyStatMs.add(latencyMs);
}
- mAudioFlinger->mLock.unlock();
+ mAfThreadCallback->mutex().unlock();
}
} else {
if (lastDownstreamPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
@@ -4076,7 +4061,7 @@
setHalLatencyMode_l();
for (const auto &track : mActiveTracks ) {
- track->updateTeePatches();
+ track->updateTeePatches_l();
}
// signal actual start of output stream when the render position reported by the kernel
@@ -4104,14 +4089,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);
}
}
}
@@ -4280,7 +4266,7 @@
unlockEffectChains(effectChains);
if (!metadataUpdate.playbackMetadataUpdate.empty()) {
- mAudioFlinger->mMelReporter->updateMetadataForCsd(id(),
+ mAfThreadCallback->getMelReporter()->updateMetadataForCsd(id(),
metadataUpdate.playbackMetadataUpdate);
}
@@ -4481,7 +4467,7 @@
return false;
}
-void AudioFlinger::PlaybackThread::collectTimestamps_l()
+void PlaybackThread::collectTimestamps_l()
{
if (mStandby) {
mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
@@ -4586,10 +4572,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);
@@ -4617,7 +4603,7 @@
}
// removeTracks_l() must be called with ThreadBase::mLock held
-void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
+void PlaybackThread::removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove)
NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
for (const auto& track : tracksToRemove) {
@@ -4659,7 +4645,7 @@
}
}
-status_t AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
+status_t PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
{
if (mNormalSink != 0) {
ExtendedTimestamp ets;
@@ -4688,7 +4674,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) {
@@ -4710,7 +4696,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;
@@ -4727,7 +4713,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;
@@ -4811,7 +4797,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 */)) {
@@ -4825,7 +4811,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;
@@ -4844,19 +4830,19 @@
return status;
}
-void AudioFlinger::PlaybackThread::addPatchTrack(const sp<PatchTrack>& track)
+void PlaybackThread::addPatchTrack(const sp<IAfPatchTrack>& track)
{
Mutex::Autolock _l(mLock);
mTracks.add(track);
}
-void AudioFlinger::PlaybackThread::deletePatchTrack(const sp<PatchTrack>& track)
+void PlaybackThread::deletePatchTrack(const sp<IAfPatchTrack>& track)
{
Mutex::Autolock _l(mLock);
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;
@@ -4870,9 +4856,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),
@@ -4882,7 +4875,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",
@@ -5009,7 +5002,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);
@@ -5055,7 +5048,7 @@
}
}
-AudioFlinger::MixerThread::~MixerThread()
+MixerThread::~MixerThread()
{
if (mFastMixer != 0) {
FastMixerStateQueue *sq = mFastMixer->sq();
@@ -5088,11 +5081,11 @@
}
#endif
}
- mAudioFlinger->unregisterWriter(mFastMixerNBLogWriter);
+ mAfThreadCallback->unregisterWriter(mFastMixerNBLogWriter);
delete mAudioMixer;
}
-void AudioFlinger::MixerThread::onFirstRef() {
+void MixerThread::onFirstRef() {
PlaybackThread::onFirstRef();
Mutex::Autolock _l(mLock);
@@ -5108,7 +5101,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();
@@ -5117,7 +5110,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
@@ -5145,7 +5138,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();
@@ -5160,7 +5153,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) {
@@ -5198,24 +5191,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);
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();
@@ -5231,20 +5224,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();
@@ -5262,7 +5255,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
@@ -5316,8 +5309,8 @@
}
// prepareTracks_l() must be called with ThreadBase::mLock held
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
- Vector< sp<Track> > *tracksToRemove)
+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) {
@@ -5393,23 +5386,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()) {
@@ -5427,7 +5420,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];
@@ -5437,13 +5430,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;
@@ -5453,30 +5446,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
@@ -5490,7 +5483,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;
@@ -5501,10 +5494,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
@@ -5521,7 +5514,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
@@ -5531,20 +5524,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();
@@ -5553,7 +5546,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;
@@ -5568,12 +5561,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,
@@ -5604,13 +5597,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();
@@ -5632,14 +5625,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;
@@ -5652,8 +5645,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);
@@ -5703,11 +5696,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;
@@ -5728,9 +5721,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;
@@ -5756,7 +5749,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,
@@ -5792,18 +5785,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);
@@ -5911,13 +5904,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
@@ -5969,7 +5963,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);
@@ -6045,7 +6039,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();
}
@@ -6111,7 +6105,7 @@
}
// trackCountForUid_l() must be called with ThreadBase::mLock held
-uint32_t AudioFlinger::PlaybackThread::trackCountForUid_l(uid_t uid) const
+uint32_t PlaybackThread::trackCountForUid_l(uid_t uid) const
{
uint32_t trackCount = 0;
for (size_t i = 0; i < mTracks.size() ; i++) {
@@ -6122,7 +6116,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
@@ -6146,7 +6140,7 @@
return mLatchedValue;
}
-void AudioFlinger::PlaybackThread::IsTimestampAdvancing::clear()
+void PlaybackThread::IsTimestampAdvancing::clear()
{
mLatchedValue = true;
mPreviousPosition = 0;
@@ -6154,7 +6148,7 @@
}
// isTrackAllowed_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::isTrackAllowed_l(
+bool MixerThread::isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
audio_session_t sessionId, uid_t uid) const
{
@@ -6174,7 +6168,7 @@
}
// checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePair,
+bool MixerThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
bool reconfig = false;
@@ -6188,7 +6182,7 @@
reconfig = true;
}
if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
- if (!isValidPcmSinkFormat((audio_format_t) value)) {
+ if (!AudioFlinger::isValidPcmSinkFormat(static_cast<audio_format_t>(value))) {
status = BAD_VALUE;
} else {
// no need to save value, since it's constant
@@ -6196,7 +6190,7 @@
}
}
if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
- if (!isValidPcmSinkChannelMask((audio_channel_mask_t) value)) {
+ if (!AudioFlinger::isValidPcmSinkChannelMask(static_cast<audio_channel_mask_t>(value))) {
status = BAD_VALUE;
} else {
// no need to save value, since it's constant
@@ -6237,14 +6231,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);
}
@@ -6254,7 +6248,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);
@@ -6301,17 +6295,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();
@@ -6322,11 +6316,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
@@ -6368,7 +6362,7 @@
}
}
-void AudioFlinger::MixerThread::updateHalSupportedLatencyModes_l() {
+void MixerThread::updateHalSupportedLatencyModes_l() {
if (mOutput == nullptr || mOutput->stream == nullptr) {
return;
@@ -6386,7 +6380,7 @@
}
}
-status_t AudioFlinger::MixerThread::getSupportedLatencyModes(
+status_t MixerThread::getSupportedLatencyModes(
std::vector<audio_latency_mode_t>* modes) {
if (modes == nullptr) {
return BAD_VALUE;
@@ -6396,7 +6390,7 @@
return NO_ERROR;
}
-void AudioFlinger::MixerThread::onRecommendedLatencyModeChanged(
+void MixerThread::onRecommendedLatencyModeChanged(
std::vector<audio_latency_mode_t> modes) {
Mutex::Autolock _l(mLock);
if (modes != mSupportedLatencyModes) {
@@ -6407,7 +6401,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;
@@ -6418,27 +6412,36 @@
// ----------------------------------------------------------------------------
-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);
if (mMasterBalance != balance) {
@@ -6448,12 +6451,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 size_t framesReleased = proxy->framesReleased();
const int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
@@ -6488,14 +6491,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,
@@ -6527,10 +6530,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) {
@@ -6552,8 +6555,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();
@@ -6562,14 +6565,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
@@ -6577,7 +6580,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()) {
@@ -6613,8 +6616,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.
@@ -6626,7 +6629,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;
@@ -6644,8 +6647,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;
@@ -6658,7 +6661,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
@@ -6670,7 +6673,7 @@
mPreviousTrack = track;
// reset retry count
- track->mRetryCount = targetRetryCount;
+ track->retryCount() = targetRetryCount;
mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
if (mHwPaused) {
@@ -6685,7 +6688,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;
@@ -6703,7 +6706,7 @@
mOutput->presentationComplete();
}
if (track->isStopping_2()) {
- track->mState = TrackBase::STOPPED;
+ track->setState(IAfTrackBase::STOPPED);
}
if (track->isStopped()) {
track->reset();
@@ -6716,9 +6719,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);
@@ -6775,7 +6778,7 @@
return mixerStatus;
}
-void AudioFlinger::DirectOutputThread::threadLoop_mix()
+void DirectOutputThread::threadLoop_mix()
{
size_t frameCount = mFrameCount;
int8_t *curBuf = (int8_t *)mSinkBuffer;
@@ -6802,7 +6805,7 @@
mActiveTrack.clear();
}
-void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
+void DirectOutputThread::threadLoop_sleepTime()
{
// do not write to HAL when paused
if (mHwPaused || (usesHwAvSync() && mStandby)) {
@@ -6818,7 +6821,7 @@
// linear or proportional PCM direct tracks in underrun.
}
-void AudioFlinger::DirectOutputThread::threadLoop_exit()
+void DirectOutputThread::threadLoop_exit()
{
{
Mutex::Autolock _l(mLock);
@@ -6836,7 +6839,7 @@
}
// must be called with thread mutex locked
-bool AudioFlinger::DirectOutputThread::shouldStandby_l()
+bool DirectOutputThread::shouldStandby_l()
{
bool trackPaused = false;
bool trackStopped = false;
@@ -6846,14 +6849,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,
+bool DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
bool reconfig = false;
@@ -6895,7 +6898,7 @@
return reconfig;
}
-uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
+uint32_t DirectOutputThread::activeSleepTimeUs() const
{
uint32_t time;
if (audio_has_proportional_frames(mFormat)) {
@@ -6906,7 +6909,7 @@
return time;
}
-uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() const
+uint32_t DirectOutputThread::idleSleepTimeUs() const
{
uint32_t time;
if (audio_has_proportional_frames(mFormat)) {
@@ -6917,7 +6920,7 @@
return time;
}
-uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() const
+uint32_t DirectOutputThread::suspendSleepTimeUs() const
{
uint32_t time;
if (audio_has_proportional_frames(mFormat)) {
@@ -6928,7 +6931,7 @@
return time;
}
-void AudioFlinger::DirectOutputThread::cacheParameters_l()
+void DirectOutputThread::cacheParameters_l()
{
PlaybackThread::cacheParameters_l();
@@ -6944,7 +6947,7 @@
}
}
-void AudioFlinger::DirectOutputThread::flushHw_l()
+void DirectOutputThread::flushHw_l()
{
PlaybackThread::flushHw_l();
mOutput->flush();
@@ -6955,7 +6958,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 ?
@@ -6964,8 +6967,8 @@
// ----------------------------------------------------------------------------
-AudioFlinger::AsyncCallbackThread::AsyncCallbackThread(
- const wp<AudioFlinger::PlaybackThread>& playbackThread)
+AsyncCallbackThread::AsyncCallbackThread(
+ const wp<PlaybackThread>& playbackThread)
: Thread(false /*canCallJava*/),
mPlaybackThread(playbackThread),
mWriteAckSequence(0),
@@ -6974,16 +6977,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;
@@ -7012,7 +7011,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);
@@ -7029,7 +7028,7 @@
return false;
}
-void AudioFlinger::AsyncCallbackThread::exit()
+void AsyncCallbackThread::exit()
{
ALOGV("AsyncCallbackThread::exit");
Mutex::Autolock _l(mLock);
@@ -7037,14 +7036,14 @@
mWaitWorkCV.broadcast();
}
-void AudioFlinger::AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
+void AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
{
Mutex::Autolock _l(mLock);
// bit 0 is cleared
mWriteAckSequence = sequence << 1;
}
-void AudioFlinger::AsyncCallbackThread::resetWriteBlocked()
+void AsyncCallbackThread::resetWriteBlocked()
{
Mutex::Autolock _l(mLock);
// ignore unexpected callbacks
@@ -7054,14 +7053,14 @@
}
}
-void AudioFlinger::AsyncCallbackThread::setDraining(uint32_t sequence)
+void AsyncCallbackThread::setDraining(uint32_t sequence)
{
Mutex::Autolock _l(mLock);
// bit 0 is cleared
mDrainSequence = sequence << 1;
}
-void AudioFlinger::AsyncCallbackThread::resetDraining()
+void AsyncCallbackThread::resetDraining()
{
Mutex::Autolock _l(mLock);
// ignore unexpected callbacks
@@ -7071,7 +7070,7 @@
}
}
-void AudioFlinger::AsyncCallbackThread::setAsyncError()
+void AsyncCallbackThread::setAsyncError()
{
Mutex::Autolock _l(mLock);
mAsyncError = true;
@@ -7080,10 +7079,19 @@
// ----------------------------------------------------------------------------
-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
@@ -7091,7 +7099,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
@@ -7107,8 +7115,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();
@@ -7120,8 +7128,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
@@ -7129,7 +7137,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()) {
@@ -7138,7 +7146,7 @@
continue;
}
- if (track->mState == TrackBase::IDLE) {
+ if (track->state() == IAfTrackBase::IDLE) {
ALOGW("An idle track shouldn't be in active list");
continue;
}
@@ -7170,9 +7178,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) {
@@ -7204,8 +7212,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;
@@ -7213,7 +7221,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
@@ -7239,9 +7247,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;
@@ -7249,7 +7257,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.
@@ -7257,7 +7265,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
@@ -7277,13 +7286,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();
@@ -7303,9 +7312,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());
@@ -7349,7 +7358,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);
@@ -7359,13 +7368,13 @@
return false;
}
-bool AudioFlinger::OffloadThread::waitingAsyncCallback()
+bool OffloadThread::waitingAsyncCallback()
{
Mutex::Autolock _l(mLock);
return waitingAsyncCallback_l();
}
-void AudioFlinger::OffloadThread::flushHw_l()
+void OffloadThread::flushHw_l()
{
DirectOutputThread::flushHw_l();
// Flush anything still waiting in the mixbuffer
@@ -7386,7 +7395,7 @@
}
}
-void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
+void OffloadThread::invalidateTracks(audio_stream_type_t streamType)
{
Mutex::Autolock _l(mLock);
if (PlaybackThread::invalidateTracks_l(streamType)) {
@@ -7394,7 +7403,7 @@
}
}
-void AudioFlinger::OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
+void OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
Mutex::Autolock _l(mLock);
if (PlaybackThread::invalidateTracks_l(portIds)) {
mFlushPending = true;
@@ -7403,23 +7412,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()) {
@@ -7437,7 +7453,7 @@
mStandbyTimeNs = systemTime() + mStandbyDelayNs;
}
-void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
+void DuplicatingThread::threadLoop_sleepTime()
{
if (mSleepTimeUs == 0) {
if (mMixerStatus == MIXER_TRACKS_ENABLED) {
@@ -7457,7 +7473,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);
@@ -7485,7 +7501,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++) {
@@ -7493,7 +7509,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);
@@ -7503,7 +7519,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();
@@ -7518,17 +7534,17 @@
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);
// The downstream MixerThread consumes thread->frameCount() amount of frames per mix pass.
@@ -7547,7 +7563,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,
@@ -7565,7 +7581,7 @@
updateWaitTime_l();
}
-void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
+void DuplicatingThread::removeOutputTrack(IAfPlaybackThread* thread)
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mOutputTracks.size(); i++) {
@@ -7583,11 +7599,11 @@
}
// caller must hold mLock
-void AudioFlinger::DuplicatingThread::updateWaitTime_l()
+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) {
@@ -7597,18 +7613,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;
@@ -7617,7 +7633,7 @@
return true;
}
-void AudioFlinger::DuplicatingThread::sendMetadataToBackend_l(
+void DuplicatingThread::sendMetadataToBackend_l(
const StreamOutHalInterface::SourceMetadata& metadata)
{
for (auto& outputTrack : outputTracks) { // not mOutputTracks
@@ -7625,12 +7641,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();
@@ -7640,16 +7656,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() {
+void SpatializerThread::onFirstRef() {
MixerThread::onFirstRef();
const pid_t tid = getTid();
@@ -7664,7 +7690,7 @@
}
}
-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()) {
@@ -7702,7 +7728,7 @@
}
}
-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;
}
@@ -7711,7 +7737,7 @@
return NO_ERROR;
}
-void AudioFlinger::SpatializerThread::checkOutputStageEffects()
+void SpatializerThread::checkOutputStageEffects()
{
bool hasVirtualizer = false;
bool hasDownMixer = false;
@@ -7736,7 +7762,7 @@
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;
@@ -7767,12 +7793,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),
@@ -7793,7 +7826,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(
@@ -7901,7 +7934,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);
@@ -7926,7 +7960,7 @@
// FIXME mNormalSource
}
-AudioFlinger::RecordThread::~RecordThread()
+RecordThread::~RecordThread()
{
if (mFastCapture != 0) {
FastCaptureStateQueue *sq = mFastCapture->sq();
@@ -7943,36 +7977,36 @@
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);
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();
}
-bool AudioFlinger::RecordThread::threadLoop()
+bool RecordThread::threadLoop()
{
nsecs_t lastWarning = 0;
inputStandBy();
reacquire_wakelock:
- sp<RecordTrack> activeTrack;
+ sp<IAfRecordTrack> activeTrack;
{
Mutex::Autolock _l(mLock);
acquireWakeLock_l();
@@ -7988,13 +8022,13 @@
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;
@@ -8047,40 +8081,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);
@@ -8172,7 +8206,7 @@
}
state->mCommand = FastCaptureState::READ_WRITE;
#if 0 // FIXME
- mFastCaptureDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
+ mFastCaptureDumpState.increaseSamplingN(mAfThreadCallback->isLowRamDevice() ?
FastThreadDumpState::kSamplingNforLowRamDevice :
FastThreadDumpState::kSamplingN);
#endif
@@ -8327,7 +8361,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);
@@ -8384,16 +8418,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;
}
@@ -8407,7 +8441,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
@@ -8415,14 +8449,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",
@@ -8431,9 +8466,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);
}
@@ -8443,17 +8478,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) {
@@ -8482,7 +8518,7 @@
// update frame information and push timestamp out
activeTrack->updateTrackFrameInfo(
- activeTrack->mServerProxy->framesReleased(),
+ activeTrack->serverProxy()->framesReleased(),
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER],
mSampleRate, mTimestamp);
}
@@ -8515,7 +8551,7 @@
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mTracks.size(); i++) {
- sp<RecordTrack> track = mTracks[i];
+ sp<IAfRecordTrack> track = mTracks[i];
track->invalidate();
}
mActiveTracks.clear();
@@ -8528,7 +8564,7 @@
return false;
}
-void AudioFlinger::RecordThread::standbyIfNotAlreadyInStandby()
+void RecordThread::standbyIfNotAlreadyInStandby()
{
if (!mStandby) {
inputStandBy();
@@ -8538,7 +8574,7 @@
}
}
-void AudioFlinger::RecordThread::inputStandBy()
+void RecordThread::inputStandBy()
{
// Idle the fast capture if it's currently running
if (mFastCapture != 0) {
@@ -8579,7 +8615,7 @@
}
// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
+sp<IAfRecordTrack> RecordThread::createRecordTrack_l(
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
@@ -8598,7 +8634,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;
@@ -8744,10 +8780,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();
@@ -8777,7 +8813,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)
{
@@ -8788,8 +8824,8 @@
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));
}
@@ -8803,13 +8839,13 @@
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;
}
@@ -8817,7 +8853,7 @@
// 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();
@@ -8825,16 +8861,16 @@
mLock.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();
@@ -8861,67 +8897,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();
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 = std::any_cast<const wp<RefBase>>(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);
// 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()) {
+ while (recordTrack->state() == IAfTrackBase::PAUSING && !recordTrack->isInvalid()) {
mWaitWorkCV.broadcast(); // signal thread to stop
mStartStopCond.wait(mLock);
}
- 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)) {
@@ -8934,7 +8969,7 @@
Mutex::Autolock _l(mLock);
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;
@@ -8946,8 +8981,8 @@
#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);
@@ -8958,7 +8993,7 @@
return status;
}
-status_t AudioFlinger::RecordThread::setPreferredMicrophoneDirection(
+status_t RecordThread::setPreferredMicrophoneDirection(
audio_microphone_direction_t direction)
{
ALOGV("setPreferredMicrophoneDirection(%d)", direction);
@@ -8969,7 +9004,7 @@
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);
@@ -8979,14 +9014,14 @@
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);
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) {
@@ -9026,20 +9061,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);
@@ -9049,10 +9084,10 @@
}
// destroyTrack_l() must be called with ThreadBase::mLock held
-void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track)
+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) {
@@ -9060,7 +9095,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 */);
@@ -9074,7 +9109,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;
@@ -9102,7 +9137,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();
@@ -9115,7 +9150,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) {
@@ -9135,7 +9170,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 */);
@@ -9146,21 +9181,21 @@
write(fd, result.string(), 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);
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;
@@ -9180,11 +9215,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);
@@ -9214,16 +9249,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);
@@ -9257,7 +9292,7 @@
}
// AudioBufferProvider interface
-void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer(
+void ResamplerBufferProvider::releaseBuffer(
AudioBufferProvider::Buffer* buffer)
{
int32_t stepCount = static_cast<int32_t>(buffer->frameCount);
@@ -9271,18 +9306,18 @@
buffer->frameCount = 0;
}
-void AudioFlinger::RecordThread::checkBtNrec()
+void RecordThread::checkBtNrec()
{
Mutex::Autolock _l(mLock);
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());
@@ -9292,7 +9327,7 @@
}
-bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValuePair,
+bool RecordThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
bool reconfig = false;
@@ -9380,7 +9415,7 @@
return reconfig;
}
-String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
+String8 RecordThread::getParameters(const String8& keys)
{
Mutex::Autolock _l(mLock);
if (initCheck() == NO_ERROR) {
@@ -9392,7 +9427,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) {
@@ -9410,10 +9445,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);
@@ -9456,7 +9491,7 @@
.record();
}
-uint32_t AudioFlinger::RecordThread::getInputFramesLost()
+uint32_t RecordThread::getInputFramesLost() const
{
Mutex::Autolock _l(mLock);
uint32_t result;
@@ -9466,12 +9501,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);
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);
@@ -9480,7 +9515,7 @@
return ids;
}
-AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
+AudioStreamIn* RecordThread::clearInput()
{
Mutex::Autolock _l(mLock);
AudioStreamIn *input = mInput;
@@ -9489,7 +9524,7 @@
}
// this method must always be called either with ThreadBase mLock held or inside the thread loop
-sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const
+sp<StreamHalInterface> RecordThread::stream() const
{
if (mInput == NULL) {
return NULL;
@@ -9497,7 +9532,7 @@
return mInput->stream;
}
-status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
+status_t RecordThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
{
ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
chain->setThread(this);
@@ -9515,7 +9550,7 @@
return NO_ERROR;
}
-size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
+size_t RecordThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
{
ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
@@ -9528,7 +9563,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;
@@ -9585,7 +9620,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;
@@ -9604,7 +9639,7 @@
return status;
}
-void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+void RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
{
Mutex::Autolock _l(mLock);
mOutDevices = outDevices;
@@ -9614,7 +9649,7 @@
}
}
-int32_t AudioFlinger::RecordThread::getOldestFront_l()
+int32_t RecordThread::getOldestFront_l()
{
if (mTracks.size() == 0) {
return mRsmpInRear;
@@ -9622,7 +9657,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) {
@@ -9636,19 +9671,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
@@ -9672,7 +9707,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) {
@@ -9741,7 +9776,7 @@
mRsmpInBuffer = rsmpInBuffer;
}
-void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
+void RecordThread::addPatchTrack(const sp<IAfPatchRecord>& record)
{
Mutex::Autolock _l(mLock);
mTracks.add(record);
@@ -9750,7 +9785,7 @@
}
}
-void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
+void RecordThread::deletePatchTrack(const sp<IAfPatchRecord>& record)
{
Mutex::Autolock _l(mLock);
if (mSource == record->getSource()) {
@@ -9759,7 +9794,7 @@
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;
@@ -9775,59 +9810,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),
@@ -9839,25 +9903,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) {
+ 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.
@@ -9869,7 +9929,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,
@@ -9883,7 +9943,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) {
@@ -9893,7 +9953,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;
@@ -9901,7 +9961,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();
@@ -9918,7 +9978,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)
{
@@ -9939,7 +9999,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()) {
@@ -10022,7 +10082,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);
@@ -10034,7 +10095,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();
@@ -10064,7 +10125,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);
@@ -10079,8 +10140,8 @@
Mutex::Autolock _l(mLock);
- 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;
@@ -10118,7 +10179,7 @@
return NO_ERROR;
}
-status_t AudioFlinger::MmapThread::standby()
+status_t MmapThread::standby()
{
ALOGV("%s", __FUNCTION__);
@@ -10138,12 +10199,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);
@@ -10179,7 +10240,7 @@
.record();
}
-bool AudioFlinger::MmapThread::threadLoop()
+bool MmapThread::threadLoop()
{
checkSilentMode_l();
@@ -10250,7 +10311,7 @@
}
// checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MmapThread::checkForNewParameter_l(const String8& keyValuePair,
+bool MmapThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
AudioParameter param = AudioParameter(keyValuePair);
@@ -10268,7 +10329,7 @@
return false;
}
-String8 AudioFlinger::MmapThread::getParameters(const String8& keys)
+String8 MmapThread::getParameters(const String8& keys)
{
Mutex::Autolock _l(mLock);
String8 out_s8;
@@ -10278,7 +10339,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;
@@ -10300,10 +10361,10 @@
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
{
@@ -10394,7 +10455,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;
@@ -10416,7 +10477,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()) {
@@ -10430,14 +10491,14 @@
}
}
-status_t AudioFlinger::MmapThread::addEffectChain_l(const sp<IAfEffectChain>& 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();
@@ -10454,7 +10515,7 @@
return NO_ERROR;
}
-size_t AudioFlinger::MmapThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
+size_t MmapThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
{
audio_session_t session = chain->sessionId();
@@ -10465,7 +10526,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();
@@ -10477,29 +10538,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
@@ -10533,11 +10594,11 @@
return NO_ERROR;
}
-void AudioFlinger::MmapThread::checkInvalidTracks_l()
+void MmapThread::checkInvalidTracks_l()
NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
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) {
@@ -10554,7 +10615,7 @@
}
}
-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);
@@ -10564,7 +10625,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();
@@ -10574,7 +10635,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 */);
}
@@ -10584,10 +10645,17 @@
write(fd, result.string(), 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),
@@ -10595,8 +10663,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;
@@ -10608,7 +10676,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,
@@ -10619,7 +10687,7 @@
mStreamType = streamType;
}
-AudioStreamOut* AudioFlinger::MmapPlaybackThread::clearOutput()
+AudioStreamOut* MmapPlaybackThread::clearOutput()
{
Mutex::Autolock _l(mLock);
AudioStreamOut *output = mOutput;
@@ -10627,7 +10695,7 @@
return output;
}
-void AudioFlinger::MmapPlaybackThread::setMasterVolume(float value)
+void MmapPlaybackThread::setMasterVolume(float value)
{
Mutex::Autolock _l(mLock);
// Don't apply master volume in SW if our HAL can do it for us.
@@ -10639,7 +10707,7 @@
}
}
-void AudioFlinger::MmapPlaybackThread::setMasterMute(bool muted)
+void MmapPlaybackThread::setMasterMute(bool muted)
{
Mutex::Autolock _l(mLock);
// Don't apply master mute in SW if our HAL can do it for us.
@@ -10650,7 +10718,7 @@
}
}
-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);
if (stream == mStreamType) {
@@ -10659,7 +10727,7 @@
}
}
-float AudioFlinger::MmapPlaybackThread::streamVolume(audio_stream_type_t stream) const
+float MmapPlaybackThread::streamVolume(audio_stream_type_t stream) const
{
Mutex::Autolock _l(mLock);
if (stream == mStreamType) {
@@ -10668,7 +10736,7 @@
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);
if (stream == mStreamType) {
@@ -10677,22 +10745,22 @@
}
}
-void AudioFlinger::MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
{
Mutex::Autolock _l(mLock);
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);
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;
@@ -10707,7 +10775,7 @@
}
}
-void AudioFlinger::MmapPlaybackThread::processVolume_l()
+void MmapPlaybackThread::processVolume_l()
NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
{
float volume;
@@ -10749,9 +10817,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,
@@ -10763,13 +10831,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 = {
@@ -10788,7 +10856,7 @@
return change;
};
-void AudioFlinger::MmapPlaybackThread::checkSilentMode_l()
+void MmapPlaybackThread::checkSilentMode_l()
{
if (!mMasterMute) {
char value[PROPERTY_VALUE_MAX];
@@ -10805,7 +10873,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) {
@@ -10814,8 +10882,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;
@@ -10828,7 +10896,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) {
@@ -10839,7 +10907,7 @@
}
// startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MmapPlaybackThread::startMelComputation_l(
+void MmapPlaybackThread::startMelComputation_l(
const sp<audio_utils::MelProcessor>& processor)
{
ALOGV("%s: starting mel processor for thread %d", __func__, id());
@@ -10853,7 +10921,7 @@
}
// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MmapPlaybackThread::stopMelComputation_l()
+void MmapPlaybackThread::stopMelComputation_l()
{
ALOGV("%s: pausing mel processor for thread %d", __func__, id());
auto melProcessor = mMelProcessor.load();
@@ -10862,7 +10930,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);
@@ -10871,17 +10939,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()
@@ -10892,7 +10967,7 @@
return MmapThread::exitStandby_l();
}
-AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
+AudioStreamIn* MmapCaptureThread::clearInput()
{
Mutex::Autolock _l(mLock);
AudioStreamIn *input = mInput;
@@ -10900,8 +10975,7 @@
return input;
}
-
-void AudioFlinger::MmapCaptureThread::processVolume_l()
+void MmapCaptureThread::processVolume_l()
{
bool changed = false;
bool silenced = false;
@@ -10928,13 +11002,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 = {
@@ -10951,7 +11025,7 @@
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);
for (size_t i = 0; i < mActiveTracks.size() ; i++) {
@@ -10963,7 +11037,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) {
@@ -10972,8 +11046,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;
@@ -10983,12 +11057,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;
@@ -11020,7 +11101,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 a5c1048..902806d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -15,38 +15,24 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
-public: // TODO(b/288339104) extract out of AudioFlinger class
-class ThreadBase : public Thread {
+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 {
@@ -90,8 +76,6 @@
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) {
@@ -135,7 +119,6 @@
ConfigEvent(CFG_EVENT_IO) {
mData = new IoConfigEventData(event, pid, portId);
}
- virtual ~IoConfigEvent() {}
};
class PrioConfigEventData : public ConfigEventData {
@@ -160,7 +143,6 @@
ConfigEvent(CFG_EVENT_PRIO, true) {
mData = new PrioConfigEventData(pid, tid, prio, forApp);
}
- virtual ~PrioConfigEvent() {}
};
class SetParameterConfigEventData : public ConfigEventData {
@@ -182,7 +164,6 @@
mData = new SetParameterConfigEventData(keyValuePairs);
mWaitStatus = true;
}
- virtual ~SetParameterConfigEvent() {}
};
class CreateAudioPatchConfigEventData : public ConfigEventData {
@@ -207,7 +188,6 @@
mData = new CreateAudioPatchConfigEventData(patch, handle);
mWaitStatus = true;
}
- virtual ~CreateAudioPatchConfigEvent() {}
};
class ReleaseAudioPatchConfigEventData : public ConfigEventData {
@@ -229,7 +209,6 @@
mData = new ReleaseAudioPatchConfigEventData(handle);
mWaitStatus = true;
}
- virtual ~ReleaseAudioPatchConfigEvent() {}
};
class UpdateOutDevicesConfigEventData : public ConfigEventData {
@@ -250,8 +229,6 @@
ConfigEvent(CFG_EVENT_UPDATE_OUT_DEVICE) {
mData = new UpdateOutDevicesConfigEventData(outDevices);
}
-
- virtual ~UpdateOutDevicesConfigEvent();
};
class ResizeBufferConfigEventData : public ConfigEventData {
@@ -272,8 +249,6 @@
ConfigEvent(CFG_EVENT_RESIZE_BUFFER) {
mData = new ResizeBufferConfigEventData(maxSharedAudioHistoryMs);
}
-
- virtual ~ResizeBufferConfigEvent() {}
};
class CheckOutputStageEffectsEvent : public ConfigEvent {
@@ -281,8 +256,6 @@
CheckOutputStageEffectsEvent() :
ConfigEvent(CFG_EVENT_CHECK_OUTPUT_STAGE_EFFECTS) {
}
-
- virtual ~CheckOutputStageEffectsEvent() {}
};
class HalLatencyModesChangedEvent : public ConfigEvent {
@@ -290,8 +263,6 @@
HalLatencyModesChangedEvent() :
ConfigEvent(CFG_EVENT_HAL_LATENCY_MODES_CHANGED) {
}
-
- virtual ~HalLatencyModesChangedEvent() {}
};
@@ -309,108 +280,87 @@
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;
+ void exit() final;
+ status_t setParameters(const String8& keyValuePairs) final;
+
// 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);
- 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<IAfEffectHandle> createEffect_l(
+ sp<IAfEffectHandle> createEffect_l(
const sp<Client>& client,
const sp<media::IEffectClient>& effectClient,
int32_t priority,
@@ -420,7 +370,7 @@
status_t *status /*non-NULL*/,
bool pinned,
bool probe,
- bool notifyFramesProcessed);
+ bool notifyFramesProcessed) final;
// return values for hasAudioSession (bit field)
enum effect_state {
@@ -436,47 +386,40 @@
// bit-perfect track
};
- // get effect chain corresponding to session Id.
- sp<IAfEffectChain> getEffectChain(audio_session_t sessionId);
- // same as getEffectChain() but must be called with ThreadBase mutex locked
- sp<IAfEffectChain> 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<IAfEffectChain>& chain) = 0;
- // remove an effect chain from the chain list (mEffectChains)
- virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& 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<IAfEffectChain>>& effectChains);
+ void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) final;
// unlock effect chains after process
- void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains);
+ void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) final;
// get a copy of mEffectChains vector
- Vector<sp<IAfEffectChain>> 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<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId);
- sp<IAfEffectModule> 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<IAfEffectModule>& effect);
+ status_t addEffect_l(const sp<IAfEffectModule>& effect) final;
// remove and effect module. Also removes the effect chain is this was the last
// effect
- void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false);
+ 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(IAfEffectHandle *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 {
+ 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 {
Mutex::Autolock _l(mLock);
return hasAudioSession_l(sessionId);
}
@@ -488,7 +431,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()) {
@@ -510,19 +453,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,
@@ -530,36 +471,35 @@
// 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;
+ Mutex& mutex() const final {
+ return mLock;
+ }
mutable Mutex mLock;
- void onEffectEnable(const sp<IAfEffectModule>& 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 { }
+ 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 {
+ void invalidateTracksForAudioSession(audio_session_t sessionId) const final {
Mutex::Autolock _l(mLock);
invalidateTracksForAudioSession_l(sessionId);
}
@@ -568,17 +508,15 @@
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;
+ void stopMelComputation_l() override;
protected:
@@ -602,7 +540,7 @@
// 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,
@@ -629,7 +567,7 @@
return INVALID_OPERATION;
}
public:
-// TODO(b/288339104) organize with publics
+// TODO(b/291317898) organize with publics
product_strategy_t getStrategyForStream(audio_stream_type_t stream) const;
protected:
@@ -639,15 +577,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;
- const sp<AudioFlinger> mAudioFlinger;
+ const sp<IAfThreadCallback> mAfThreadCallback;
ThreadMetrics mThreadMetrics;
const bool mIsOut;
@@ -784,7 +719,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 {
@@ -829,8 +764,6 @@
return wakeLockUids; // moved by underlying SharedBuffer
}
- std::map<uid_t, std::pair<ssize_t /* previous */, ssize_t /* current */>>
- mBatteryCounter;
SortedVector<sp<T>> mActiveTracks;
int mActiveTracksGeneration;
int mLastActiveTracksGeneration;
@@ -847,35 +780,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
@@ -883,7 +795,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;
@@ -893,19 +804,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()
@@ -915,14 +830,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
@@ -930,18 +845,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();
@@ -956,29 +874,28 @@
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(
+ sp<IAfTrack> createTrack_l(
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
@@ -999,15 +916,20 @@
audio_port_handle_t portId,
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
- bool isBitPerfect);
+ bool isBitPerfect) final;
- 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
@@ -1015,123 +937,127 @@
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<IAfEffectChain>& chain);
- virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& 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) {
+ void setDownStreamPatch(const struct audio_patch* patch) final {
Mutex::Autolock _l(mLock);
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;
+ void stopMelComputation_l() override;
- void setStandby() {
+ void setStandby() final {
Mutex::Autolock _l(mLock);
setStandby_l();
}
- void setStandby_l() {
+ void setStandby_l() final {
mStandby = true;
mHalStarted = false;
mKernelPositionOnStandby =
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
}
- bool waitForHalStart() {
+ bool waitForHalStart() final {
Mutex::Autolock _l(mLock);
static const nsecs_t kWaitHalTimeoutNs = seconds(2);
nsecs_t endWaitTimetNs = systemTime() + kWaitHalTimeoutNs;
@@ -1246,7 +1172,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.
@@ -1260,8 +1185,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
@@ -1271,7 +1195,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() { }
@@ -1289,26 +1213,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;
@@ -1366,9 +1287,10 @@
SortedVector<sp<T>> mTracks; // wrapped SortedVector.
};
- Tracks<Track> mTracks;
+ Tracks<IAfTrack> mTracks;
stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
+
AudioStreamOut *mOutput;
float mMasterVolume;
@@ -1423,19 +1345,20 @@
// 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;
// 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;
@@ -1453,14 +1376,14 @@
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;
@@ -1511,36 +1434,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(
@@ -1551,15 +1473,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
@@ -1635,17 +1557,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
@@ -1665,7 +1591,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();
@@ -1678,16 +1604,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;
@@ -1719,7 +1645,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() {};
@@ -1727,7 +1653,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();
@@ -1745,11 +1671,8 @@
class AsyncCallbackThread : public Thread {
public:
-
explicit AsyncCallbackThread(const wp<PlaybackThread>& playbackThread);
- virtual ~AsyncCallbackThread();
-
// Thread virtuals
virtual bool threadLoop();
@@ -1778,16 +1701,21 @@
bool mAsyncError;
};
-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;
@@ -1814,8 +1742,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(
@@ -1838,23 +1766,22 @@
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();
+ void onFirstRef() final;
- 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
@@ -1864,83 +1791,39 @@
};
// 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(
+ sp<IAfRecordTrack> createRecordTrack_l(
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
@@ -1955,17 +1838,19 @@
pid_t tid,
status_t *status /*non-NULL*/,
audio_port_handle_t portId,
- int32_t maxSharedAudioHistoryMs);
+ int32_t maxSharedAudioHistoryMs) final;
- 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;
@@ -1973,19 +1858,19 @@
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<IAfEffectChain>& chain);
virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain);
@@ -2004,7 +1889,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,
@@ -2015,20 +1900,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.
@@ -2038,15 +1923,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);
}
@@ -2068,10 +1953,10 @@
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;
+ ActiveTracks<IAfRecordTrack> mActiveTracks;
Condition mStartStopCond;
@@ -2138,90 +2023,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(mLock);
- 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<IAfEffectChain>& chain);
- virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& 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;
@@ -2244,8 +2124,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
@@ -2260,7 +2140,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;
@@ -2268,56 +2148,59 @@
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;
+ void stopMelComputation_l() final;
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;
@@ -2329,28 +2212,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(mLock) 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);
}
@@ -2361,12 +2245,12 @@
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;
@@ -2374,4 +2258,4 @@
float mVolumeRight = 0.f;
};
-private:
+} // namespace android
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index d5b6a98..5708c61 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,26 @@
* 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(); }
+
+ /**
+ * Called when a track moves to active state to record its contribution to battery usage.
+ * Track state transitions should eventually be handled within the track class.
+ */
+ void beginBatteryAttribution() final {
+ mBatteryStatsHolder.emplace(uid());
+ }
+
+ /**
+ * Called when a track moves out of the active state to record its contribution
+ * to battery usage.
+ */
+ void endBatteryAttribution() final {
+ mBatteryStatsHolder.reset();
+ }
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -285,31 +267,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 +333,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;
@@ -413,39 +395,32 @@
// If the last track change was notified to the client with readAndClearHasChanged
std::atomic_flag mChangeNotified = ATOMIC_FLAG_INIT;
+ // RAII object for battery stats book-keeping
+ std::optional<mediautils::BatteryStatsAudioHandle> mBatteryStatsHolder;
};
-// 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 +428,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 9ec3ee3..ecea9eb 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);
+ Mutex::Autolock _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;
}
@@ -339,7 +343,7 @@
class TrackHandle : public android::media::BnAudioTrack {
public:
- explicit TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track);
+ explicit TrackHandle(const sp<IAfTrack>& track);
~TrackHandle() override;
binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
@@ -373,20 +377,18 @@
const media::audio::common::AudioPlaybackRate& playbackRate) final;
private:
- const sp<AudioFlinger::PlaybackThread::Track> mTrack;
+ const sp<IAfTrack> mTrack;
};
/* static */
-sp<media::IAudioTrack> AudioFlinger::PlaybackThread::Track::createIAudioTrackAdapter(
- const sp<Track>& track) {
+sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
return sp<TrackHandle>::make(track);
}
-TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
+TrackHandle::TrackHandle(const sp<IAfTrack>& track)
: BnAudioTrack(),
mTrack(track)
{
- // TODO(b/288339104) binder thread priority change not needed.
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
@@ -556,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)
{
@@ -588,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),
@@ -601,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);
@@ -609,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
@@ -621,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(
@@ -640,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);
+ Mutex::Autolock _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);
@@ -667,7 +667,7 @@
}
// static
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::getPackagesForUid(
+void OpPlayAudioMonitor::getPackagesForUid(
uid_t uid, Vector<String16>& packages)
{
PermissionController permissionController;
@@ -678,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,
@@ -714,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),
@@ -771,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);
@@ -804,7 +852,7 @@
mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
}
-AudioFlinger::PlaybackThread::Track::~Track()
+Track::~Track()
{
ALOGV("%s(%d)", __func__, mId);
@@ -817,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) {
@@ -826,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
@@ -839,20 +887,20 @@
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();
+ Mutex::Autolock _l(thread->mutex());
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
wasActive = playbackThread->destroyTrack_l(this);
+ forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
}
if (isExternalTrack() && !wasActive) {
AudioSystem::releaseOutput(mPortId);
}
}
- 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 "
@@ -863,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) {
@@ -905,7 +953,7 @@
}
char fillingStatus;
- switch (mFillingUpStatus) {
+ switch (mFillingStatus) {
case FS_INVALID:
fillingStatus = 'I';
break;
@@ -991,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;
@@ -1014,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;
@@ -1031,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);
@@ -1052,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.
@@ -1061,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.
@@ -1083,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;
}
@@ -1104,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);
+ Mutex::Autolock _laf(thread->afThreadCallback()->mutex());
+ Mutex::Autolock _lth(thread->mutex());
sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
- if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
+ if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
(ec != 0 && ec->isNonOffloadableEnabled())) {
invalidate();
return PERMISSION_DENIED;
}
}
- Mutex::Autolock _lth(thread->mLock);
+ Mutex::Autolock _lth(thread->mutex());
track_state state = mState;
// here the track could be either new, or restarted
// in both cases "unstop" the track
@@ -1162,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)
@@ -1222,14 +1270,16 @@
buffer.mFrameCount = 1;
(void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
}
+ if (status == NO_ERROR) {
+ forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
+ }
} else {
status = BAD_VALUE;
}
if (status == NO_ERROR) {
- 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>();
@@ -1248,17 +1298,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);
+ Mutex::Autolock _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()) {
@@ -1270,24 +1320,24 @@
// move to STOPPING_2 when drain completes and then STOPPED
mState = STOPPING_1;
if (isOffloaded()) {
- mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload;
+ mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
}
}
playbackThread->broadcast_l();
ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d",
__func__, mId, (int)mThreadIoHandle);
}
+ forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
}
- 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();
+ Mutex::Autolock _l(thread->mutex());
+ auto* const playbackThread = thread->asIAfPlaybackThread().get();
switch (mState) {
case STOPPING_1:
case STOPPING_2:
@@ -1313,23 +1363,23 @@
default:
break;
}
+ // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
+ forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
}
- // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
- 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();
+ Mutex::Autolock _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();
}
@@ -1368,7 +1418,7 @@
if (isDirect()) {
mFlushHwPending = true;
}
- if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+ if (!playbackThread->isTrackActive(this)) {
reset();
}
}
@@ -1376,13 +1426,14 @@
// before mixer thread can run. This is important when offloading
// because the hardware buffer could hold a large amount of audio
playbackThread->broadcast_l();
+ // Flush the Tee to avoid on resume playing old data and glitching on the transition to
+ // new data
+ forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); });
}
- // Flush the Tee to avoid on resume playing old data and glitching on the transition to new data
- forEachTeePatchTrack([](auto patchTrack) { patchTrack->flush(); });
}
// must be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::flushAck()
+void Track::flushAck()
{
if (!isOffloaded() && !isDirect()) {
return;
@@ -1395,12 +1446,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.
@@ -1408,7 +1459,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;
@@ -1416,34 +1467,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)
{
@@ -1451,16 +1503,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);
+ Mutex::Autolock _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.
@@ -1468,7 +1520,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;
@@ -1484,7 +1536,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) {
@@ -1556,26 +1608,26 @@
*backInserter++ = metadata;
}
-void AudioFlinger::PlaybackThread::Track::updateTeePatches() {
+void Track::updateTeePatches_l() {
if (mTeePatchesToUpdate.has_value()) {
- forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
+ forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
mTeePatches = mTeePatchesToUpdate.value();
if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
mState == TrackBase::STOPPING_1) {
- forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+ forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
}
mTeePatchesToUpdate.reset();
}
}
-void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
+void Track::setTeePatchesToUpdate_l(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) {
@@ -1607,31 +1659,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();
+ Mutex::Autolock _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) {
@@ -1647,14 +1700,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.
@@ -1697,7 +1750,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.
@@ -1729,14 +1782,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) {
@@ -1751,7 +1804,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));
@@ -1776,7 +1829,7 @@
return vlr;
}
-status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(
+status_t Track::setSyncEvent(
const sp<audioflinger::SyncEvent>& event)
{
if (isTerminated() || mState == PAUSED ||
@@ -1792,19 +1845,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;
@@ -1814,25 +1867,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();
+ Mutex::Autolock _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();
+ Mutex::Autolock _l(t->mutex());
+ status = t->getOutput_l()->stream->getDualMonoMode(mode);
ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
"%s: mode %d inconsistent", __func__, mDualMonoMode);
}
@@ -1840,15 +1893,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();
+ Mutex::Autolock lock(t->mutex());
+ status = t->getOutput_l()->stream->setDualMonoMode(mode);
if (status == NO_ERROR) {
mDualMonoMode = mode;
}
@@ -1857,15 +1910,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();
+ Mutex::Autolock lock(t->mutex());
+ status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
"%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
}
@@ -1873,15 +1926,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();
+ Mutex::Autolock lock(t->mutex());
+ status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
if (status == NO_ERROR) {
mAudioDescriptionMixLevel = leveldB;
}
@@ -1890,16 +1943,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();
+ Mutex::Autolock lock(t->mutex());
+ status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
ALOGD_IF((status == NO_ERROR) &&
!isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
"%s: playbackRate inconsistent", __func__);
@@ -1908,16 +1961,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();
+ Mutex::Autolock lock(t->mutex());
+ status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
if (status == NO_ERROR) {
mPlaybackRateParameters = playbackRate;
}
@@ -1927,7 +1980,7 @@
}
//To be called with thread lock held
-bool AudioFlinger::PlaybackThread::Track::isResumePending() {
+bool Track::isResumePending() const {
if (mState == RESUMING) {
return true;
}
@@ -1941,7 +1994,7 @@
}
//To be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::resumeAck() {
+void Track::resumeAck() {
if (mState == RESUMING) {
mState = ACTIVE;
}
@@ -1955,7 +2008,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.
@@ -2035,14 +2088,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();
+ Mutex::Autolock _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);
@@ -2052,13 +2105,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();
@@ -2068,9 +2121,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,
@@ -2087,7 +2159,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,
@@ -2105,13 +2177,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);
@@ -2124,7 +2196,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::OutputTrack::stop()
+void OutputTrack::stop()
{
Track::stop();
clearBufferQueue();
@@ -2132,11 +2204,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);
@@ -2154,7 +2226,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();
@@ -2243,8 +2315,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);
}
}
@@ -2258,7 +2330,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;
@@ -2281,13 +2353,13 @@
}
}
-void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
{
std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
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);
mTrackMetadatas = metadatas;
@@ -2296,7 +2368,7 @@
setMetadataHasChanged();
}
-status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
+status_t OutputTrack::obtainBuffer(
AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
{
ClientProxy::Buffer buf;
@@ -2310,7 +2382,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
+void OutputTrack::clearBufferQueue()
{
size_t size = mBufferQueue.size();
@@ -2322,7 +2394,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)) {
@@ -2334,7 +2406,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,
@@ -2353,7 +2456,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,
@@ -2361,12 +2464,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();
@@ -2375,7 +2478,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);
@@ -2387,7 +2490,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);
@@ -2413,7 +2516,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;
@@ -2423,7 +2526,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;
@@ -2440,7 +2543,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
+void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
{
mProxy->releaseBuffer(buffer);
restartIfDisabled();
@@ -2449,23 +2552,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);
@@ -2483,7 +2586,7 @@
class RecordHandle : public android::media::BnAudioRecord {
public:
- explicit RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack);
+ explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
~RecordHandle() override;
binder::Status start(int /*AudioSystem::sync_event_t*/ event,
int /*audio_session_t*/ triggerSession) final;
@@ -2497,24 +2600,23 @@
const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
private:
- const sp<AudioFlinger::RecordThread::RecordTrack> mRecordTrack;
+ const sp<IAfRecordTrack> mRecordTrack;
// for use from destructor
void stop_nonvirtual();
};
/* static */
-sp<media::IAudioRecord> AudioFlinger::RecordThread::RecordTrack::createIAudioRecordAdapter(
- const sp<RecordTrack>& recordTrack) {
+sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
+ const sp<IAfRecordTrack>& recordTrack) {
return sp<RecordHandle>::make(recordTrack);
}
RecordHandle::RecordHandle(
- const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
+ const sp<IAfRecordTrack>& recordTrack)
: BnAudioRecord(),
mRecordTrack(recordTrack)
{
- // TODO(b/288339104) binder thread priority change not needed.
setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}
@@ -2568,9 +2670,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,
@@ -2609,7 +2749,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.
@@ -2629,8 +2769,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);
@@ -2645,14 +2785,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) {
@@ -2662,7 +2802,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;
@@ -2676,12 +2816,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());
@@ -2689,27 +2829,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();
+ Mutex::Autolock _l(thread->mutex());
+ auto* const recordThread = thread->asIAfRecordThread().get();
priorState = mState;
if (!mSharedAudioPackageName.empty()) {
recordThread->resetAudioHistory_l();
@@ -2740,7 +2880,7 @@
}
}
-void AudioFlinger::RecordThread::RecordTrack::invalidate()
+void RecordTrack::invalidate()
{
TrackBase::invalidate();
// FIXME should use proxy, and needs work
@@ -2752,7 +2892,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 "
@@ -2760,7 +2900,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 "
@@ -2799,26 +2939,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)
{
@@ -2858,40 +2998,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();
@@ -2908,9 +3048,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) {
@@ -2922,7 +3062,7 @@
}
}
-void AudioFlinger::RecordThread::RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
{
// Do not forward PatchRecord metadata with unspecified audio source
@@ -2946,7 +3086,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,
@@ -2963,7 +3129,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,
@@ -2971,7 +3137,7 @@
(int)(mPeerTimeout.tv_nsec / 1000000));
}
-AudioFlinger::RecordThread::PatchRecord::~PatchRecord()
+PatchRecord::~PatchRecord()
{
ALOGV("%s(%d)", __func__, mId);
}
@@ -2995,7 +3161,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);
@@ -3010,7 +3176,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);
@@ -3032,7 +3198,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;
@@ -3042,13 +3208,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);
}
@@ -3063,8 +3229,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,
@@ -3080,18 +3266,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();
+ Mutex::Autolock _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) {
@@ -3109,7 +3295,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.
@@ -3157,7 +3343,7 @@
return result;
}
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
{
if (buffer->mFrameCount <= mUnconsumedFrames) {
mUnconsumedFrames -= buffer->mFrameCount;
@@ -3174,7 +3360,7 @@
// 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);
@@ -3193,15 +3379,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'.
@@ -3213,7 +3399,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;
@@ -3221,7 +3407,7 @@
return NO_ERROR;
}
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(
+void PassthruPatchRecord::releaseBuffer(
AudioBufferProvider::Buffer* buffer)
{
buffer->frameCount = 0;
@@ -3232,7 +3418,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,
@@ -3258,27 +3469,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;
@@ -3286,21 +3497,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
@@ -3331,13 +3541,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..b5131eb 100644
--- a/services/audioflinger/afutils/Android.bp
+++ b/services/audioflinger/afutils/Android.bp
@@ -39,13 +39,17 @@
"AudioWatchdog.cpp",
"BufLog.cpp",
"NBAIO_Tee.cpp",
+ "Permission.cpp",
"PropertyUtils.cpp",
"TypedLogger.cpp",
],
shared_libs: [
+ "framework-permission-aidl-cpp",
+ "libaudioclient_aidl_conversion",
"libaudioutils",
"libbase",
+ "libbinder",
"libcutils", // property_get_int32
"liblog",
"libnbaio",
diff --git a/services/audioflinger/afutils/DumpTryLock.h b/services/audioflinger/afutils/DumpTryLock.h
new file mode 100644
index 0000000..c185a68
--- /dev/null
+++ b/services/audioflinger/afutils/DumpTryLock.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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 <utils/Mutex.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;
+}
+
+} // android::afutils
\ No newline at end of file
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/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/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 21f346e..97470a2 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -301,6 +301,25 @@
return binder::Status::ok();
}
+binder::Status SoundDoseManager::SoundDose::initCachedAudioDeviceCategories(
+ const std::vector<media::ISoundDose::AudioDeviceCategory>& btDeviceCategories) {
+ ALOGV("%s", __func__);
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager != nullptr) {
+ soundDoseManager->initCachedAudioDeviceCategories(btDeviceCategories);
+ }
+ return binder::Status::ok();
+}
+binder::Status SoundDoseManager::SoundDose::setAudioDeviceCategory(
+ const media::ISoundDose::AudioDeviceCategory& btAudioDevice) {
+ ALOGV("%s", __func__);
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager != nullptr) {
+ soundDoseManager->setAudioDeviceCategory(btAudioDevice);
+ }
+ return binder::Status::ok();
+}
+
binder::Status SoundDoseManager::SoundDose::getOutputRs2UpperBound(float* value) {
ALOGV("%s", __func__);
auto soundDoseManager = mSoundDoseManager.promote();
@@ -358,7 +377,9 @@
auto melProcessor = mp.second.promote();
if (melProcessor != nullptr) {
auto deviceId = melProcessor->getDeviceId();
- if (mActiveDeviceTypes[deviceId] == deviceType) {
+ const auto deviceTypeIt = mActiveDeviceTypes.find(deviceId);
+ if (deviceTypeIt != mActiveDeviceTypes.end() &&
+ deviceTypeIt->second == deviceType) {
ALOGV("%s: set attenuation for deviceId %d to %f",
__func__, deviceId, attenuationDB);
melProcessor->setAttenuation(attenuationDB);
@@ -390,6 +411,103 @@
return mEnabledCsd;
}
+void SoundDoseManager::initCachedAudioDeviceCategories(
+ const std::vector<media::ISoundDose::AudioDeviceCategory>& deviceCategories) {
+ ALOGV("%s", __func__);
+ {
+ const std::lock_guard _l(mLock);
+ mBluetoothDevicesWithCsd.clear();
+ }
+ for (const auto& btDeviceCategory : deviceCategories) {
+ setAudioDeviceCategory(btDeviceCategory);
+ }
+}
+
+void SoundDoseManager::setAudioDeviceCategory(
+ const media::ISoundDose::AudioDeviceCategory& audioDevice) {
+ ALOGV("%s: set BT audio device type with address %s to headphone %d", __func__,
+ audioDevice.address.c_str(), audioDevice.csdCompatible);
+
+ std::vector<audio_port_handle_t> devicesToStart;
+ std::vector<audio_port_handle_t> devicesToStop;
+ {
+ const std::lock_guard _l(mLock);
+ const auto deviceIt = mBluetoothDevicesWithCsd.find(
+ std::make_pair(audioDevice.address,
+ static_cast<audio_devices_t>(audioDevice.internalAudioType)));
+ if (deviceIt != mBluetoothDevicesWithCsd.end()) {
+ deviceIt->second = audioDevice.csdCompatible;
+ } else {
+ mBluetoothDevicesWithCsd.emplace(
+ std::make_pair(audioDevice.address,
+ static_cast<audio_devices_t>(audioDevice.internalAudioType)),
+ audioDevice.csdCompatible);
+ }
+
+ for (const auto &activeDevice: mActiveDevices) {
+ if (activeDevice.first.address() == audioDevice.address &&
+ activeDevice.first.mType ==
+ static_cast<audio_devices_t>(audioDevice.internalAudioType)) {
+ if (audioDevice.csdCompatible) {
+ devicesToStart.push_back(activeDevice.second);
+ } else {
+ devicesToStop.push_back(activeDevice.second);
+ }
+ }
+ }
+ }
+
+ for (const auto& deviceToStart : devicesToStart) {
+ mMelReporterCallback->startMelComputationForDeviceId(deviceToStart);
+ }
+ for (const auto& deviceToStop : devicesToStop) {
+ mMelReporterCallback->stopMelComputationForDeviceId(deviceToStop);
+ }
+}
+
+bool SoundDoseManager::shouldComputeCsdForDeviceType(audio_devices_t device) {
+ if (!isCsdEnabled()) {
+ ALOGV("%s csd is disabled", __func__);
+ return false;
+ }
+ if (forceComputeCsdOnAllDevices()) {
+ return true;
+ }
+
+ switch (device) {
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ // TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets
+ // case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+ case AUDIO_DEVICE_OUT_USB_HEADSET:
+ case AUDIO_DEVICE_OUT_BLE_HEADSET:
+ case AUDIO_DEVICE_OUT_BLE_BROADCAST:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool SoundDoseManager::shouldComputeCsdForDeviceWithAddress(const audio_devices_t type,
+ const std::string& deviceAddress) {
+ if (!isCsdEnabled()) {
+ ALOGV("%s csd is disabled", __func__);
+ return false;
+ }
+ if (forceComputeCsdOnAllDevices()) {
+ return true;
+ }
+
+ if (!audio_is_ble_out_device(type) && !audio_is_a2dp_device(type)) {
+ return shouldComputeCsdForDeviceType(type);
+ }
+
+ const std::lock_guard _l(mLock);
+ const auto deviceIt = mBluetoothDevicesWithCsd.find(std::make_pair(deviceAddress, type));
+ return deviceIt != mBluetoothDevicesWithCsd.end() && deviceIt->second;
+}
+
void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
// invalidate any HAL sound dose interface used
setHalSoundDoseInterface(nullptr);
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index 9ed0661..888561f 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -32,6 +32,15 @@
using aidl::android::hardware::audio::core::sounddose::ISoundDose;
+class IMelReporterCallback : public virtual RefBase {
+public:
+ IMelReporterCallback() {};
+ virtual ~IMelReporterCallback() {};
+
+ virtual void stopMelComputationForDeviceId(audio_port_handle_t deviceId) = 0;
+ virtual void startMelComputationForDeviceId(audio_port_handle_t deviceId) = 0;
+};
+
class SoundDoseManager : public audio_utils::MelProcessor::MelCallback {
public:
/** CSD is computed with a rolling window of 7 days. */
@@ -39,8 +48,9 @@
/** Default RS2 upper bound in dBA as defined in IEC 62368-1 3rd edition. */
static constexpr float kDefaultRs2UpperBound = 100.f;
- SoundDoseManager()
- : mMelAggregator(sp<audio_utils::MelAggregator>::make(kCsdWindowSeconds)),
+ explicit SoundDoseManager(const sp<IMelReporterCallback>& melReporterCallback)
+ : mMelReporterCallback(melReporterCallback),
+ mMelAggregator(sp<audio_utils::MelAggregator>::make(kCsdWindowSeconds)),
mRs2UpperBound(kDefaultRs2UpperBound) {};
/**
@@ -104,6 +114,21 @@
/** Returns true if CSD is enabled. */
bool isCsdEnabled();
+ void initCachedAudioDeviceCategories(
+ const std::vector<media::ISoundDose::AudioDeviceCategory>& deviceCategories);
+
+ void setAudioDeviceCategory(
+ const media::ISoundDose::AudioDeviceCategory& audioDevice);
+
+ /**
+ * Returns true if the type can compute CSD. For bluetooth devices we rely on whether we
+ * categorized the address as headphones/headsets, only in this case we return true.
+ */
+ bool shouldComputeCsdForDeviceWithAddress(const audio_devices_t type,
+ const std::string& deviceAddress);
+ /** Returns true for all device types which could support CSD computation. */
+ bool shouldComputeCsdForDeviceType(audio_devices_t device);
+
std::string dump() const;
// used for testing only
@@ -139,6 +164,13 @@
binder::Status getOutputRs2UpperBound(float* value) override;
binder::Status setCsdEnabled(bool enabled) override;
+ binder::Status initCachedAudioDeviceCategories(
+ const std::vector<media::ISoundDose::AudioDeviceCategory> &btDeviceCategories)
+ override;
+
+ binder::Status setAudioDeviceCategory(
+ const media::ISoundDose::AudioDeviceCategory& btAudioDevice) override;
+
binder::Status getCsd(float* value) override;
binder::Status forceUseFrameworkMel(bool useFrameworkMel) override;
binder::Status forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices) override;
@@ -179,6 +211,8 @@
mutable std::mutex mLock;
+ const sp<IMelReporterCallback> mMelReporterCallback;
+
// no need for lock since MelAggregator is thread-safe
const sp<audio_utils::MelAggregator> mMelAggregator;
@@ -191,6 +225,17 @@
std::map<AudioDeviceTypeAddr, audio_port_handle_t> mActiveDevices GUARDED_BY(mLock);
std::unordered_map<audio_port_handle_t, audio_devices_t> mActiveDeviceTypes GUARDED_BY(mLock);
+ struct bt_device_type_hash {
+ std::size_t operator() (const std::pair<std::string, audio_devices_t> &deviceType) const {
+ return std::hash<std::string>()(deviceType.first) ^
+ std::hash<audio_devices_t>()(deviceType.second);
+ }
+ };
+ // storing the BT cached information as received from the java side
+ // see SoundDoseManager::setCachedAudioDeviceCategories
+ std::unordered_map<std::pair<std::string, audio_devices_t>, bool, bt_device_type_hash>
+ mBluetoothDevicesWithCsd GUARDED_BY(mLock);
+
float mRs2UpperBound GUARDED_BY(mLock);
std::unordered_map<audio_devices_t, float> mMelAttenuationDB GUARDED_BY(mLock);
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
index 9fab77d..7d0b3a7 100644
--- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -39,10 +39,18 @@
(const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>&), (override));
};
+class MelReporterCallback : public IMelReporterCallback {
+public:
+ MOCK_METHOD(void, startMelComputationForDeviceId, (audio_port_handle_t), (override));
+ MOCK_METHOD(void, stopMelComputationForDeviceId, (audio_port_handle_t), (override));
+};
+
+
class SoundDoseManagerTest : public ::testing::Test {
protected:
void SetUp() override {
- mSoundDoseManager = sp<SoundDoseManager>::make();
+ mMelReporterCallback = sp<MelReporterCallback>::make();
+ mSoundDoseManager = sp<SoundDoseManager>::make(mMelReporterCallback);
mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound)
@@ -52,6 +60,7 @@
});
}
+ sp<MelReporterCallback> mMelReporterCallback;
sp<SoundDoseManager> mSoundDoseManager;
std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
};
@@ -243,5 +252,53 @@
EXPECT_TRUE(mSoundDoseManager->forceUseFrameworkMel());
}
+TEST_F(SoundDoseManagerTest, SetAudioDeviceCategoryStopsNonHeadphone) {
+ media::ISoundDose::AudioDeviceCategory device1;
+ device1.address = "dev1";
+ device1.csdCompatible = false;
+ device1.internalAudioType = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ const AudioDeviceTypeAddr dev1Adt{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, device1.address};
+
+ // this will mark the device as active
+ mSoundDoseManager->mapAddressToDeviceId(dev1Adt, /*deviceId=*/1);
+ EXPECT_CALL(*mMelReporterCallback.get(), stopMelComputationForDeviceId).Times(1);
+
+ mSoundDoseManager->setAudioDeviceCategory(device1);
+}
+
+TEST_F(SoundDoseManagerTest, SetAudioDeviceCategoryStartsHeadphone) {
+ media::ISoundDose::AudioDeviceCategory device1;
+ device1.address = "dev1";
+ device1.csdCompatible = true;
+ device1.internalAudioType = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ const AudioDeviceTypeAddr dev1Adt{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, device1.address};
+
+ // this will mark the device as active
+ mSoundDoseManager->mapAddressToDeviceId(dev1Adt, /*deviceId=*/1);
+ EXPECT_CALL(*mMelReporterCallback.get(), startMelComputationForDeviceId).Times(1);
+
+ mSoundDoseManager->setAudioDeviceCategory(device1);
+}
+
+TEST_F(SoundDoseManagerTest, InitCachedAudioDevicesStartsOnlyActiveDevices) {
+ media::ISoundDose::AudioDeviceCategory device1;
+ media::ISoundDose::AudioDeviceCategory device2;
+ device1.address = "dev1";
+ device1.csdCompatible = true;
+ device1.internalAudioType = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ device2.address = "dev2";
+ device2.csdCompatible = true;
+ device2.internalAudioType = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ const AudioDeviceTypeAddr dev1Adt{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, device1.address};
+ std::vector<media::ISoundDose::AudioDeviceCategory> btDevices = {device1, device2};
+
+ // this will mark the device as active
+ mSoundDoseManager->mapAddressToDeviceId(dev1Adt, /*deviceId=*/1);
+ EXPECT_CALL(*mMelReporterCallback.get(), startMelComputationForDeviceId).Times(1);
+
+ mSoundDoseManager->initCachedAudioDeviceCategories(btDevices);
+}
+
+
} // namespace
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 876911d..1e57edd 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -102,9 +102,13 @@
void setVolume(float volumeDb) { mCurVolumeDb = volumeDb; }
float getVolume() const { return mCurVolumeDb; }
+ void setIsVoice(bool isVoice) { mIsVoice = isVoice; }
+ bool isVoice() const { return mIsVoice; }
+
private:
int mMuteCount = 0; /**< mute request counter */
float mCurVolumeDb = NAN; /**< current volume in dB. */
+ bool mIsVoice = false; /** true if this volume source is used for voice call volume */
};
/**
* Note: volume activities shall be indexed by CurvesId if we want to allow multiple
@@ -162,7 +166,8 @@
VolumeSource volumeSource, const StreamTypeVector &streams,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
- bool force);
+ bool force,
+ bool isVoiceVolSrc = false);
/**
* @brief setStopTime set the stop time due to the client stoppage or a re routing of this
@@ -222,17 +227,25 @@
{
return mVolumeActivities[vs].decMuteCount();
}
- void setCurVolume(VolumeSource vs, float volumeDb)
+ void setCurVolume(VolumeSource vs, float volumeDb, bool isVoiceVolSrc)
{
// Even if not activity for this source registered, need to create anyway
mVolumeActivities[vs].setVolume(volumeDb);
+ mVolumeActivities[vs].setIsVoice(isVoiceVolSrc);
}
float getCurVolume(VolumeSource vs) const
{
return mVolumeActivities.find(vs) != std::end(mVolumeActivities) ?
mVolumeActivities.at(vs).getVolume() : NAN;
}
-
+ VolumeSource getVoiceSource() {
+ for (const auto &iter : mVolumeActivities) {
+ if (iter.second.isVoice()) {
+ return iter.first;
+ }
+ }
+ return VOLUME_SOURCE_NONE;
+ }
bool isStrategyActive(product_strategy_t ps, uint32_t inPastMs = 0, nsecs_t sysTime = 0) const
{
return mRoutingActivities.find(ps) != std::end(mRoutingActivities)?
@@ -381,7 +394,8 @@
VolumeSource volumeSource, const StreamTypeVector &streams,
const DeviceTypeSet& device,
uint32_t delayMs,
- bool force);
+ bool force,
+ bool isVoiceVolSrc = false);
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
@@ -424,6 +438,15 @@
bool supportsAllDevices(const DeviceVector &devices) const;
/**
+ * @brief supportsAtLeastOne checks if any device in devices is currently supported
+ * @param devices to be checked against
+ * @return true if the device is weakly supported by type (e.g. for non bus / rsubmix devices),
+ * true if the device is supported (both type and address) for bus / remote submix
+ * false otherwise
+ */
+ bool supportsAtLeastOne(const DeviceVector &devices) const;
+
+ /**
* @brief supportsDevicesForPlayback
* @param devices to be checked against
* @return true if the devices is a supported combo for playback
@@ -475,7 +498,8 @@
VolumeSource volumeSource, const StreamTypeVector &streams,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
- bool force);
+ bool force,
+ bool isVoiceVolSrc = false);
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 92292e1..7e29e10 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -138,7 +138,7 @@
*/
status_t setUserIdDeviceAffinities(int userId, const AudioDeviceTypeAddrVector& devices);
status_t removeUserIdDeviceAffinities(int userId);
- status_t getDevicesForUserId(int userId, Vector<AudioDeviceTypeAddr>& devices) const;
+ status_t getDevicesForUserId(int userId, AudioDeviceTypeAddrVector& devices) const;
void dump(String8 *dst) const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 4877166..2f424b8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -163,7 +163,8 @@
const StreamTypeVector &/*streams*/,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
- bool force)
+ bool force,
+ bool isVoiceVolSrc)
{
if (!supportedDevices().containsDeviceAmongTypes(deviceTypes)) {
@@ -176,7 +177,7 @@
// - the force flag is set
if (volumeDb != getCurVolume(volumeSource) || force) {
ALOGV("%s for volumeSrc %d, volume %f, delay %d", __func__, volumeSource, volumeDb, delayMs);
- setCurVolume(volumeSource, volumeDb);
+ setCurVolume(volumeSource, volumeDb, isVoiceVolSrc);
return true;
}
return false;
@@ -389,6 +390,11 @@
return supportedDevices().containsAllDevices(devices);
}
+bool SwAudioOutputDescriptor::supportsAtLeastOne(const DeviceVector &devices) const
+{
+ return filterSupportedDevices(devices).size() > 0;
+}
+
bool SwAudioOutputDescriptor::supportsDevicesForPlayback(const DeviceVector &devices) const
{
// No considering duplicated output
@@ -505,11 +511,12 @@
VolumeSource vs, const StreamTypeVector &streamTypes,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
- bool force)
+ bool force,
+ bool isVoiceVolSrc)
{
StreamTypeVector streams = streamTypes;
if (!AudioOutputDescriptor::setVolume(
- volumeDb, muted, vs, streamTypes, deviceTypes, delayMs, force)) {
+ volumeDb, muted, vs, streamTypes, deviceTypes, delayMs, force, isVoiceVolSrc)) {
return false;
}
if (streams.empty()) {
@@ -555,6 +562,10 @@
float volumeAmpl = Volume::DbToAmpl(getCurVolume(vs));
if (hasStream(streams, AUDIO_STREAM_BLUETOOTH_SCO)) {
mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle, delayMs);
+ VolumeSource callVolSrc = getVoiceSource();
+ if (callVolSrc != VOLUME_SOURCE_NONE) {
+ setCurVolume(callVolSrc, getCurVolume(vs), true);
+ }
}
for (const auto &stream : streams) {
ALOGV("%s output %d for volumeSource %d, volume %f, delay %d stream=%s", __func__,
@@ -783,10 +794,11 @@
VolumeSource volumeSource, const StreamTypeVector &streams,
const DeviceTypeSet& deviceTypes,
uint32_t delayMs,
- bool force)
+ bool force,
+ bool isVoiceVolSrc)
{
bool changed = AudioOutputDescriptor::setVolume(
- volumeDb, muted, volumeSource, streams, deviceTypes, delayMs, force);
+ volumeDb, muted, volumeSource, streams, deviceTypes, delayMs, force, isVoiceVolSrc);
if (changed) {
// TODO: use gain controller on source device if any to adjust volume
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 6b9757d..bc2ba31 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -642,7 +642,7 @@
}
status_t AudioPolicyMixCollection::getDevicesForUserId(int userId,
- Vector<AudioDeviceTypeAddr>& devices) const {
+ AudioDeviceTypeAddrVector& devices) const {
// for each player mix:
// find rules that don't exclude this userId, and add the device to the list
for (size_t i = 0; i < size(); i++) {
@@ -660,7 +660,7 @@
}
}
if (ruleAllowsUserId) {
- devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
+ devices.push_back(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
}
}
return NO_ERROR;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp
index 8ccb8b9..82f51ad 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp
@@ -115,12 +115,22 @@
profile->setDynamicFormat(true);
profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels());
profile->setDynamicRate(dynamicFormatProfile->isDynamicRate());
- addAudioProfileAndSort(audioProfileVector, profile);
+ size_t profileIndex = 0;
+ for (; profileIndex < audioProfileVector.size(); profileIndex++) {
+ if (profile->equals(audioProfileVector.at(profileIndex))) {
+ // The dynamic profile is already there
+ break;
+ }
+ }
+ if (profileIndex >= audioProfileVector.size()) {
+ // Only add when the dynamic profile is not there
+ addAudioProfileAndSort(audioProfileVector, profile);
+ }
}
}
void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector,
- const sp<AudioProfile> &profileToAdd)
+ const sp<AudioProfile> &profileToAdd)
{
// Check valid profile to add:
if (!profileToAdd->hasValidFormat()) {
@@ -143,11 +153,15 @@
audioProfileVector, profileToAdd->getChannels(), profileToAdd->getFormat());
return;
}
+ const bool originalIsDynamicFormat = profileToAdd->isDynamicFormat();
+ profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal
// Go through the list of profile to avoid duplicates
for (size_t profileIndex = 0; profileIndex < audioProfileVector.size(); profileIndex++) {
const sp<AudioProfile> &profile = audioProfileVector.at(profileIndex);
- if (profile->isValid() && profile == profileToAdd) {
- // Nothing to do
+ if (profile->isValid() && profile->equals(profileToAdd)) {
+ // The same profile is already there, no need to add.
+ // Reset `isDynamicProfile` as original value.
+ profileToAdd->setDynamicFormat(originalIsDynamicFormat);
return;
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index fad89d9..44648de 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1298,7 +1298,8 @@
if (outputDevices.size() == 1) {
info = getPreferredMixerAttributesInfo(
outputDevices.itemAt(0)->getId(),
- mEngine->getProductStrategyForAttributes(*resultAttr));
+ mEngine->getProductStrategyForAttributes(*resultAttr),
+ true /*activeBitPerfectPreferred*/);
// Only use preferred mixer if the uid matches or the preferred mixer is bit-perfect
// and it is currently active.
if (info != nullptr && info->getUid() != uid &&
@@ -2152,6 +2153,26 @@
return DEAD_OBJECT;
}
info->increaseActiveClient();
+ if (info->getActiveClientCount() == 1 &&
+ (info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE) {
+ // If it is first bit-perfect client, reroute all clients that will be routed to
+ // the bit-perfect sink so that it is guaranteed only bit-perfect stream is active.
+ PortHandleVector clientsToInvalidate;
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ if (mOutputs[i] == outputDesc ||
+ mOutputs[i]->devices().filter(outputDesc->devices()).isEmpty()) {
+ continue;
+ }
+ for (const auto& c : mOutputs[i]->getClientIterable()) {
+ clientsToInvalidate.push_back(c->portId());
+ }
+ }
+ if (!clientsToInvalidate.empty()) {
+ ALOGD("%s Invalidate clients due to first bit-perfect client started",
+ __func__);
+ mpClientInterface->invalidateTracks(clientsToInvalidate);
+ }
+ }
}
}
@@ -3787,6 +3808,44 @@
return true;
}
+void AudioPolicyManager::changeOutputDevicesMuteState(
+ const AudioDeviceTypeAddrVector& devices) {
+ ALOGVV("%s() num devices %zu", __func__, devices.size());
+
+ std::vector<sp<SwAudioOutputDescriptor>> outputs =
+ getSoftwareOutputsForDevices(devices);
+
+ for (size_t i = 0; i < outputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> outputDesc = outputs[i];
+ DeviceVector prevDevices = outputDesc->devices();
+ checkDeviceMuteStrategies(outputDesc, prevDevices, 0 /* delayMs */);
+ }
+}
+
+std::vector<sp<SwAudioOutputDescriptor>> AudioPolicyManager::getSoftwareOutputsForDevices(
+ const AudioDeviceTypeAddrVector& devices) const
+{
+ std::vector<sp<SwAudioOutputDescriptor>> outputs;
+ DeviceVector deviceDescriptors;
+ for (size_t j = 0; j < devices.size(); j++) {
+ sp<DeviceDescriptor> desc = mHwModules.getDeviceDescriptor(
+ devices[j].mType, devices[j].getAddress(), String8(), AUDIO_FORMAT_DEFAULT);
+ if (desc == nullptr || !audio_is_output_device(devices[j].mType)) {
+ ALOGE("%s: device type %#x address %s not supported or not an output device",
+ __func__, devices[j].mType, devices[j].getAddress());
+ continue;
+ }
+ deviceDescriptors.add(desc);
+ }
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ if (!mOutputs.valueAt(i)->supportsAtLeastOne(deviceDescriptors)) {
+ continue;
+ }
+ outputs.push_back(mOutputs.valueAt(i));
+ }
+ return outputs;
+}
+
status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
const AudioDeviceTypeAddrVector& devices) {
ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size());
@@ -3853,7 +3912,8 @@
return NO_ERROR;
}
-void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs)
+void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs,
+ bool skipDelays)
{
uint32_t waitMs = 0;
bool wasLeUnicastActive = isLeUnicastActive();
@@ -3879,8 +3939,8 @@
continue;
}
waitMs = setOutputDevices(outputDesc, newDevices, forceRouting, delayMs, nullptr,
- true /*requiresMuteCheck*/,
- !forceRouting /*requiresVolumeCheck*/);
+ !skipDelays /*requiresMuteCheck*/,
+ !forceRouting /*requiresVolumeCheck*/, skipDelays);
// Only apply special touch sound delay once
delayMs = 0;
}
@@ -4065,13 +4125,18 @@
// reevaluate outputs for all devices
checkForDeviceAndOutputChanges();
- updateCallAndOutputRouting();
+ changeOutputDevicesMuteState(devices);
+ updateCallAndOutputRouting(false /* forceVolumeReeval */, 0 /* delayMs */,
+ true /* skipDelays */);
+ changeOutputDevicesMuteState(devices);
return NO_ERROR;
}
status_t AudioPolicyManager::removeUserIdDeviceAffinities(int userId) {
ALOGV("%s() userId=%d", __FUNCTION__, userId);
+ AudioDeviceTypeAddrVector devices;
+ mPolicyMixes.getDevicesForUserId(userId, devices);
status_t status = mPolicyMixes.removeUserIdDeviceAffinities(userId);
if (status != NO_ERROR) {
ALOGE("%s() Could not remove all device affinities fo userId = %d",
@@ -4081,7 +4146,10 @@
// reevaluate outputs for all devices
checkForDeviceAndOutputChanges();
- updateCallAndOutputRouting();
+ changeOutputDevicesMuteState(devices);
+ updateCallAndOutputRouting(false /* forceVolumeReeval */, 0 /* delayMs */,
+ true /* skipDelays */);
+ changeOutputDevicesMuteState(devices);
return NO_ERROR;
}
@@ -4490,16 +4558,24 @@
}
sp<PreferredMixerAttributesInfo> AudioPolicyManager::getPreferredMixerAttributesInfo(
- audio_port_handle_t devicePortId, product_strategy_t strategy) {
+ audio_port_handle_t devicePortId,
+ product_strategy_t strategy,
+ bool activeBitPerfectPreferred) {
auto it = mPreferredMixerAttrInfos.find(devicePortId);
if (it == mPreferredMixerAttrInfos.end()) {
return nullptr;
}
- auto mixerAttrInfoIt = it->second.find(strategy);
- if (mixerAttrInfoIt == it->second.end()) {
- return nullptr;
+ if (activeBitPerfectPreferred) {
+ for (auto [strategy, info] : it->second) {
+ if ((info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE
+ && info->getActiveClientCount() != 0) {
+ return info;
+ }
+ }
}
- return mixerAttrInfoIt->second;
+ auto strategyMatchedMixerAttrInfoIt = it->second.find(strategy);
+ return strategyMatchedMixerAttrInfoIt == it->second.end()
+ ? nullptr : strategyMatchedMixerAttrInfoIt->second;
}
status_t AudioPolicyManager::getPreferredMixerAttributes(
@@ -5841,22 +5917,26 @@
}
}
+ // The caller can have the audio config criteria ignored by either passing a null ptr or
+ // the AUDIO_CONFIG_INITIALIZER value.
+ // If an audio config is specified, current policy is to only allow spatialization for
+ // some positional channel masks and PCM format
+
+ if (config != nullptr && *config != AUDIO_CONFIG_INITIALIZER) {
+ if (!audio_is_channel_mask_spatialized(config->channel_mask)) {
+ return false;
+ }
+ if (!audio_is_linear_pcm(config->format)) {
+ return false;
+ }
+ }
+
sp<IOProfile> profile =
getSpatializerOutputProfile(config, devices);
if (profile == nullptr) {
return false;
}
- // The caller can have the audio config criteria ignored by either passing a null ptr or
- // the AUDIO_CONFIG_INITIALIZER value.
- // If an audio config is specified, current policy is to only allow spatialization for
- // some positional channel masks.
-
- if (config != nullptr && *config != AUDIO_CONFIG_INITIALIZER) {
- if (!audio_is_channel_mask_spatialized(config->channel_mask)) {
- return false;
- }
- }
return true;
}
@@ -7320,7 +7400,8 @@
bool force,
int delayMs,
audio_patch_handle_t *patchHandle,
- bool requiresMuteCheck, bool requiresVolumeCheck)
+ bool requiresMuteCheck, bool requiresVolumeCheck,
+ bool skipMuteDelay)
{
// TODO(b/262404095): Consider if the output need to be reopened.
ALOGV("%s device %s delayMs %d", __func__, devices.toString().c_str(), delayMs);
@@ -7328,9 +7409,9 @@
if (outputDesc->isDuplicated()) {
muteWaitMs = setOutputDevices(outputDesc->subOutput1(), devices, force, delayMs,
- nullptr /* patchHandle */, requiresMuteCheck);
+ nullptr /* patchHandle */, requiresMuteCheck, skipMuteDelay);
muteWaitMs += setOutputDevices(outputDesc->subOutput2(), devices, force, delayMs,
- nullptr /* patchHandle */, requiresMuteCheck);
+ nullptr /* patchHandle */, requiresMuteCheck, skipMuteDelay);
return muteWaitMs;
}
@@ -7396,12 +7477,16 @@
// Add half reported latency to delayMs when muteWaitMs is null in order
// to avoid disordered sequence of muting volume and changing devices.
- installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(),
- muteWaitMs == 0 ? (delayMs + (outputDesc->latency() / 2)) : delayMs);
+ int actualDelayMs = !skipMuteDelay && muteWaitMs == 0
+ ? (delayMs + (outputDesc->latency() / 2)) : delayMs;
+ installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), actualDelayMs);
}
- // update stream volumes according to new device
- applyStreamVolumes(outputDesc, filteredDevices.types(), delayMs);
+ // Since the mute is skip, also skip the apply stream volume as that will be applied externally
+ if (!skipMuteDelay) {
+ // update stream volumes according to new device
+ applyStreamVolumes(outputDesc, filteredDevices.types(), delayMs);
+ }
return muteWaitMs;
}
@@ -7759,8 +7844,8 @@
volumeDb = 0.0f;
}
const bool muted = (index == 0) && (volumeDb != 0.0f);
- outputDesc->setVolume(
- volumeDb, muted, volumeSource, curves.getStreamTypes(), deviceTypes, delayMs, force);
+ outputDesc->setVolume(volumeDb, muted, volumeSource, curves.getStreamTypes(),
+ deviceTypes, delayMs, force, isVoiceVolSrc);
if (outputDesc == mPrimaryOutput && (isVoiceVolSrc || isBtScoVolSrc)) {
float voiceVolume;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 88bafef..863c785 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -535,8 +535,9 @@
* and currently active, allow to have proper drain and avoid pops
* @param requiresVolumeCheck true if called requires to reapply volume if the routing did
* not change (but the output is still routed).
+ * @param skipMuteDelay if true will skip mute delay when installing audio patch
* @return the number of ms we have slept to allow new routing to take effect in certain
- * cases.
+ * cases.
*/
uint32_t setOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
const DeviceVector &device,
@@ -544,7 +545,8 @@
int delayMs = 0,
audio_patch_handle_t *patchHandle = NULL,
bool requiresMuteCheck = true,
- bool requiresVolumeCheck = false);
+ bool requiresVolumeCheck = false,
+ bool skipMuteDelay = false);
status_t resetOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
audio_patch_handle_t *patchHandle = NULL);
@@ -647,8 +649,10 @@
/**
* @brief updates routing for all outputs (including call if call in progress).
* @param delayMs delay for unmuting if required
+ * @param skipDelays if true all the delays will be skip while updating routing
*/
- void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
+ void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0,
+ bool skipDelays = false);
bool isCallRxAudioSource(const sp<SourceClientDescriptor> &source) {
return mCallRxSourceClient != nullptr && source == mCallRxSourceClient;
@@ -1241,6 +1245,21 @@
const char* context,
bool matchAddress = true);
+ /**
+ * @brief changeOutputDevicesMuteState mute/unmute devices using checkDeviceMuteStrategies
+ * @param devices devices to mute/unmute
+ */
+ void changeOutputDevicesMuteState(const AudioDeviceTypeAddrVector& devices);
+
+ /**
+ * @brief Returns a vector of software output descriptor that support the queried devices
+ * @param devices devices to query
+ * @param openOutputs open outputs where the devices are supported as determined by
+ * SwAudioOutputDescriptor::supportsAtLeastOne
+ */
+ std::vector<sp<SwAudioOutputDescriptor>> getSoftwareOutputsForDevices(
+ const AudioDeviceTypeAddrVector& devices) const;
+
bool isScoRequestedForComm() const;
bool isHearingAidUsedForComm() const;
@@ -1298,8 +1317,15 @@
uint32_t flags,
bool isInput);
+ /**
+ * Returns the preferred mixer attributes info for the given device port id and strategy.
+ * Bit-perfect mixer attributes will be returned if it is active and
+ * `activeBitPerfectPreferred` is true.
+ */
sp<PreferredMixerAttributesInfo> getPreferredMixerAttributesInfo(
- audio_port_handle_t devicePortId, product_strategy_t strategy);
+ audio_port_handle_t devicePortId,
+ product_strategy_t strategy,
+ bool activeBitPerfectPreferred = false);
sp<SwAudioOutputDescriptor> reopenOutput(
sp<SwAudioOutputDescriptor> outputDesc,
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 5d22ed4..15aced0 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -25,6 +25,7 @@
#include <sys/time.h>
#include <dlfcn.h>
+#include <android/content/pm/IPackageManagerNative.h>
#include <audio_utils/clock.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
@@ -215,6 +216,27 @@
{
delete interface;
}
+
+namespace {
+int getTargetSdkForPackageName(std::string_view packageName) {
+ const auto binder = defaultServiceManager()->checkService(String16{"package_native"});
+ int targetSdk = -1;
+ if (binder != nullptr) {
+ const auto pm = interface_cast<content::pm::IPackageManagerNative>(binder);
+ if (pm != nullptr) {
+ const auto status = pm->getTargetSdkVersionForPackage(
+ String16{packageName.data(), packageName.size()}, &targetSdk);
+ ALOGI("Capy check package %s, sdk %d", packageName.data(), targetSdk);
+ return status.isOk() ? targetSdk : -1;
+ }
+ }
+ return targetSdk;
+}
+
+bool doesPackageTargetAtLeastU(std::string_view packageName) {
+ return getTargetSdkForPackageName(packageName) >= __ANDROID_API_U__;
+}
+} // anonymous
// ----------------------------------------------------------------------------
AudioPolicyService::AudioPolicyService()
@@ -1926,10 +1948,14 @@
checkOp();
mOpCallback = new RecordAudioOpCallback(this);
ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str());
+ int flags = doesPackageTargetAtLeastU(
+ mAttributionSource.packageName.value_or("")) ?
+ AppOpsManager::WATCH_FOREGROUND_CHANGES : 0;
// TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too
// since it controls the mic permission for legacy apps.
mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
mAttributionSource.packageName.value_or(""))),
+ flags,
mOpCallback);
}
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 5e58dbb..15eae14 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1232,6 +1232,19 @@
EXPECT_FALSE(isBitPerfect);
EXPECT_EQ(bitPerfectOutput, output);
+ const audio_attributes_t dtmfAttr = {
+ .content_type = AUDIO_CONTENT_TYPE_UNKNOWN,
+ .usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ };
+ audio_io_handle_t dtmfOutput = AUDIO_IO_HANDLE_NONE;
+ selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ portId = AUDIO_PORT_HANDLE_NONE;
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000, AUDIO_OUTPUT_FLAG_NONE, &dtmfOutput, &portId, dtmfAttr,
+ AUDIO_SESSION_NONE, anotherUid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_EQ(bitPerfectOutput, dtmfOutput);
+
// When configuration matches preferred mixer attributes, which is bit-perfect, but the client
// is not the owner of preferred mixer attributes, the playback will not be bit-perfect.
getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index bf85029..1b1662b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -316,14 +316,24 @@
for (auto& i : mListenerList) {
if (shouldSkipStatusUpdates(systemCameraKind, i->isVendorListener(), i->getListenerPid(),
i->getListenerUid())) {
- ALOGV("Skipping torch callback for system-only camera device %s",
- cameraId.c_str());
+ ALOGV("%s: Skipping torch callback for system-only camera device %s",
+ __FUNCTION__, cameraId.c_str());
continue;
}
auto ret = i->getListener()->onTorchStatusChanged(mapToInterface(status),
String16{cameraId});
i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d",
__FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode());
+ // Also trigger the torch callbacks for cameras that were remapped to the current cameraId
+ // for the specific package that this listener belongs to.
+ std::vector<String8> remappedCameraIds =
+ findOriginalIdsForRemappedCameraId(cameraId, i->getListenerUid());
+ for (auto& remappedCameraId : remappedCameraIds) {
+ ret = i->getListener()->onTorchStatusChanged(mapToInterface(status),
+ String16(remappedCameraId));
+ i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d",
+ __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode());
+ }
}
}
@@ -745,6 +755,156 @@
return Status::ok();
}
+Status CameraService::remapCameraIds(const hardware::CameraIdRemapping&
+ cameraIdRemapping) {
+ if (!checkCallingPermission(sCameraInjectExternalCameraPermission)) {
+ const int pid = CameraThreadState::getCallingPid();
+ const int uid = CameraThreadState::getCallingUid();
+ ALOGE("%s: Permission Denial: can't configure camera ID mapping pid=%d, uid=%d",
+ __FUNCTION__, pid, uid);
+ return STATUS_ERROR(ERROR_PERMISSION_DENIED,
+ "Permission Denial: no permission to configure camera id mapping");
+ }
+ TCameraIdRemapping cameraIdRemappingMap{};
+ binder::Status parseStatus = parseCameraIdRemapping(cameraIdRemapping, &cameraIdRemappingMap);
+ if (!parseStatus.isOk()) {
+ return parseStatus;
+ }
+ remapCameraIds(cameraIdRemappingMap);
+ return Status::ok();
+}
+
+Status CameraService::parseCameraIdRemapping(
+ const hardware::CameraIdRemapping& cameraIdRemapping,
+ /* out */ TCameraIdRemapping* cameraIdRemappingMap) {
+ String16 packageName;
+ String8 cameraIdToReplace, updatedCameraId;
+ for(const auto& packageIdRemapping: cameraIdRemapping.packageIdRemappings) {
+ packageName = packageIdRemapping.packageName;
+ if (packageName == String16("")) {
+ return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
+ "CameraIdRemapping: Package name cannot be empty");
+ }
+
+ if (packageIdRemapping.cameraIdsToReplace.size()
+ != packageIdRemapping.updatedCameraIds.size()) {
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
+ "CameraIdRemapping: Mismatch in CameraId Remapping lists sizes for package %s",
+ String8(packageName).c_str());
+ }
+ for(size_t i = 0; i < packageIdRemapping.cameraIdsToReplace.size(); i++) {
+ cameraIdToReplace = String8(packageIdRemapping.cameraIdsToReplace[i]);
+ updatedCameraId = String8(packageIdRemapping.updatedCameraIds[i]);
+ if (cameraIdToReplace == String8("") || updatedCameraId == String8("")) {
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
+ "CameraIdRemapping: Camera Id cannot be empty for package %s",
+ String8(packageName).c_str());
+ }
+ if (cameraIdToReplace == updatedCameraId) {
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
+ "CameraIdRemapping: CameraIdToReplace cannot be the same"
+ " as updatedCameraId for %s",
+ String8(packageName).c_str());
+ }
+ (*cameraIdRemappingMap)[packageName][cameraIdToReplace] = updatedCameraId;
+ }
+ }
+ return Status::ok();
+}
+
+void CameraService::remapCameraIds(const TCameraIdRemapping& cameraIdRemapping) {
+ // Acquire mServiceLock and prevent other clients from connecting
+ std::unique_ptr<AutoConditionLock> serviceLockWrapper =
+ AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
+
+ Mutex::Autolock lock(mCameraIdRemappingLock);
+ // This will disconnect all existing clients for camera Ids that are being
+ // remapped in cameraIdRemapping, but only if they were being used by an
+ // affected packageName.
+ std::vector<sp<BasicClient>> clientsToDisconnect;
+ std::vector<String8> cameraIdsToUpdate;
+ for (const auto& [packageName, injectionMap] : cameraIdRemapping) {
+ for (auto& [id0, id1] : injectionMap) {
+ ALOGI("%s: UPDATE:= %s: %s: %s", __FUNCTION__, String8(packageName).c_str(),
+ id0.c_str(), id1.c_str());
+ auto clientDescriptor = mActiveClientManager.get(id0);
+ if (clientDescriptor != nullptr) {
+ sp<BasicClient> clientSp = clientDescriptor->getValue();
+ if (clientSp->getPackageName() == packageName) {
+ // This camera ID is being used by the affected packageName.
+ clientsToDisconnect.push_back(clientSp);
+ cameraIdsToUpdate.push_back(id0);
+ }
+ }
+ }
+ }
+
+ // Update mCameraIdRemapping.
+ mCameraIdRemapping.clear();
+ mCameraIdRemapping.insert(cameraIdRemapping.begin(), cameraIdRemapping.end());
+
+ // Do not hold mServiceLock while disconnecting clients, but retain the condition
+ // blocking other clients from connecting in mServiceLockWrapper if held.
+ mServiceLock.unlock();
+
+ // Disconnect clients.
+ for (auto& clientSp : clientsToDisconnect) {
+ // We send up ERROR_CAMERA_DEVICE so that the app attempts to reconnect
+ // automatically.
+ clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+ CaptureResultExtras{});
+ // This also triggers the status updates
+ clientSp->disconnect();
+ }
+
+ mServiceLock.lock();
+}
+
+std::vector<String8> CameraService::findOriginalIdsForRemappedCameraId(
+ const String8& inputCameraId, int clientUid) {
+ String16 packageName = getPackageNameFromUid(clientUid);
+ std::vector<String8> cameraIds;
+ Mutex::Autolock lock(mCameraIdRemappingLock);
+ if (auto packageMapIter = mCameraIdRemapping.find(packageName);
+ packageMapIter != mCameraIdRemapping.end()) {
+ for (auto& [id0, id1]: packageMapIter->second) {
+ if (id1 == inputCameraId) {
+ cameraIds.push_back(id0);
+ }
+ }
+ }
+ return cameraIds;
+}
+
+String8 CameraService::resolveCameraId(const String8& inputCameraId) {
+ return resolveCameraId(inputCameraId, String16(""));
+}
+
+String8 CameraService::resolveCameraId(
+ const String8& inputCameraId,
+ const String16& packageName) {
+ String16 packageNameVal = packageName;
+ if (packageName == String16("")) {
+ int clientUid = CameraThreadState::getCallingUid();
+ packageNameVal = getPackageNameFromUid(clientUid);
+ }
+ Mutex::Autolock lock(mCameraIdRemappingLock);
+ if (auto packageMapIter = mCameraIdRemapping.find(packageNameVal);
+ packageMapIter != mCameraIdRemapping.end()) {
+ ALOGI("%s: resolveCameraId: packageName found %s",
+ __FUNCTION__, String8(packageNameVal).c_str());
+ auto packageMap = packageMapIter->second;
+ if (auto replacementIdIter = packageMap.find(inputCameraId);
+ replacementIdIter != packageMap.end()) {
+ ALOGI("%s: resolveCameraId: inputId found %s, replacing with %s",
+ __FUNCTION__, inputCameraId.c_str(),
+ replacementIdIter->second.c_str());
+ return replacementIdIter->second;
+ }
+ }
+ return inputCameraId;
+}
+
Status CameraService::getCameraInfo(int cameraId, bool overrideToPortrait,
CameraInfo* cameraInfo) {
ATRACE_CALL();
@@ -815,9 +975,10 @@
return String8(cameraIdIntToStrLocked(cameraIdInt).c_str());
}
-Status CameraService::getCameraCharacteristics(const String16& cameraId,
+Status CameraService::getCameraCharacteristics(const String16& unresolvedCameraId,
int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) {
ATRACE_CALL();
+ String8 cameraId = resolveCameraId(String8(unresolvedCameraId));
if (!cameraInfo) {
ALOGE("%s: cameraInfo is NULL", __FUNCTION__);
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "cameraInfo is NULL");
@@ -837,8 +998,7 @@
Status ret{};
-
- std::string cameraIdStr = String8(cameraId).string();
+ std::string cameraIdStr = cameraId.string();
bool overrideForPerfClass =
SessionConfigurationUtils::targetPerfClassPrimaryCamera(mPerfClassPrimaryCameraIds,
cameraIdStr, targetSdkVersion);
@@ -1028,7 +1188,7 @@
int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid,
int servicePid, std::pair<int, IPCTransport> deviceVersionAndTransport,
apiLevel effectiveApiLevel, bool overrideForPerfClass, bool overrideToPortrait,
- bool forceSlowJpegMode, /*out*/sp<BasicClient>* client) {
+ bool forceSlowJpegMode, const String8& originalCameraId, /*out*/sp<BasicClient>* client) {
// For HIDL devices
if (deviceVersionAndTransport.second == IPCTransport::HIDL) {
// Create CameraClient based on device version reported by the HAL.
@@ -1071,7 +1231,7 @@
*client = new CameraDeviceClient(cameraService, tmp,
cameraService->mCameraServiceProxyWrapper, packageName, systemNativeClient,
featureId, cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid,
- overrideForPerfClass, overrideToPortrait);
+ overrideForPerfClass, overrideToPortrait, originalCameraId);
ALOGI("%s: Camera2 API, override to portrait %d", __FUNCTION__, overrideToPortrait);
}
return Status::ok();
@@ -1163,7 +1323,7 @@
internalPackageName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID,
API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
/*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*overrideToPortrait*/ true,
- /*forceSlowJpegMode*/false, /*out*/ tmp)
+ /*forceSlowJpegMode*/false, id, /*out*/ tmp)
).isOk()) {
ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
}
@@ -1700,7 +1860,7 @@
ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
clientPackageName,/*systemNativeClient*/ false, {}, clientUid, clientPid, API_1,
/*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion,
- overrideToPortrait, forceSlowJpegMode, /*out*/client);
+ overrideToPortrait, forceSlowJpegMode, id, /*out*/client);
if(!ret.isOk()) {
logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1780,7 +1940,7 @@
Status CameraService::connectDevice(
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
- const String16& cameraId,
+ const String16& unresolvedCameraId,
const String16& clientPackageName,
const std::optional<String16>& clientFeatureId,
int clientUid, int oomScoreOffset, int targetSdkVersion,
@@ -1790,7 +1950,7 @@
ATRACE_CALL();
Status ret = Status::ok();
- String8 id = String8(cameraId);
+ String8 id = resolveCameraId(String8(unresolvedCameraId), clientPackageName);
sp<CameraDeviceClient> client = nullptr;
String16 clientPackageNameAdj = clientPackageName;
int callingPid = CameraThreadState::getCallingPid();
@@ -1840,7 +2000,7 @@
/*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient,clientFeatureId,
clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset,
targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false,
- /*out*/client);
+ String8(unresolvedCameraId), /*out*/client);
if(!ret.isOk()) {
logRejected(id, callingPid, String8(clientPackageNameAdj), ret.toString8());
@@ -1909,7 +2069,7 @@
int api1CameraId, const String16& clientPackageNameMaybe, bool systemNativeClient,
const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
- bool overrideToPortrait, bool forceSlowJpegMode,
+ bool overrideToPortrait, bool forceSlowJpegMode, const String8& originalCameraId,
/*out*/sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
@@ -2026,7 +2186,7 @@
clientFeatureId, cameraId, api1CameraId, facing, orientation,
clientPid, clientUid, getpid(),
deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
- overrideToPortrait, forceSlowJpegMode,
+ overrideToPortrait, forceSlowJpegMode, originalCameraId,
/*out*/&tmp)).isOk()) {
return ret;
}
@@ -2040,6 +2200,9 @@
if (err != OK) {
ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
// Errors could be from the HAL module open call or from AppOpsManager
+ mServiceLock.unlock();
+ client->disconnect();
+ mServiceLock.lock();
switch(err) {
case BAD_VALUE:
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
@@ -2278,7 +2441,8 @@
return OK;
}
-Status CameraService::turnOnTorchWithStrengthLevel(const String16& cameraId, int32_t torchStrength,
+Status CameraService::turnOnTorchWithStrengthLevel(const String16& unresolvedCameraId,
+ int32_t torchStrength,
const sp<IBinder>& clientBinder) {
Mutex::Autolock lock(mServiceLock);
@@ -2289,7 +2453,7 @@
"Torch client binder in null.");
}
- String8 id = String8(cameraId.string());
+ String8 id = resolveCameraId(String8(unresolvedCameraId));
int uid = CameraThreadState::getCallingUid();
if (shouldRejectSystemCameraConnection(id)) {
@@ -2349,7 +2513,7 @@
{
Mutex::Autolock al(mTorchUidMapMutex);
- updateTorchUidMapLocked(cameraId, uid);
+ updateTorchUidMapLocked(String16(id), uid);
}
// Check if the current torch strength level is same as the new one.
bool shouldSkipTorchStrengthUpdates = mCameraProviderManager->shouldSkipTorchStrengthUpdate(
@@ -2408,7 +2572,8 @@
return Status::ok();
}
-Status CameraService::setTorchMode(const String16& cameraId, bool enabled,
+Status CameraService::setTorchMode(const String16& unresolvedCameraId,
+ bool enabled,
const sp<IBinder>& clientBinder) {
Mutex::Autolock lock(mServiceLock);
@@ -2419,7 +2584,7 @@
"Torch client Binder is null");
}
- String8 id = String8(cameraId.string());
+ String8 id = resolveCameraId(String8(unresolvedCameraId));
int uid = CameraThreadState::getCallingUid();
if (shouldRejectSystemCameraConnection(id)) {
@@ -2479,7 +2644,7 @@
// Update UID map - this is used in the torch status changed callbacks, so must be done
// before setTorchMode
Mutex::Autolock al(mTorchUidMapMutex);
- updateTorchUidMapLocked(cameraId, uid);
+ updateTorchUidMapLocked(String16(id), uid);
}
status_t err = mFlashlight->setTorchMode(id, enabled);
@@ -2949,11 +3114,20 @@
return ret;
}
-Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion,
+Status CameraService::supportsCameraApi(const String16& unresolvedCameraId, int apiVersion,
/*out*/ bool *isSupported) {
ATRACE_CALL();
- const String8 id = String8(cameraId);
+ String8 resolvedId;
+ if (apiVersion == API_VERSION_2) {
+ resolvedId = resolveCameraId(String8(unresolvedCameraId));
+ } else { // if (apiVersion == API_VERSION_1)
+ // We don't support remapping for API 1.
+ // TODO(b/286287541): Also support remapping for API 1.
+ resolvedId = String8(unresolvedCameraId);
+ }
+
+ const String8 id = resolvedId;
ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());
@@ -3013,11 +3187,11 @@
return Status::ok();
}
-Status CameraService::isHiddenPhysicalCamera(const String16& cameraId,
+Status CameraService::isHiddenPhysicalCamera(const String16& unresolvedCameraId,
/*out*/ bool *isSupported) {
ATRACE_CALL();
- const String8 id = String8(cameraId);
+ const String8 id = resolveCameraId(String8(unresolvedCameraId));
ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());
*isSupported = mCameraProviderManager->isHiddenPhysicalCamera(id.string());
@@ -4960,7 +5134,6 @@
state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind,
&logicalCameraIds]
(const String8& cameraId, StatusInternal status) {
-
if (status != StatusInternal::ENUMERATING) {
// Update torch status if it has a flash unit.
Mutex::Autolock al(mTorchStatusMutex);
@@ -4993,9 +5166,21 @@
auto ret = listener->getListener()->onStatusChanged(mapToInterface(status),
String16(cameraId));
listener->handleBinderStatus(ret,
- "%s: Failed to trigger onStatusChanged callback for %d:%d: %d",
+ "%s: Failed to trigger onStatusChanged callback for %d:%d: %d",
__FUNCTION__, listener->getListenerUid(), listener->getListenerPid(),
ret.exceptionCode());
+ // Also trigger the callbacks for cameras that were remapped to the current
+ // cameraId for the specific package that this listener belongs to.
+ std::vector<String8> remappedCameraIds =
+ findOriginalIdsForRemappedCameraId(cameraId, listener->getListenerUid());
+ for (auto& remappedCameraId : remappedCameraIds) {
+ ret = listener->getListener()->onStatusChanged(
+ mapToInterface(status), String16(remappedCameraId));
+ listener->handleBinderStatus(ret,
+ "%s: Failed to trigger onStatusChanged callback for %d:%d: %d",
+ __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(),
+ ret.exceptionCode());
+ }
}
});
}
@@ -5206,6 +5391,8 @@
return handleWatchCommand(args, in, out);
} else if (args.size() >= 2 && args[0] == String16("set-watchdog")) {
return handleSetCameraServiceWatchdog(args);
+ } else if (args.size() >= 4 && args[0] == String16("remap-camera-id")) {
+ return handleCameraIdRemapping(args, err);
} else if (args.size() == 1 && args[0] == String16("help")) {
printHelp(out);
return OK;
@@ -5214,6 +5401,23 @@
return BAD_VALUE;
}
+status_t CameraService::handleCameraIdRemapping(const Vector<String16>& args, int err) {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ if (uid != AID_ROOT) {
+ dprintf(err, "Must be adb root\n");
+ return PERMISSION_DENIED;
+ }
+ if (args.size() != 4) {
+ dprintf(err, "Expected format: remap-camera-id <PACKAGE> <Id0> <Id1>\n");
+ return BAD_VALUE;
+ }
+ String16 packageName = args[1];
+ String8 cameraIdToReplace = String8(args[2]);
+ String8 cameraIdNew = String8(args[3]);
+ remapCameraIds({{packageName, {{cameraIdToReplace, cameraIdNew}}}});
+ return OK;
+}
+
status_t CameraService::handleSetUidState(const Vector<String16>& args, int err) {
String16 packageName = args[1];
@@ -5841,6 +6045,7 @@
" clear-stream-use-case-override clear the stream use case override\n"
" set-zoom-override <-1/0/1> enable or disable zoom override\n"
" Valid values -1: do not override, 0: override to OFF, 1: override to ZOOM\n"
+ " remap-camera-id <PACKAGE> <Id0> <Id1> remaps camera ids. Must use adb root\n"
" watch <start|stop|dump|print|clear> manages tag monitoring in connected clients\n"
" help print this message\n");
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 3214d4c..65b11e7 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -20,6 +20,7 @@
#include <android/hardware/BnCameraService.h>
#include <android/hardware/BnSensorPrivacyListener.h>
#include <android/hardware/ICameraServiceListener.h>
+#include <android/hardware/CameraIdRemapping.h>
#include <android/hardware/camera2/BnCameraInjectionSession.h>
#include <android/hardware/camera2/ICameraInjectionCallback.h>
@@ -61,6 +62,7 @@
#include <utility>
#include <unordered_map>
#include <unordered_set>
+#include <vector>
namespace android {
@@ -138,6 +140,9 @@
/////////////////////////////////////////////////////////////////////
// ICameraService
+ // IMPORTANT: All binder calls that deal with logicalCameraId should use
+ // resolveCameraId(logicalCameraId) to arrive at the correct cameraId to
+ // perform the operation on (in case of Id Remapping).
virtual binder::Status getNumberOfCameras(int32_t type, int32_t* numCameras);
virtual binder::Status getCameraInfo(int cameraId, bool overrideToPortrait,
@@ -221,6 +226,9 @@
virtual binder::Status reportExtensionSessionStats(
const hardware::CameraExtensionSessionStats& stats, String16* sessionKey /*out*/);
+ virtual binder::Status remapCameraIds(const hardware::CameraIdRemapping&
+ cameraIdRemapping);
+
// Extra permissions checks
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
@@ -916,7 +924,7 @@
int api1CameraId, const String16& clientPackageNameMaybe, bool systemNativeClient,
const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset, int targetSdkVersion,
- bool overrideToPortrait, bool forceSlowJpegMode,
+ bool overrideToPortrait, bool forceSlowJpegMode, const String8& originalCameraId,
/*out*/sp<CLIENT>& device);
// Lock guarding camera service state
@@ -943,6 +951,48 @@
// Mutex guarding mCameraStates map
mutable Mutex mCameraStatesLock;
+ /**
+ * Mapping from packageName -> {cameraIdToReplace -> newCameraIdtoUse}.
+ *
+ * This specifies that for packageName, for every binder operation targeting
+ * cameraIdToReplace, use newCameraIdToUse instead.
+ */
+ typedef std::map<String16, std::map<String8, String8>> TCameraIdRemapping;
+ TCameraIdRemapping mCameraIdRemapping{};
+ /** Mutex guarding mCameraIdRemapping. */
+ Mutex mCameraIdRemappingLock;
+
+ /** Parses cameraIdRemapping parcelable into the native cameraIdRemappingMap. */
+ binder::Status parseCameraIdRemapping(
+ const hardware::CameraIdRemapping& cameraIdRemapping,
+ /* out */ TCameraIdRemapping* cameraIdRemappingMap);
+
+ /**
+ * Resolve the (potentially remapped) camera Id to use for packageName.
+ *
+ * This returns the Camera Id to use in case inputCameraId was remapped to a
+ * different Id for the given packageName. Otherwise, it returns the inputCameraId.
+ */
+ String8 resolveCameraId(const String8& inputCameraId, const String16& packageName);
+ /**
+ * Resolve the (potentially remapped) camera Id to use.
+ *
+ * This returns the Camera Id to use in case inputCameraId was remapped to a
+ * different Id for the packageName of the client. Otherwise, it returns the inputCameraId.
+ */
+ String8 resolveCameraId(const String8& inputCameraId);
+
+ /**
+ * Updates the state of mCameraIdRemapping, while disconnecting active clients as necessary.
+ */
+ void remapCameraIds(const TCameraIdRemapping& cameraIdRemapping);
+
+ /**
+ * Finds the Camera Ids that were remapped to the inputCameraId for the given client.
+ */
+ std::vector<String8> findOriginalIdsForRemappedCameraId(
+ const String8& inputCameraId, int clientUid);
+
// Circular buffer for storing event logging for dumps
RingBuffer<String8> mEventLog;
Mutex mLogLock;
@@ -1322,6 +1372,9 @@
// Set or clear the zoom override flag
status_t handleSetZoomOverride(const Vector<String16>& args);
+ // Set Camera Id remapping using 'cmd'
+ status_t handleCameraIdRemapping(const Vector<String16>& args, int errFd);
+
// Handle 'watch' command as passed through 'cmd'
status_t handleWatchCommand(const Vector<String16> &args, int inFd, int outFd);
@@ -1367,14 +1420,15 @@
*/
static String8 getFormattedCurrentTime();
- static binder::Status makeClient(const sp<CameraService>& cameraService,
- const sp<IInterface>& cameraCb, const String16& packageName,
- bool systemNativeClient, const std::optional<String16>& featureId,
- const String8& cameraId, int api1CameraId, int facing, int sensorOrientation,
- int clientPid, uid_t clientUid, int servicePid,
+ static binder::Status makeClient(
+ const sp<CameraService>& cameraService, const sp<IInterface>& cameraCb,
+ const String16& packageName, bool systemNativeClient,
+ const std::optional<String16>& featureId, const String8& cameraId, int api1CameraId,
+ int facing, int sensorOrientation, int clientPid, uid_t clientUid, int servicePid,
std::pair<int, IPCTransport> deviceVersionAndIPCTransport, apiLevel effectiveApiLevel,
bool overrideForPerfClass, bool overrideToPortrait, bool forceSlowJpegMode,
- /*out*/sp<BasicClient>* client);
+ const String8& originalCameraId,
+ /*out*/ sp<BasicClient>* client);
status_t checkCameraAccess(const String16& opPackageName);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 8348cd9..5b5892a 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -70,7 +70,9 @@
cameraDeviceId, api1CameraId, cameraFacing, sensorOrientation, clientPid,
clientUid, servicePid, overrideForPerfClass, overrideToPortrait,
/*legacyClient*/ true),
- mParameters(api1CameraId, cameraFacing)
+ mParameters(api1CameraId, cameraFacing),
+ mLatestRequestIds(kMaxRequestIds),
+ mLatestFailedRequestIds(kMaxRequestIds)
{
ATRACE_CALL();
@@ -1843,7 +1845,7 @@
(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT == errorCode)) {
Mutex::Autolock al(mLatestRequestMutex);
- mLatestFailedRequestId = resultExtras.requestId;
+ mLatestFailedRequestIds.add(resultExtras.requestId);
mLatestRequestSignal.signal();
}
mCaptureSequencer->notifyError(errorCode, resultExtras);
@@ -2418,7 +2420,10 @@
status_t Camera2Client::waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout) {
Mutex::Autolock l(mLatestRequestMutex);
- while ((mLatestRequestId != requestId) && (mLatestFailedRequestId != requestId)) {
+ while ((std::find(mLatestRequestIds.begin(), mLatestRequestIds.end(), requestId) ==
+ mLatestRequestIds.end()) &&
+ (std::find(mLatestFailedRequestIds.begin(), mLatestFailedRequestIds.end(), requestId) ==
+ mLatestFailedRequestIds.end())) {
nsecs_t startTime = systemTime();
auto res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
@@ -2427,13 +2432,14 @@
timeout -= (systemTime() - startTime);
}
- return (mLatestRequestId == requestId) ? OK : DEAD_OBJECT;
+ return (std::find(mLatestRequestIds.begin(), mLatestRequestIds.end(), requestId) !=
+ mLatestRequestIds.end()) ? OK : DEAD_OBJECT;
}
void Camera2Client::notifyRequestId(int32_t requestId) {
Mutex::Autolock al(mLatestRequestMutex);
- mLatestRequestId = requestId;
+ mLatestRequestIds.add(requestId);
mLatestRequestSignal.signal();
}
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 6bdb644..a7ea823 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -22,11 +22,7 @@
#include "common/Camera2ClientBase.h"
#include "api1/client2/Parameters.h"
#include "api1/client2/FrameProcessor.h"
-//#include "api1/client2/StreamingProcessor.h"
-//#include "api1/client2/JpegProcessor.h"
-//#include "api1/client2/ZslProcessor.h"
-//#include "api1/client2/CaptureSequencer.h"
-//#include "api1/client2/CallbackProcessor.h"
+#include <media/RingBuffer.h>
namespace android {
@@ -263,8 +259,8 @@
mutable Mutex mLatestRequestMutex;
Condition mLatestRequestSignal;
- int32_t mLatestRequestId = -1;
- int32_t mLatestFailedRequestId = -1;
+ static constexpr size_t kMaxRequestIds = BufferQueueDefs::NUM_BUFFER_SLOTS;
+ RingBuffer<int32_t> mLatestRequestIds, mLatestFailedRequestIds;
status_t waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout);
status_t waitUntilCurrentRequestIdLocked();
};
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 38c615d..1720b55 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -98,7 +98,8 @@
uid_t clientUid,
int servicePid,
bool overrideForPerfClass,
- bool overrideToPortrait) :
+ bool overrideToPortrait,
+ const String8& originalCameraId) :
Camera2ClientBase(cameraService, remoteCallback, cameraServiceProxyWrapper, clientPackageName,
systemNativeClient, clientFeatureId, cameraId, /*API1 camera ID*/ -1, cameraFacing,
sensorOrientation, clientPid, clientUid, servicePid, overrideForPerfClass,
@@ -106,8 +107,8 @@
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0),
- mOverrideForPerfClass(overrideForPerfClass) {
-
+ mOverrideForPerfClass(overrideForPerfClass),
+ mOriginalCameraId(originalCameraId) {
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
@@ -322,7 +323,7 @@
//The first capture settings should always match the logical camera id
String8 logicalId(request.mPhysicalCameraSettings.begin()->id.c_str());
- if (mDevice->getId() != logicalId) {
+ if (mDevice->getId() != logicalId && mOriginalCameraId != logicalId) {
ALOGE("%s: Camera %s: Invalid camera request settings.", __FUNCTION__,
mCameraIdStr.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
@@ -437,6 +438,8 @@
CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
for (const auto& it : request.mPhysicalCameraSettings) {
+ std::string resolvedId = (
+ mOriginalCameraId.string() == it.id) ? mDevice->getId().string() : it.id;
if (it.settings.isEmpty()) {
ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
__FUNCTION__, mCameraIdStr.string());
@@ -447,7 +450,7 @@
// Check whether the physical / logical stream has settings
// consistent with the sensor pixel mode(s) it was configured with.
// mCameraIdToStreamSet will only have ids that are high resolution
- const auto streamIdSetIt = mHighResolutionCameraIdToStreamIdSet.find(it.id);
+ const auto streamIdSetIt = mHighResolutionCameraIdToStreamIdSet.find(resolvedId);
if (streamIdSetIt != mHighResolutionCameraIdToStreamIdSet.end()) {
std::list<int> streamIdsUsedInRequest = getIntersection(streamIdSetIt->second,
outputStreamIds);
@@ -455,14 +458,14 @@
!isSensorPixelModeConsistent(streamIdsUsedInRequest, it.settings)) {
ALOGE("%s: Camera %s: Request settings CONTROL_SENSOR_PIXEL_MODE not "
"consistent with configured streams. Rejecting request.",
- __FUNCTION__, it.id.c_str());
+ __FUNCTION__, resolvedId.c_str());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
"Request settings CONTROL_SENSOR_PIXEL_MODE are not consistent with "
"streams configured");
}
}
- String8 physicalId(it.id.c_str());
+ String8 physicalId(resolvedId.c_str());
bool hasTestPatternModePhysicalKey = std::find(mSupportedPhysicalRequestKeys.begin(),
mSupportedPhysicalRequestKeys.end(), ANDROID_SENSOR_TEST_PATTERN_MODE) !=
mSupportedPhysicalRequestKeys.end();
@@ -471,7 +474,7 @@
mSupportedPhysicalRequestKeys.end();
if (physicalId != mDevice->getId()) {
auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(),
- it.id);
+ resolvedId);
if (found == requestedPhysicalIds.end()) {
ALOGE("%s: Camera %s: Physical camera id: %s not part of attached outputs.",
__FUNCTION__, mCameraIdStr.string(), physicalId.string());
@@ -494,11 +497,11 @@
}
}
- physicalSettingsList.push_back({it.id, filteredParams,
+ physicalSettingsList.push_back({resolvedId, filteredParams,
hasTestPatternModePhysicalKey, hasTestPatternDataPhysicalKey});
}
} else {
- physicalSettingsList.push_back({it.id, it.settings});
+ physicalSettingsList.push_back({resolvedId, it.settings});
}
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 1533cf5..95563ee 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -191,7 +191,8 @@
uid_t clientUid,
int servicePid,
bool overrideForPerfClass,
- bool overrideToPortrait);
+ bool overrideToPortrait,
+ const String8& originalCameraId);
virtual ~CameraDeviceClient();
virtual status_t initialize(sp<CameraProviderManager> manager,
@@ -368,6 +369,9 @@
std::string mUserTag;
// The last set video stabilization mode
int mVideoStabilizationMode = -1;
+
+ // This only exists in case of camera ID Remapping.
+ String8 mOriginalCameraId;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 61c3298..71e49fd 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -3030,6 +3030,7 @@
mNotifyPipelineDrain(false),
mFrameNumber(0),
mLatestRequestId(NAME_NOT_FOUND),
+ mLatestFailedRequestId(NAME_NOT_FOUND),
mCurrentAfTriggerId(0),
mCurrentPreCaptureTriggerId(0),
mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
@@ -3281,7 +3282,7 @@
ATRACE_CALL();
Mutex::Autolock l(mLatestRequestMutex);
status_t res;
- while (mLatestRequestId != requestId) {
+ while (mLatestRequestId != requestId && mLatestFailedRequestId != requestId) {
nsecs_t startTime = systemTime();
res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
@@ -4010,8 +4011,11 @@
sp<Camera3Device> parent = mParent.promote();
if (parent != nullptr) {
const String8& streamCameraId = outputStream->getPhysicalCameraId();
+ // Consider the case where clients are sending a single logical camera request
+ // to physical output/outputs
+ bool singleRequest = captureRequest->mSettingsList.size() == 1;
for (const auto& settings : captureRequest->mSettingsList) {
- if ((streamCameraId.isEmpty() &&
+ if (((streamCameraId.isEmpty() || singleRequest) &&
parent->getId() == settings.cameraId.c_str()) ||
streamCameraId == settings.cameraId.c_str()) {
outputStream->fireBufferRequestForFrameNumber(
@@ -4356,6 +4360,12 @@
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
captureRequest->mResultExtras);
}
+ {
+ Mutex::Autolock al(mLatestRequestMutex);
+
+ mLatestFailedRequestId = captureRequest->mResultExtras.requestId;
+ mLatestRequestSignal.signal();
+ }
}
// Remove yet-to-be submitted inflight request from inflightMap
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index b1dd135..aa1d55a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1142,6 +1142,7 @@
Condition mLatestRequestSignal;
// android.request.id for latest process_capture_request
int32_t mLatestRequestId;
+ int32_t mLatestFailedRequestId;
CameraMetadata mLatestRequest;
std::unordered_map<std::string, CameraMetadata> mLatestPhysicalRequest;