AudioFlinger: Extract inner Track classes
Finish removing inner Track classes from AudioFlinger.
Test: atest audiorecord_tests audiotrack_tests audiorouting_tests trackplayerbase_tests audiosystem_tests
Test: atest AudioTrackTest AudioRecordTest
Test: YouTube and Camera
Bug: 288339104
Bug: 288468076
Merged-In: Ib44c7eb854f9d447aa11223d76373b00c413a778
Change-Id: Ib44c7eb854f9d447aa11223d76373b00c413a778
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index fc2431b..b99e33f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2391,7 +2391,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;
@@ -3946,7 +3946,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 +3966,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(),
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 54e5cbc..ebff932 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -119,6 +119,7 @@
#include "android/media/BnEffect.h"
#include "Client.h"
+#include "ResamplerBufferProvider.h"
// include AudioFlinger component interfaces
#include "IAfEffect.h"
@@ -136,7 +137,6 @@
class FastMixer;
class IAudioManager;
class PassthruBufferProvider;
-class RecordBufferConverter;
class ServerProxy;
// ----------------------------------------------------------------------------
@@ -571,8 +571,6 @@
class AsyncCallbackThread;
class BitPerfectThread;
private:
- class Track;
- class RecordTrack;
class DeviceEffectManager;
// TODO(b/288339104) these should be separate files
public:
@@ -581,8 +579,9 @@
private:
struct AudioStreamIn;
struct TeePatch;
+public:
using TeePatches = std::vector<TeePatch>;
-
+private:
struct stream_type_t {
stream_type_t()
@@ -705,9 +704,12 @@
PlaybackThread *srcThread,
PlaybackThread *dstThread);
+public:
+ // TODO(b/288339104) cluster together
status_t moveAuxEffectToIo(int EffectId,
const sp<PlaybackThread>& dstThread,
sp<PlaybackThread> *srcThread);
+private:
// return thread associated with primary hardware device, or NULL
PlaybackThread *primaryPlaybackThread_l() const;
@@ -728,7 +730,10 @@
void removeClient_l(pid_t pid);
void removeNotificationClient(pid_t pid);
+public:
+ // TODO(b/288339104) cluster together
bool isNonOffloadableGlobalEffectEnabled_l();
+private:
void onNonOffloadableGlobalEffectEnable();
bool isSessionAcquired_l(audio_session_t audioSession);
@@ -783,8 +788,8 @@
};
struct TeePatch {
- sp<RecordThread::PatchRecord> patchRecord;
- sp<PlaybackThread::PatchTrack> patchTrack;
+ sp<IAfPatchRecord> patchRecord;
+ sp<IAfPatchTrack> patchTrack;
};
// for mAudioSessionRefs only
@@ -797,11 +802,13 @@
int mCnt;
};
+public:
+ // TODO(b/288339104) access by getter,
mutable Mutex mLock;
// 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:
@@ -910,9 +917,9 @@
size_t rejectedKVPSize, const String8& rejectedKVPs,
uid_t callingUid);
+public:
sp<IAudioManager> getOrCreateAudioManager();
-public:
// These methods read variables atomically without mLock,
// though the variables are updated with mLock.
bool isLowRamDevice() const { return mIsLowRamDevice; }
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
index bd2228b..541be0a 100644
--- a/services/audioflinger/IAfTrack.h
+++ b/services/audioflinger/IAfTrack.h
@@ -223,6 +223,9 @@
// 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).
@@ -230,6 +233,31 @@
// Only one AIDL IAudioTrack interface adapter should be created per Track.
static sp<media::IAudioTrack> createIAudioTrackAdapter(const sp<IAfTrack>& track);
+ static sp<IAfTrack> create( // TODO(b/288339104) void*
+ void* /* AudioFlinger::PlaybackThread */ 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;
@@ -316,11 +344,66 @@
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/288339104) 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:
+ // TODO(b/288339104) void*
+ static sp<IAfOutputTrack> create(
+ void* /* AudioFlinger::PlaybackThread */ playbackThread,
+ void* /* AudioFlinger::DuplicatingThread */ 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;
@@ -333,6 +416,18 @@
class IAfMmapTrack : public virtual IAfTrackBase {
public:
+ // TODO(b/288339104) void*
+ static sp<IAfMmapTrack> create(void* /*AudioFlinger::ThreadBase */ 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
@@ -348,6 +443,8 @@
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
@@ -357,6 +454,24 @@
// Only one AIDL IAudioRecord interface adapter should be created per RecordTrack.
static sp<media::IAudioRecord> createIAudioRecordAdapter(const sp<IAfRecordTrack>& recordTrack);
+ // TODO(b/288339104) void*
+ static sp<IAfRecordTrack> create(void* /* AudioFlinger::RecordThread */ 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
@@ -386,6 +501,12 @@
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.
@@ -401,13 +522,32 @@
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 {};
+class IAfPatchTrack : public virtual IAfTrack, public virtual IAfPatchTrackBase {
+public:
+ static sp<IAfPatchTrack> create(
+ void * /* PlaybackThread */ playbackThread, // TODO(b/288339104)
+ 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. */);
+};
// Abstraction for the Audio Source for the RecordThread (HAL or PassthruPatchRecord).
struct Source {
@@ -420,6 +560,27 @@
class IAfPatchRecord : public virtual IAfRecordTrack, public virtual IAfPatchTrackBase {
public:
+ static sp<IAfPatchRecord> create(
+ void* /* RecordThread */ recordThread, // TODO(b/288339104)
+ 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(
+ void* /* RecordThread */ recordThread, // TODO(b/288339104)
+ 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;
};
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index 0ab1adb..081af74 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -15,14 +15,14 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+namespace android {
// playback track
class MmapTrack : public TrackBase, public IAfMmapTrack {
public:
- MmapTrack(ThreadBase *thread,
+ MmapTrack(AudioFlinger::ThreadBase* thread,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
@@ -87,3 +87,4 @@
GUARDED_BY(AudioFlinger::MmapPlaybackThread::mLock);
}; // end of Track
+} // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 7063ff0..cb74292 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -546,7 +546,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 +558,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 +577,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 +602,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,
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 2c5e47c..e693486 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -216,9 +216,9 @@
// 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;
+ Endpoint<PlaybackThread, IAfPatchTrack> mPlayback;
// connects source device to record thread input
- Endpoint<RecordThread, RecordThread::PatchRecord> mRecord;
+ Endpoint<RecordThread, IAfPatchRecord> mRecord;
wp<ThreadBase> mThread;
bool mIsEndpointPatch;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 5467629..c549f3f 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -15,13 +15,12 @@
** 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>
+namespace android {
+
// Checks and monitors OP_PLAY_AUDIO
class OpPlayAudioMonitor : public RefBase {
friend class sp<OpPlayAudioMonitor>;
@@ -69,7 +68,7 @@
// playback track
class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider {
public:
- Track( PlaybackThread *thread,
+ Track(AudioFlinger::PlaybackThread* thread,
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
@@ -191,9 +190,10 @@
// This function should be called with holding thread lock.
void updateTeePatches_l() final;
void setTeePatchesToUpdate_l(const void* teePatchesToUpdate) final {
- setTeePatchesToUpdate_l(*reinterpret_cast<const TeePatches*>(teePatchesToUpdate));
+ setTeePatchesToUpdate_l( // TODO(b/288339104) void*
+ *reinterpret_cast<const AudioFlinger::TeePatches*>(teePatchesToUpdate));
}
- void setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate);
+ void setTeePatchesToUpdate_l(AudioFlinger::TeePatches teePatchesToUpdate);
void tallyUnderrunFrames(size_t frames) final {
if (isOut()) { // we expect this from output tracks only
@@ -235,34 +235,35 @@
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;
}
@@ -273,7 +274,6 @@
void signalClientFlag(int32_t flag);
-public:
void triggerEvents(AudioSystem::sync_event_t type) final;
void invalidate() final;
void disable() final;
@@ -282,11 +282,32 @@
// 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
@@ -368,8 +389,8 @@
bool mFlushHwPending; // track requests for thread flush
bool mPauseHwPending = false; // direct/offload track request for thread pause
audio_output_flags_t mFlags;
- TeePatches mTeePatches;
- std::optional<TeePatches> mTeePatchesToUpdate;
+ AudioFlinger::TeePatches mTeePatches;
+ std::optional<AudioFlinger::TeePatches> mTeePatchesToUpdate;
const float mSpeed;
const bool mIsSpatialized;
const bool mIsBitPerfect;
@@ -390,8 +411,8 @@
void *mBuffer;
};
- OutputTrack(PlaybackThread *thread,
- DuplicatingThread *sourceThread,
+ OutputTrack(AudioFlinger::PlaybackThread* thread,
+ AudioFlinger::DuplicatingThread* sourceThread,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@@ -436,7 +457,7 @@
Vector < Buffer* > mBufferQueue;
AudioBufferProvider::Buffer mOutBuffer;
bool mActive;
- DuplicatingThread* const mSourceThread; // for waitTimeMs() in write()
+ AudioFlinger::DuplicatingThread* const mSourceThread; // for waitTimeMs() in write()
sp<AudioTrackClientProxy> mClientProxy;
/** Attributes of the source tracks.
@@ -458,8 +479,7 @@
// playback track, used by PatchPanel
class PatchTrack : public Track, public PatchTrackBase, public IAfPatchTrack {
public:
-
- PatchTrack(PlaybackThread *playbackThread,
+ PatchTrack(AudioFlinger::PlaybackThread* playbackThread,
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
@@ -492,3 +512,5 @@
private:
void restartIfDisabled();
}; // end of PatchTrack
+
+} // namespace android
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index ad627d7..9d25ba4 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -15,16 +15,16 @@
** limitations under the License.
*/
+#pragma once
+
#include <android/content/AttributionSourceState.h>
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+namespace android {
// record track
class RecordTrack : public TrackBase, public virtual IAfRecordTrack {
public:
- RecordTrack(RecordThread *thread,
+ RecordTrack(AudioFlinger::RecordThread* thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
@@ -85,15 +85,27 @@
using MetadataInserter = std::back_insert_iterator<SinkMetadatas>;
void copyMetadataTo(MetadataInserter& backInserter) const final;
+ 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
@@ -106,7 +118,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;
@@ -121,8 +133,7 @@
// playback track, used by PatchPanel
class PatchRecord : public RecordTrack, public PatchTrackBase, public IAfPatchRecord {
public:
-
- PatchRecord(RecordThread *recordThread,
+ PatchRecord(AudioFlinger::RecordThread* recordThread,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
audio_format_t format,
@@ -158,7 +169,7 @@
class PassthruPatchRecord : public PatchRecord, public Source {
public:
- PassthruPatchRecord(RecordThread *recordThread,
+ PassthruPatchRecord(AudioFlinger::RecordThread* recordThread,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
audio_format_t format,
@@ -201,7 +212,7 @@
PassthruPatchRecord& mPassthru;
};
- sp<StreamInHalInterface> obtainStream(sp<ThreadBase>* thread);
+ sp<StreamInHalInterface> obtainStream(sp<AudioFlinger::ThreadBase>* thread);
PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
std::unique_ptr<void, decltype(free)*> mSinkBuffer; // frame size aligned continuous buffer
@@ -213,3 +224,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 07f0373..8c68751 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2208,7 +2208,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) {
@@ -2228,7 +2228,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 */);
@@ -2275,7 +2275,7 @@
}
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
+sp<IAfTrack> AudioFlinger::PlaybackThread::createTrack_l(
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
@@ -2300,7 +2300,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;
@@ -2593,7 +2593,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) {
@@ -2615,11 +2615,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;
@@ -2752,7 +2752,7 @@
}
// addTrack_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
+status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<IAfTrack>& track)
NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
status_t status = ALREADY_EXISTS;
@@ -2762,12 +2762,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());
@@ -2793,15 +2793,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());
@@ -2841,7 +2841,7 @@
}
}
- track->mResetDone = false;
+ track->setResetDone(false);
track->resetPresentationComplete();
mActiveTracks.add(track);
if (chain != 0) {
@@ -2858,25 +2858,25 @@
return status;
}
-bool AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
+bool AudioFlinger::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 AudioFlinger::PlaybackThread::removeTrack_l(const sp<IAfTrack>& track)
{
track->triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
@@ -2890,12 +2890,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) {
@@ -3223,7 +3223,7 @@
}
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);
}
@@ -3274,7 +3274,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());
}
@@ -3325,7 +3325,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;
@@ -3342,7 +3342,7 @@
}
void AudioFlinger::PlaybackThread::threadLoop_removeTracks(
- [[maybe_unused]] const Vector< sp<Track> >& tracksToRemove)
+ [[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.
@@ -3493,7 +3493,7 @@
{
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.
@@ -3548,7 +3548,7 @@
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;
@@ -3572,7 +3572,7 @@
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());
@@ -3586,7 +3586,7 @@
}
// getTrackById_l must be called with holding thread lock
-AudioFlinger::PlaybackThread::Track* AudioFlinger::PlaybackThread::getTrackById_l(
+IAfTrack* AudioFlinger::PlaybackThread::getTrackById_l(
audio_port_handle_t trackPortId) {
for (size_t i = 0; i < mTracks.size(); i++) {
if (mTracks[i]->portId() == trackPortId) {
@@ -3680,7 +3680,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);
@@ -3690,7 +3690,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);
@@ -3742,7 +3742,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);
@@ -3752,7 +3752,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();
@@ -3765,14 +3765,14 @@
}
status_t AudioFlinger::PlaybackThread::attachAuxEffect(
- const sp<AudioFlinger::PlaybackThread::Track>& track, int EffectId)
+ 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)
+ const sp<IAfTrack>& track, int EffectId)
{
status_t status = NO_ERROR;
@@ -3797,7 +3797,7 @@
void AudioFlinger::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);
}
@@ -3809,7 +3809,7 @@
{
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.
@@ -3864,7 +3864,7 @@
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.
//
@@ -4082,14 +4082,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);
}
}
}
@@ -4564,10 +4565,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);
@@ -4595,7 +4596,7 @@
}
// removeTracks_l() must be called with ThreadBase::mLock held
-void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
+void AudioFlinger::PlaybackThread::removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove)
NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
for (const auto& track : tracksToRemove) {
@@ -4822,13 +4823,13 @@
return status;
}
-void AudioFlinger::PlaybackThread::addPatchTrack(const sp<PatchTrack>& track)
+void AudioFlinger::PlaybackThread::addPatchTrack(const sp<IAfPatchTrack>& track)
{
Mutex::Autolock _l(mLock);
mTracks.add(track);
}
-void AudioFlinger::PlaybackThread::deletePatchTrack(const sp<PatchTrack>& track)
+void AudioFlinger::PlaybackThread::deletePatchTrack(const sp<IAfPatchTrack>& track)
{
Mutex::Autolock _l(mLock);
destroyTrack_l(track);
@@ -5295,7 +5296,7 @@
// prepareTracks_l() must be called with ThreadBase::mLock held
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
- Vector< sp<Track> > *tracksToRemove)
+ Vector<sp<IAfTrack>>* tracksToRemove)
{
// clean up deleted track ids in AudioMixer before allocating new tracks
(void)mTracks.processDeletedTrackIds([this](int trackId) {
@@ -5371,23 +5372,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()) {
@@ -5405,7 +5406,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];
@@ -5415,13 +5416,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;
@@ -5431,30 +5432,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
@@ -5468,7 +5469,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;
@@ -5479,10 +5480,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
@@ -5499,7 +5500,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
@@ -5509,20 +5510,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();
@@ -5531,7 +5532,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;
@@ -5546,7 +5547,7 @@
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));
@@ -5582,13 +5583,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();
@@ -5610,14 +5611,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;
@@ -5630,8 +5631,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);
@@ -5681,11 +5682,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;
@@ -5706,9 +5707,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;
@@ -5770,18 +5771,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);
@@ -5889,13 +5890,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
@@ -5947,7 +5949,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);
@@ -6023,7 +6025,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();
}
@@ -6215,14 +6217,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);
}
@@ -6426,12 +6428,12 @@
}
}
-void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTrack)
+void AudioFlinger::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];
@@ -6507,8 +6509,8 @@
void AudioFlinger::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) {
@@ -6531,7 +6533,7 @@
}
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
- Vector< sp<Track> > *tracksToRemove
+ Vector<sp<IAfTrack>>* tracksToRemove
)
{
size_t count = mActiveTracks.size();
@@ -6540,14 +6542,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
@@ -6555,7 +6557,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()) {
@@ -6591,8 +6593,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.
@@ -6604,7 +6606,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;
@@ -6622,8 +6624,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;
@@ -6636,7 +6638,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
@@ -6648,7 +6650,7 @@
mPreviousTrack = track;
// reset retry count
- track->mRetryCount = targetRetryCount;
+ track->retryCount() = targetRetryCount;
mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
if (mHwPaused) {
@@ -6663,7 +6665,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;
@@ -6681,7 +6683,7 @@
mOutput->presentationComplete();
}
if (track->isStopping_2()) {
- track->mState = TrackBase::STOPPED;
+ track->setState(IAfTrackBase::STOPPED);
}
if (track->isStopped()) {
track->reset();
@@ -6694,9 +6696,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);
@@ -6824,7 +6826,7 @@
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));
@@ -7086,7 +7088,7 @@
}
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTracks_l(
- Vector< sp<Track> > *tracksToRemove
+ Vector<sp<IAfTrack>>* tracksToRemove
)
{
size_t count = mActiveTracks.size();
@@ -7098,8 +7100,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
@@ -7107,7 +7109,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()) {
@@ -7116,7 +7118,7 @@
continue;
}
- if (track->mState == TrackBase::IDLE) {
+ if (track->state() == IAfTrackBase::IDLE) {
ALOGW("An idle track shouldn't be in active list");
continue;
}
@@ -7148,9 +7150,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) {
@@ -7182,8 +7184,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;
@@ -7191,7 +7193,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
@@ -7217,9 +7219,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;
@@ -7227,7 +7229,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.
@@ -7235,7 +7237,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
@@ -7255,13 +7258,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();
@@ -7281,9 +7284,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());
@@ -7526,7 +7529,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,
@@ -7939,7 +7942,7 @@
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();
@@ -7953,7 +7956,7 @@
inputStandBy();
reacquire_wakelock:
- sp<RecordTrack> activeTrack;
+ sp<IAfRecordTrack> activeTrack;
{
Mutex::Autolock _l(mLock);
acquireWakeLock_l();
@@ -7969,13 +7972,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;
@@ -8028,40 +8031,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);
@@ -8308,7 +8311,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);
@@ -8365,16 +8368,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;
}
@@ -8388,7 +8391,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
@@ -8396,14 +8399,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",
@@ -8412,9 +8416,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);
}
@@ -8424,17 +8428,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) {
@@ -8463,7 +8468,7 @@
// update frame information and push timestamp out
activeTrack->updateTrackFrameInfo(
- activeTrack->mServerProxy->framesReleased(),
+ activeTrack->serverProxy()->framesReleased(),
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER],
mSampleRate, mTimestamp);
}
@@ -8496,7 +8501,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();
@@ -8560,7 +8565,7 @@
}
// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
+sp<IAfRecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
@@ -8579,7 +8584,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;
@@ -8725,10 +8730,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();
@@ -8758,7 +8763,7 @@
return track;
}
-status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
+status_t AudioFlinger::RecordThread::start(IAfRecordTrack* recordTrack,
AudioSystem::sync_event_t event,
audio_session_t triggerSession)
{
@@ -8769,7 +8774,7 @@
if (event == AudioSystem::SYNC_EVENT_NONE) {
recordTrack->clearSyncStartEvent();
} else if (event != AudioSystem::SYNC_EVENT_SAME) {
- recordTrack->mSynchronizedRecordState.startRecording(
+ recordTrack->synchronizedRecordState().startRecording(
mAudioFlinger->createSyncEvent(
event, triggerSession,
recordTrack->sessionId(), syncStartEventCallback, recordTrack));
@@ -8784,13 +8789,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;
}
@@ -8798,7 +8803,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();
@@ -8806,16 +8811,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();
@@ -8842,12 +8847,12 @@
// 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;
@@ -8868,31 +8873,31 @@
}
}
-bool AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
+bool AudioFlinger::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;
}
@@ -8916,7 +8921,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;
@@ -9021,7 +9026,7 @@
}
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);
@@ -9031,10 +9036,10 @@
}
// destroyTrack_l() must be called with ThreadBase::mLock held
-void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track)
+void AudioFlinger::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) {
@@ -9042,7 +9047,7 @@
}
}
-void AudioFlinger::RecordThread::removeTrack_l(const sp<RecordTrack>& track)
+void AudioFlinger::RecordThread::removeTrack_l(const sp<IAfRecordTrack>& track)
{
String8 result;
track->appendDump(result, false /* active */);
@@ -9097,7 +9102,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) {
@@ -9117,7 +9122,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 */);
@@ -9132,17 +9137,17 @@
{
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 = sp<AudioFlinger::ThreadBase>::cast(mRecordTrack->thread().promote());
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread *>(threadBase.get());
mRsmpInUnrel = 0;
const int32_t rear = recordThread->mRsmpInRear;
ssize_t deltaFrames = 0;
@@ -9162,11 +9167,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 = sp<AudioFlinger::ThreadBase>::cast(mRecordTrack->thread().promote());
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread *>(threadBase.get());
const int32_t rear = recordThread->mRsmpInRear;
const int32_t front = mRsmpInFront;
const ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
@@ -9196,16 +9201,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 = sp<AudioFlinger::ThreadBase>::cast(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<AudioFlinger::RecordThread *>(threadBase.get());
int32_t rear = recordThread->mRsmpInRear;
int32_t front = mRsmpInFront;
ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
@@ -9239,7 +9244,7 @@
}
// AudioBufferProvider interface
-void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer(
+void ResamplerBufferProvider::releaseBuffer(
AudioBufferProvider::Buffer* buffer)
{
int32_t stepCount = static_cast<int32_t>(buffer->frameCount);
@@ -9453,7 +9458,7 @@
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);
@@ -9604,7 +9609,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) {
@@ -9624,9 +9629,9 @@
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);
}
}
@@ -9723,7 +9728,7 @@
mRsmpInBuffer = rsmpInBuffer;
}
-void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
+void AudioFlinger::RecordThread::addPatchTrack(const sp<IAfPatchRecord>& record)
{
Mutex::Autolock _l(mLock);
mTracks.add(record);
@@ -9732,7 +9737,7 @@
}
}
-void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
+void AudioFlinger::RecordThread::deletePatchTrack(const sp<IAfPatchRecord>& record)
{
Mutex::Autolock _l(mLock);
if (mSource == record->getSource()) {
@@ -9832,14 +9837,14 @@
void AudioFlinger::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.
@@ -10004,7 +10009,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);
@@ -10016,7 +10022,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();
@@ -10061,8 +10067,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;
@@ -10419,7 +10425,7 @@
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();
@@ -10447,7 +10453,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();
@@ -10519,7 +10525,7 @@
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) {
@@ -10556,7 +10562,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 */);
}
@@ -10663,7 +10669,7 @@
{
Mutex::Autolock _l(mLock);
if (streamType == mStreamType) {
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
track->invalidate();
}
broadcast_l();
@@ -10674,7 +10680,7 @@
{
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;
@@ -10731,7 +10737,7 @@
}
}
}
- for (const sp<MmapTrack> &track : mActiveTracks) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
track->setMetadataHasChanged();
track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
/*muteState=*/{mMasterMute,
@@ -10751,7 +10757,7 @@
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 = {
@@ -10916,7 +10922,7 @@
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 = {
@@ -10970,7 +10976,7 @@
: MixerThread(audioflinger, output, id, systemReady, BIT_PERFECT) {}
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::BitPerfectThread::prepareTracks_l(
- Vector<sp<Track>> *tracksToRemove) {
+ 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;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 8b420c0..51aeb7e 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -21,10 +21,11 @@
public: // TODO(b/288339104) extract out of AudioFlinger class
class ThreadBase : public Thread {
+ // TODO(b/288339104) remove friends
+ friend class RecordTrack;
+ friend class Track;
+ friend class TrackBase;
public:
-
-#include "TrackBase.h"
-
enum type_t {
MIXER, // Thread class is MixerThread
DIRECT, // Thread class is DirectOutputThread
@@ -488,7 +489,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()) {
@@ -568,7 +569,7 @@
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();
}
@@ -861,10 +862,11 @@
// --- PlaybackThread ---
class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback,
public VolumeInterface, public StreamOutHalInterfaceEventCallback {
+ // TODO(b/288339104) remove friends
+ friend class OutputTrack;
+ friend class Track;
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
@@ -913,14 +915,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
@@ -976,7 +978,7 @@
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,
@@ -1021,14 +1023,14 @@
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
// Consider also removing and passing an explicit mMainBuffer initialization
- // parameter to AF::PlaybackThread::Track::Track().
+ // parameter to AF::IAfTrack::Track().
float *sinkBuffer() const {
return reinterpret_cast<float *>(mSinkBuffer); };
virtual void detachAuxEffect_l(int effectId);
- status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track,
+ status_t attachAuxEffect(const sp<IAfTrack>& track,
int EffectId);
- status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track>& track,
+ status_t attachAuxEffect_l(const sp<IAfTrack>& track,
int EffectId);
virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain);
@@ -1058,8 +1060,8 @@
status_t getTimestamp_l(AudioTimestamp& timestamp);
- void addPatchTrack(const sp<PatchTrack>& track);
- void deletePatchTrack(const sp<PatchTrack>& track);
+ void addPatchTrack(const sp<IAfPatchTrack>& track);
+ void deletePatchTrack(const sp<IAfPatchTrack>& track);
virtual void toAudioPortConfig(struct audio_port_config *config);
@@ -1096,7 +1098,7 @@
mDownStreamPatch = *patch;
}
- PlaybackThread::Track* getTrackById_l(audio_port_handle_t trackId);
+ IAfTrack* getTrackById_l(audio_port_handle_t trackId);
bool hasMixer() const {
return mType == MIXER || mType == DUPLICATING || mType == SPATIALIZER;
@@ -1259,7 +1261,7 @@
}
protected:
- ActiveTracks<Track> mActiveTracks;
+ ActiveTracks<IAfTrack> mActiveTracks;
// Time to sleep between cycles when:
virtual uint32_t activeSleepTimeUs() const; // mixer state MIXER_TRACKS_ENABLED
@@ -1304,9 +1306,9 @@
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);
+ bool destroyTrack_l(const sp<IAfTrack>& track);
+ void removeTrack_l(const sp<IAfTrack>& track);
void readOutputParameters_l();
MetadataUpdate updateMetadata_l() final;
@@ -1364,7 +1366,7 @@
SortedVector<sp<T>> mTracks; // wrapped SortedVector.
};
- Tracks<Track> mTracks;
+ Tracks<IAfTrack> mTracks;
stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
AudioStreamOut *mOutput;
@@ -1425,7 +1427,7 @@
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
@@ -1533,7 +1535,7 @@
audio_channel_mask_t channelMask, audio_format_t format,
audio_session_t sessionId, uid_t uid) const override;
protected:
- virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+ virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
virtual uint32_t idleSleepTimeUs() const;
virtual uint32_t suspendSleepTimeUs() const;
virtual void cacheParameters_l();
@@ -1663,7 +1665,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();
@@ -1679,13 +1681,13 @@
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, 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;
@@ -1725,7 +1727,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();
@@ -1812,8 +1814,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(
@@ -1864,55 +1866,12 @@
// record thread
class RecordThread : public ThreadBase
{
+ // TODO(b/288339104) remove friends
+ friend class PassthruPatchRecord;
+ friend class RecordTrack;
+ friend class ResamplerBufferProvider;
public:
- 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,
AudioStreamIn *input,
@@ -1922,8 +1881,8 @@
virtual ~RecordThread();
// no addTrack_l ?
- void destroyTrack_l(const sp<RecordTrack>& track);
- void removeTrack_l(const sp<RecordTrack>& track);
+ void destroyTrack_l(const sp<IAfRecordTrack>& track);
+ void removeTrack_l(const sp<IAfRecordTrack>& track);
// Thread virtuals
virtual bool threadLoop();
@@ -1938,7 +1897,7 @@
virtual sp<IMemory> pipeMemory() const { 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,13 +1914,13 @@
audio_port_handle_t portId,
int32_t maxSharedAudioHistoryMs);
- status_t start(RecordTrack* recordTrack,
+ status_t start(IAfRecordTrack* recordTrack,
AudioSystem::sync_event_t event,
audio_session_t triggerSession);
// 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);
AudioStreamIn* clearInput();
virtual sp<StreamHalInterface> stream() const;
@@ -1979,8 +1938,8 @@
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);
+ void deletePatchTrack(const sp<IAfPatchRecord>& record);
void readInputParameters_l();
virtual uint32_t getInputFramesLost();
@@ -2066,10 +2025,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;
@@ -2139,9 +2098,6 @@
class MmapThread : public ThreadBase
{
public:
-
-#include "MmapTracks.h"
-
MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady,
bool isOut);
@@ -2258,7 +2214,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;
@@ -2363,7 +2319,7 @@
audio_io_handle_t id, bool systemReady);
protected:
- mixer_state prepareTracks_l(Vector<sp<Track>> *tracksToRemove) override;
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) override;
void threadLoop_mix() override;
private:
@@ -2372,4 +2328,4 @@
float mVolumeRight = 0.f;
};
-private:
+private:
\ No newline at end of file
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 7cd78c3..8f31468 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -15,14 +15,14 @@
** limitations under the License.
*/
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
- #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+namespace android {
// base for record and playback
class TrackBase : public ExtendedAudioBufferProvider, public virtual IAfTrackBase {
public:
- TrackBase(ThreadBase *thread,
+ TrackBase(AudioFlinger::ThreadBase* thread,
const sp<Client>& client,
const audio_attributes_t& mAttr,
uint32_t sampleRate,
@@ -322,7 +322,7 @@
// true for Track, false for RecordTrack,
// this could be a track type if needed later
- const wp<ThreadBase> mThread;
+ const wp<AudioFlinger::ThreadBase> mThread;
const alloc_type mAllocType;
/*const*/ sp<Client> mClient; // see explanation at ~TrackBase() why not const
sp<IMemory> mCblkMemory;
@@ -391,8 +391,8 @@
class PatchTrackBase : public PatchProxyBufferProvider, public virtual IAfPatchTrackBase
{
public:
- using Timeout = std::optional<std::chrono::nanoseconds>;
- PatchTrackBase(const sp<ClientProxy>& proxy, const ThreadBase& thread,
+ PatchTrackBase(const sp<ClientProxy>& proxy,
+ const AudioFlinger::ThreadBase& thread,
const Timeout& timeout);
void setPeerTimeout(std::chrono::nanoseconds timeout) final;
void setPeerProxy(const sp<IAfPatchTrackBase>& proxy, bool holdReference) final {
@@ -417,5 +417,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 fca9745..7bdd374 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -30,6 +30,10 @@
#include <private/media/AudioTrackShared.h>
#include "AudioFlinger.h"
+#include "TrackBase.h"
+#include "PlaybackTracks.h"
+#include "RecordTracks.h"
+#include "MmapTracks.h"
#include <media/nbaio/Pipe.h>
#include <media/nbaio/PipeReader.h>
@@ -76,8 +80,8 @@
static volatile int32_t nextTrackId = 55;
// TrackBase constructor must be called with AudioFlinger::mLock held
-AudioFlinger::ThreadBase::TrackBase::TrackBase(
- ThreadBase *thread,
+TrackBase::TrackBase(
+ AudioFlinger::ThreadBase *thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
@@ -253,7 +257,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 +268,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();
@@ -289,7 +293,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,16 +307,15 @@
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,
+ const AudioFlinger::ThreadBase& thread, const Timeout& timeout)
: mProxy(proxy)
{
if (timeout) {
@@ -325,7 +328,7 @@
}
}
-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;
}
@@ -555,8 +558,7 @@
// -------------------------------
// static
-sp<AudioFlinger::PlaybackThread::OpPlayAudioMonitor>
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
+sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
AudioFlinger::ThreadBase* thread,
const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
audio_stream_type_t streamType)
@@ -587,7 +589,7 @@
return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
}
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
+OpPlayAudioMonitor::OpPlayAudioMonitor(
AudioFlinger::ThreadBase* thread,
const AttributionSourceState& attributionSource,
audio_usage_t usage, int id, uid_t uid)
@@ -600,7 +602,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);
@@ -608,7 +610,7 @@
mOpCallback.clear();
}
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
+void OpPlayAudioMonitor::onFirstRef()
{
checkPlayAudioForUsage();
if (mAttributionSource.packageName.has_value()) {
@@ -618,14 +620,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()
+void OpPlayAudioMonitor::checkPlayAudioForUsage()
{
const bool hasAppOps = mAttributionSource.packageName.has_value()
&& mAppOpsManager.checkAudioOpNoThrow(
@@ -644,11 +646,11 @@
}
}
-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);
@@ -662,7 +664,7 @@
}
// static
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::getPackagesForUid(
+void OpPlayAudioMonitor::getPackagesForUid(
uid_t uid, Vector<String16>& packages)
{
PermissionController permissionController;
@@ -673,9 +675,57 @@
#undef LOG_TAG
#define LOG_TAG "AF::Track"
+/* static */
+sp<IAfTrack> IAfTrack::create( // TODO(b/288339104) void*
+ void * /* AudioFlinger::PlaybackThread */ 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(reinterpret_cast<AudioFlinger::PlaybackThread*>(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(
+ AudioFlinger::PlaybackThread *thread,
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
@@ -709,7 +759,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),
@@ -799,7 +849,7 @@
mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
}
-AudioFlinger::PlaybackThread::Track::~Track()
+Track::~Track()
{
ALOGV("%s(%d)", __func__, mId);
@@ -812,7 +862,7 @@
}
}
-status_t AudioFlinger::PlaybackThread::Track::initCheck() const
+status_t Track::initCheck() const
{
status_t status = TrackBase::initCheck();
if (status == NO_ERROR && mCblk == nullptr) {
@@ -821,7 +871,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
@@ -834,10 +884,10 @@
sp<Track> keep(this);
{ // scope for mLock
bool wasActive = false;
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
wasActive = playbackThread->destroyTrack_l(this);
forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
}
@@ -847,7 +897,7 @@
}
}
-void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result) const
+void Track::appendDumpHeader(String8& result) const
{
result.appendFormat("Type Id Active Client Session Port Id S Flags "
" Format Chn mask SRate "
@@ -858,7 +908,7 @@
isServerLatencySupported() ? " Latency" : "");
}
-void AudioFlinger::PlaybackThread::Track::appendDump(String8& result, bool active) const
+void Track::appendDump(String8& result, bool active) const
{
char trackType;
switch (mType) {
@@ -900,7 +950,7 @@
}
char fillingStatus;
- switch (mFillingUpStatus) {
+ switch (mFillingStatus) {
case FS_INVALID:
fillingStatus = 'I';
break;
@@ -986,12 +1036,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;
@@ -1009,14 +1059,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;
@@ -1026,12 +1076,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);
@@ -1047,7 +1097,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.
@@ -1056,12 +1106,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.
@@ -1078,14 +1128,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;
}
@@ -1099,21 +1149,21 @@
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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
if (isOffloaded()) {
Mutex::Autolock _laf(thread->mAudioFlinger->mLock);
@@ -1157,7 +1207,7 @@
__func__, mId, (int)mThreadIoHandle);
}
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
// states to reset position info for pcm tracks
if (audio_is_linear_pcm(mFormat)
@@ -1244,16 +1294,16 @@
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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
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();
+ auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
if (playbackThread->mActiveTracks.indexOf(this) < 0) {
reset();
mState = STOPPED;
@@ -1266,7 +1316,7 @@
// move to STOPPING_2 when drain completes and then STOPPED
mState = STOPPING_1;
if (isOffloaded()) {
- mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload;
+ mRetryCount = AudioFlinger::PlaybackThread::kMaxTrackStopRetriesOffload;
}
}
playbackThread->broadcast_l();
@@ -1277,13 +1327,13 @@
}
}
-void AudioFlinger::PlaybackThread::Track::pause()
+void Track::pause()
{
ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
switch (mState) {
case STOPPING_1:
case STOPPING_2:
@@ -1314,13 +1364,13 @@
}
}
-void AudioFlinger::PlaybackThread::Track::flush()
+void Track::flush()
{
ALOGV("%s(%d)", __func__, mId);
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.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.
@@ -1379,7 +1429,7 @@
}
// must be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::flushAck()
+void Track::flushAck()
{
if (!isOffloaded() && !isDirect()) {
return;
@@ -1392,12 +1442,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.
@@ -1405,7 +1455,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;
@@ -1413,34 +1463,35 @@
}
}
-status_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyValuePairs)
+status_t Track::setParameters(const String8& keyValuePairs)
{
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> 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() == AudioFlinger::ThreadBase::DIRECT) ||
+ (thread->type() == AudioFlinger::ThreadBase::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();
+ sp<AudioFlinger::ThreadBase> 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() == AudioFlinger::ThreadBase::DIRECT)
+ || (thread->type() == AudioFlinger::ThreadBase::OFFLOAD)) {
+ auto directOutputThread = static_cast<AudioFlinger::DirectOutputThread*>(thread.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)
{
@@ -1448,7 +1499,7 @@
if (isOffloadedOrDirect()) {
// Signal thread to fetch new volume.
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
thread->broadcast_l();
@@ -1457,7 +1508,7 @@
return status;
}
-sp<VolumeShaper::State> AudioFlinger::PlaybackThread::Track::getVolumeShaperState(int id) const
+sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
{
// Note: We don't check if Thread exists.
@@ -1465,7 +1516,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;
@@ -1481,7 +1532,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) {
@@ -1553,7 +1604,7 @@
*backInserter++ = metadata;
}
-void AudioFlinger::PlaybackThread::Track::updateTeePatches_l() {
+void Track::updateTeePatches_l() {
if (mTeePatchesToUpdate.has_value()) {
forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
mTeePatches = mTeePatchesToUpdate.value();
@@ -1565,14 +1616,14 @@
}
}
-void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
+void Track::setTeePatchesToUpdate_l(AudioFlinger::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) {
@@ -1604,30 +1655,31 @@
}
}
-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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread == 0) {
return INVALID_OPERATION;
}
Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.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();
+ sp<AudioFlinger::ThreadBase> 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()
+ auto dstThread = sp<AudioFlinger::PlaybackThread>::cast(thread);
+ // srcThread is initialized by call to moveAuxEffectToIo()
+ sp<AudioFlinger::PlaybackThread> srcThread;
sp<AudioFlinger> af = mClient->audioFlinger();
status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
@@ -1644,14 +1696,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.
@@ -1694,7 +1746,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.
@@ -1726,14 +1778,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) {
@@ -1748,7 +1800,7 @@
// implement VolumeBufferProvider interface
-gain_minifloat_packed_t AudioFlinger::PlaybackThread::Track::getVolumeLR() const
+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));
@@ -1773,7 +1825,7 @@
return vlr;
}
-status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(
+status_t Track::setSyncEvent(
const sp<audioflinger::SyncEvent>& event)
{
if (isTerminated() || mState == PAUSED ||
@@ -1789,19 +1841,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;
@@ -1811,23 +1863,23 @@
(void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
}
-void AudioFlinger::PlaybackThread::Track::signal()
+void Track::signal()
{
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
- PlaybackThread *t = (PlaybackThread *)thread.get();
+ auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Mutex::Autolock _l(t->mLock);
t->broadcast_l();
}
}
-status_t AudioFlinger::PlaybackThread::Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
+status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- PlaybackThread *t = (PlaybackThread *)thread.get();
+ auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Mutex::Autolock _l(t->mLock);
status = t->mOutput->stream->getDualMonoMode(mode);
ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
@@ -1837,13 +1889,13 @@
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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
+ auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Mutex::Autolock lock(t->mLock);
status = t->mOutput->stream->setDualMonoMode(mode);
if (status == NO_ERROR) {
@@ -1854,13 +1906,13 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::Track::getAudioDescriptionMixLevel(float* leveldB) const
+status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
+ auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Mutex::Autolock lock(t->mLock);
status = t->mOutput->stream->getAudioDescriptionMixLevel(leveldB);
ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
@@ -1870,13 +1922,13 @@
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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
+ auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Mutex::Autolock lock(t->mLock);
status = t->mOutput->stream->setAudioDescriptionMixLevel(leveldB);
if (status == NO_ERROR) {
@@ -1887,14 +1939,14 @@
return status;
}
-status_t AudioFlinger::PlaybackThread::Track::getPlaybackRateParameters(
+status_t Track::getPlaybackRateParameters(
audio_playback_rate_t* playbackRate) const
{
status_t status = INVALID_OPERATION;
if (isOffloadedOrDirect()) {
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
+ auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Mutex::Autolock lock(t->mLock);
status = t->mOutput->stream->getPlaybackRateParameters(playbackRate);
ALOGD_IF((status == NO_ERROR) &&
@@ -1905,14 +1957,14 @@
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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != nullptr) {
- auto t = static_cast<PlaybackThread *>(thread.get());
+ auto* const t = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
Mutex::Autolock lock(t->mLock);
status = t->mOutput->stream->setPlaybackRateParameters(playbackRate);
if (status == NO_ERROR) {
@@ -1924,7 +1976,7 @@
}
//To be called with thread lock held
-bool AudioFlinger::PlaybackThread::Track::isResumePending() {
+bool Track::isResumePending() const {
if (mState == RESUMING) {
return true;
}
@@ -1938,7 +1990,7 @@
}
//To be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::resumeAck() {
+void Track::resumeAck() {
if (mState == RESUMING) {
mState = ACTIVE;
}
@@ -1952,7 +2004,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.
@@ -2032,12 +2084,12 @@
}
}
-bool AudioFlinger::PlaybackThread::Track::AudioVibrationController::setMute(bool muted) {
- sp<ThreadBase> thread = mTrack->mThread.promote();
+bool Track::AudioVibrationController::setMute(bool muted) {
+ sp<AudioFlinger::ThreadBase> thread = mTrack->mThread.promote();
if (thread != 0) {
// Lock for updating mHapticPlaybackEnabled.
Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
&& playbackThread->mHapticChannelCount > 0) {
ALOGD("%s, haptic playback was %s for track %d",
@@ -2049,13 +2101,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();
@@ -2065,9 +2117,28 @@
#undef LOG_TAG
#define LOG_TAG "AF::OutputTrack"
-AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
- PlaybackThread *playbackThread,
- DuplicatingThread *sourceThread,
+/* static */
+sp<IAfOutputTrack> IAfOutputTrack::create( // TODO(b/288339104) void*
+ void* /* AudioFlinger::PlaybackThread */ playbackThread,
+ void* /* AudioFlinger::DuplicatingThread */ sourceThread,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount,
+ const AttributionSourceState& attributionSource) {
+ return sp<OutputTrack>::make(
+ reinterpret_cast<AudioFlinger::PlaybackThread*>(playbackThread),
+ reinterpret_cast<AudioFlinger::DuplicatingThread*>(sourceThread),
+ sampleRate,
+ format,
+ channelMask,
+ frameCount,
+ attributionSource);
+}
+
+OutputTrack::OutputTrack(
+ AudioFlinger::PlaybackThread *playbackThread,
+ AudioFlinger::DuplicatingThread *sourceThread,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@@ -2102,13 +2173,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);
@@ -2121,7 +2192,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::OutputTrack::stop()
+void OutputTrack::stop()
{
Track::stop();
clearBufferQueue();
@@ -2129,10 +2200,10 @@
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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != nullptr && thread->standby()) {
// preload one silent buffer to trigger mixer on start()
ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
@@ -2151,7 +2222,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 = static_cast<AudioFlinger::PlaybackThread*>(thread.get());
if (!pt->waitForHalStart()) {
ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
stop();
@@ -2240,7 +2311,7 @@
// If we could not write all frames, allocate a buffer and queue it for next time.
if (inBuffer.frameCount) {
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0 && !thread->standby()) {
queueBuffer(inBuffer);
}
@@ -2255,7 +2326,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;
@@ -2278,13 +2349,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;
@@ -2293,7 +2364,7 @@
setMetadataHasChanged();
}
-status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
+status_t OutputTrack::obtainBuffer(
AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
{
ClientProxy::Buffer buf;
@@ -2307,7 +2378,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
+void OutputTrack::clearBufferQueue()
{
size_t size = mBufferQueue.size();
@@ -2319,7 +2390,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)) {
@@ -2331,7 +2402,38 @@
#undef LOG_TAG
#define LOG_TAG "AF::PatchTrack"
-AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThread,
+/* static */
+sp<IAfPatchTrack> IAfPatchTrack::create(
+ void* /* PlaybackThread */ playbackThread, // TODO(b/288339104)
+ 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(
+ reinterpret_cast<AudioFlinger::PlaybackThread*>(playbackThread),
+ streamType,
+ sampleRate,
+ channelMask,
+ format,
+ frameCount,
+ buffer,
+ bufferSize,
+ flags,
+ timeout,
+ frameCountToBeReady);
+}
+
+PatchTrack::PatchTrack(AudioFlinger::PlaybackThread *playbackThread,
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
@@ -2358,12 +2460,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();
@@ -2372,7 +2474,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);
@@ -2384,7 +2486,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);
@@ -2410,7 +2512,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;
@@ -2420,7 +2522,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;
@@ -2437,7 +2539,7 @@
return status;
}
-void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
+void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
{
mProxy->releaseBuffer(buffer);
restartIfDisabled();
@@ -2446,23 +2548,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 (sp<AudioFlinger::ThreadBase> thread = mThread.promote();
thread != 0) {
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ auto* const playbackThread = static_cast<AudioFlinger::PlaybackThread*>(thread.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);
@@ -2565,9 +2667,47 @@
#undef LOG_TAG
#define LOG_TAG "AF::RecordTrack"
+
+/* static */ // TODO(b/288339104)
+sp<IAfRecordTrack> IAfRecordTrack::create(void* /*AudioFlinger::RecordThread */ 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(
+ reinterpret_cast<AudioFlinger::RecordThread*>(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(
+ AudioFlinger::RecordThread* thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
@@ -2642,14 +2782,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) {
@@ -2659,7 +2799,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;
@@ -2673,12 +2813,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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
return recordThread->start(this, event, triggerSession);
} else {
ALOGW("%s track %d: thread was destroyed", __func__, portId());
@@ -2686,27 +2826,27 @@
}
}
-void AudioFlinger::RecordThread::RecordTrack::stop()
+void RecordTrack::stop()
{
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
- RecordThread *recordThread = (RecordThread *) thread.get();
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
priorState = mState;
if (!mSharedAudioPackageName.empty()) {
recordThread->resetAudioHistory_l();
@@ -2737,7 +2877,7 @@
}
}
-void AudioFlinger::RecordThread::RecordTrack::invalidate()
+void RecordTrack::invalidate()
{
TrackBase::invalidate();
// FIXME should use proxy, and needs work
@@ -2749,7 +2889,7 @@
}
-void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) const
+void RecordTrack::appendDumpHeader(String8& result) const
{
result.appendFormat("Active Id Client Session Port Id S Flags "
" Format Chn mask SRate Source "
@@ -2757,7 +2897,7 @@
isServerLatencySupported() ? " Latency" : "");
}
-void AudioFlinger::RecordThread::RecordTrack::appendDump(String8& result, bool active) const
+void RecordTrack::appendDump(String8& result, bool active) const
{
result.appendFormat("%c%5s %6d %6u %7u %7u %2s 0x%03X "
"%08X %08X %6u %6X "
@@ -2796,11 +2936,11 @@
}
// 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();
+ sp<AudioFlinger::ThreadBase> threadBase = mThread.promote();
if (threadBase != 0) {
// TODO: use actual buffer filling status instead of 2 buffers when info is available
// from audio HAL
@@ -2810,12 +2950,12 @@
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)
{
@@ -2855,40 +2995,40 @@
mServerLatencyMs.store(latencyMs);
}
-status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
+status_t RecordTrack::getActiveMicrophones(
std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
{
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.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();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.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) {
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.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();
@@ -2905,9 +3045,9 @@
return PERMISSION_DENIED;
}
- sp<ThreadBase> thread = mThread.promote();
+ sp<AudioFlinger::ThreadBase> thread = mThread.promote();
if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread*>(thread.get());
status_t status = recordThread->shareAudioHistory(
sharedAudioPackageName, mSessionId, sharedAudioStartMs);
if (status == NO_ERROR) {
@@ -2919,7 +3059,7 @@
}
}
-void AudioFlinger::RecordThread::RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
{
// Do not forward PatchRecord metadata with unspecified audio source
@@ -2943,7 +3083,33 @@
#undef LOG_TAG
#define LOG_TAG "AF::PatchRecord"
-AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,
+/* static */
+sp<IAfPatchRecord> IAfPatchRecord::create(
+ void* /* RecordThread */ recordThread, // TODO(b/288339104)
+ 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(
+ reinterpret_cast<AudioFlinger::RecordThread*>(recordThread),
+ sampleRate,
+ channelMask,
+ format,
+ frameCount,
+ buffer,
+ bufferSize,
+ flags,
+ timeout,
+ source);
+}
+
+PatchRecord::PatchRecord(AudioFlinger::RecordThread *recordThread,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
audio_format_t format,
@@ -2968,7 +3134,7 @@
(int)(mPeerTimeout.tv_nsec / 1000000));
}
-AudioFlinger::RecordThread::PatchRecord::~PatchRecord()
+PatchRecord::~PatchRecord()
{
ALOGV("%s(%d)", __func__, mId);
}
@@ -2992,7 +3158,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);
@@ -3007,7 +3173,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);
@@ -3029,7 +3195,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;
@@ -3039,13 +3205,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);
}
@@ -3060,8 +3226,28 @@
return {ptr, free};
}
-AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord(
- RecordThread *recordThread,
+/* static */
+sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
+ void* /* RecordThread */ recordThread, // TODO(b/288339104)
+ 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(
+ reinterpret_cast<AudioFlinger::RecordThread*>(recordThread),
+ sampleRate,
+ channelMask,
+ format,
+ frameCount,
+ flags,
+ source);
+}
+
+PassthruPatchRecord::PassthruPatchRecord(
+ AudioFlinger::RecordThread* recordThread,
uint32_t sampleRate,
audio_channel_mask_t channelMask,
audio_format_t format,
@@ -3077,18 +3263,18 @@
memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
}
-sp<StreamInHalInterface> AudioFlinger::RecordThread::PassthruPatchRecord::obtainStream(
- sp<ThreadBase>* thread)
+sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
+ sp<AudioFlinger::ThreadBase>* thread)
{
*thread = mThread.promote();
if (!*thread) return nullptr;
- RecordThread *recordThread = static_cast<RecordThread*>((*thread).get());
+ auto* const recordThread = static_cast<AudioFlinger::RecordThread*>((*thread).get());
Mutex::Autolock _l(recordThread->mLock);
return recordThread->mInput ? recordThread->mInput->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) {
@@ -3106,7 +3292,7 @@
const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
buffer->mFrameCount = 0;
buffer->mRaw = nullptr;
- sp<ThreadBase> thread;
+ sp<AudioFlinger::ThreadBase> thread;
sp<StreamInHalInterface> stream = obtainStream(&thread);
if (!stream) return NO_INIT; // If there is no stream, RecordThread is not reading.
@@ -3154,7 +3340,7 @@
return result;
}
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
{
if (buffer->mFrameCount <= mUnconsumedFrames) {
mUnconsumedFrames -= buffer->mFrameCount;
@@ -3171,7 +3357,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);
@@ -3190,15 +3376,15 @@
return 0;
}
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::getCapturePosition(
+status_t PassthruPatchRecord::getCapturePosition(
int64_t* frames, int64_t* time)
{
- sp<ThreadBase> thread;
+ sp<AudioFlinger::ThreadBase> 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'.
@@ -3210,7 +3396,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;
@@ -3218,7 +3404,7 @@
return NO_ERROR;
}
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(
+void PassthruPatchRecord::releaseBuffer(
AudioBufferProvider::Buffer* buffer)
{
buffer->frameCount = 0;
@@ -3229,7 +3415,32 @@
#undef LOG_TAG
#define LOG_TAG "AF::MmapTrack"
-AudioFlinger::MmapThread::MmapTrack::MmapTrack(ThreadBase *thread,
+/* static */
+sp<IAfMmapTrack> IAfMmapTrack::create(void* /* AudioFlinger::ThreadBase */ 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(
+ reinterpret_cast<AudioFlinger::ThreadBase*>(thread),
+ attr,
+ sampleRate,
+ format,
+ channelMask,
+ sessionId,
+ isOut,
+ attributionSource,
+ creatorPid,
+ portId);
+}
+
+MmapTrack::MmapTrack(AudioFlinger::ThreadBase* thread,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
@@ -3255,27 +3466,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;
@@ -3283,21 +3494,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
@@ -3328,13 +3538,13 @@
}
}
-void AudioFlinger::MmapThread::MmapTrack::appendDumpHeader(String8& result) const
+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) const
+void MmapTrack::appendDump(String8& result, bool active __unused) const
{
result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
mPid,