Revert "Revert "Refactor AudioTrack callback to Interface""
This reverts commit f13b98aac7921d6ef707940daf82cc4334f5e790.
Change-Id: I67dc284307419737eeb055db851751455abf103d
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 8cf22c4..5e2dfcc 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -254,8 +254,7 @@
audio_channel_mask_t channelMask,
size_t frameCount,
audio_output_flags_t flags,
- callback_t cbf,
- void* user,
+ const wp<IAudioTrackCallback> & callback,
int32_t notificationFrames,
audio_session_t sessionId,
transfer_type transferType,
@@ -275,7 +274,85 @@
mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
(void)set(streamType, sampleRate, format, channelMask,
- frameCount, flags, cbf, user, notificationFrames,
+ frameCount, flags, callback, notificationFrames,
+ 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
+ attributionSource, pAttributes, doNotReconnect, maxRequiredSpeed, selectedDeviceId);
+}
+
+namespace {
+ class LegacyCallbackWrapper : public AudioTrack::IAudioTrackCallback {
+ const AudioTrack::legacy_callback_t mCallback;
+ void * const mData;
+ public:
+ LegacyCallbackWrapper(AudioTrack::legacy_callback_t callback, void* user)
+ : mCallback(callback), mData(user) {}
+ size_t onMoreData(const AudioTrack::Buffer & buffer) override {
+ AudioTrack::Buffer copy = buffer;
+ mCallback(AudioTrack::EVENT_MORE_DATA, mData, static_cast<void*>(©));
+ return copy.size;
+ }
+ void onUnderrun() override {
+ mCallback(AudioTrack::EVENT_UNDERRUN, mData, nullptr);
+ }
+ void onLoopEnd(int32_t loopsRemaining) override {
+ mCallback(AudioTrack::EVENT_LOOP_END, mData, &loopsRemaining);
+ }
+ void onMarker(uint32_t markerPosition) override {
+ mCallback(AudioTrack::EVENT_MARKER, mData, &markerPosition);
+ }
+ void onNewPos(uint32_t newPos) override {
+ mCallback(AudioTrack::EVENT_NEW_POS, mData, &newPos);
+ }
+ void onBufferEnd() override {
+ mCallback(AudioTrack::EVENT_BUFFER_END, mData, nullptr);
+ }
+ void onNewIAudioTrack() override {
+ mCallback(AudioTrack::EVENT_NEW_IAUDIOTRACK, mData, nullptr);
+ }
+ void onStreamEnd() override {
+ mCallback(AudioTrack::EVENT_STREAM_END, mData, nullptr);
+ }
+ size_t onCanWriteMoreData(const AudioTrack::Buffer & buffer) override {
+ AudioTrack::Buffer copy = buffer;
+ mCallback(AudioTrack::EVENT_CAN_WRITE_MORE_DATA, mData, static_cast<void*>(©));
+ return copy.size;
+ }
+ };
+}
+
+AudioTrack::AudioTrack(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount,
+ audio_output_flags_t flags,
+ legacy_callback_t callback,
+ void* user,
+ int32_t notificationFrames,
+ audio_session_t sessionId,
+ transfer_type transferType,
+ const audio_offload_info_t *offloadInfo,
+ const AttributionSourceState& attributionSource,
+ const audio_attributes_t* pAttributes,
+ bool doNotReconnect,
+ float maxRequiredSpeed,
+ audio_port_handle_t selectedDeviceId)
+ : mStatus(NO_INIT),
+ mState(STATE_STOPPED),
+ mPreviousPriority(ANDROID_PRIORITY_NORMAL),
+ mPreviousSchedulingGroup(SP_DEFAULT),
+ mPausedPosition(0),
+ mAudioTrackCallback(new AudioTrackCallback())
+{
+ mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ if (callback != nullptr) {
+ mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
+ } else if (user) {
+ LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
+ }
+ (void)set(streamType, sampleRate, format, channelMask,
+ frameCount, flags, mLegacyCallbackWrapper, notificationFrames,
0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
attributionSource, pAttributes, doNotReconnect, maxRequiredSpeed, selectedDeviceId);
}
@@ -287,8 +364,7 @@
audio_channel_mask_t channelMask,
const sp<IMemory>& sharedBuffer,
audio_output_flags_t flags,
- callback_t cbf,
- void* user,
+ const wp<IAudioTrackCallback>& callback,
int32_t notificationFrames,
audio_session_t sessionId,
transfer_type transferType,
@@ -308,11 +384,49 @@
mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
(void)set(streamType, sampleRate, format, channelMask,
- 0 /*frameCount*/, flags, cbf, user, notificationFrames,
+ 0 /*frameCount*/, flags, callback, notificationFrames,
sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
attributionSource, pAttributes, doNotReconnect, maxRequiredSpeed);
}
+AudioTrack::AudioTrack(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ const sp<IMemory>& sharedBuffer,
+ audio_output_flags_t flags,
+ legacy_callback_t callback,
+ void* user,
+ int32_t notificationFrames,
+ audio_session_t sessionId,
+ transfer_type transferType,
+ const audio_offload_info_t *offloadInfo,
+ const AttributionSourceState& attributionSource,
+ const audio_attributes_t* pAttributes,
+ bool doNotReconnect,
+ float maxRequiredSpeed)
+ : mStatus(NO_INIT),
+ mState(STATE_STOPPED),
+ mPreviousPriority(ANDROID_PRIORITY_NORMAL),
+ mPreviousSchedulingGroup(SP_DEFAULT),
+ mPausedPosition(0),
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+ mAudioTrackCallback(new AudioTrackCallback())
+{
+ mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ if (callback) {
+ mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
+ } else if (user) {
+ LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
+ }
+
+ (void)set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags,
+ mLegacyCallbackWrapper, notificationFrames, sharedBuffer,
+ false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, attributionSource,
+ pAttributes, doNotReconnect, maxRequiredSpeed);
+}
+
AudioTrack::~AudioTrack()
{
// pull together the numbers, before we clean up our structures
@@ -374,8 +488,38 @@
audio_channel_mask_t channelMask,
size_t frameCount,
audio_output_flags_t flags,
- callback_t cbf,
- void* user,
+ legacy_callback_t callback,
+ void * user,
+ int32_t notificationFrames,
+ const sp<IMemory>& sharedBuffer,
+ bool threadCanCallJava,
+ audio_session_t sessionId,
+ transfer_type transferType,
+ const audio_offload_info_t *offloadInfo,
+ const AttributionSourceState& attributionSource,
+ const audio_attributes_t* pAttributes,
+ bool doNotReconnect,
+ float maxRequiredSpeed,
+ audio_port_handle_t selectedDeviceId)
+{
+ if (callback) {
+ mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
+ } else if (user) {
+ LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
+ }
+ return set(streamType, sampleRate,format, channelMask, frameCount, flags,
+ mLegacyCallbackWrapper, notificationFrames, sharedBuffer, threadCanCallJava,
+ sessionId, transferType, offloadInfo, attributionSource, pAttributes,
+ doNotReconnect, maxRequiredSpeed, selectedDeviceId);
+}
+status_t AudioTrack::set(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t frameCount,
+ audio_output_flags_t flags,
+ const wp<IAudioTrackCallback>& callback,
int32_t notificationFrames,
const sp<IMemory>& sharedBuffer,
bool threadCanCallJava,
@@ -394,7 +538,7 @@
pid_t myPid;
uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(attributionSource.pid));
-
+ sp<IAudioTrackCallback> _callback = callback.promote();
// Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
ALOGV("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
"flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
@@ -410,7 +554,7 @@
case TRANSFER_DEFAULT:
if (sharedBuffer != 0) {
transferType = TRANSFER_SHARED;
- } else if (cbf == NULL || threadCanCallJava) {
+ } else if (_callback == nullptr|| threadCanCallJava) {
transferType = TRANSFER_SYNC;
} else {
transferType = TRANSFER_CALLBACK;
@@ -418,8 +562,8 @@
break;
case TRANSFER_CALLBACK:
case TRANSFER_SYNC_NOTIF_CALLBACK:
- if (cbf == NULL || sharedBuffer != 0) {
- ALOGE("%s(): Transfer type %s but cbf == NULL || sharedBuffer != 0",
+ if (_callback == nullptr || sharedBuffer != 0) {
+ ALOGE("%s(): Transfer type %s but callback == nullptr || sharedBuffer != 0",
convertTransferToText(transferType), __func__);
status = BAD_VALUE;
goto exit;
@@ -609,10 +753,10 @@
}
mAuxEffectId = 0;
mOrigFlags = mFlags = flags;
- mCbf = cbf;
+ mCallback = callback;
- if (cbf != NULL) {
- mAudioTrackThread = new AudioTrackThread(*this);
+ if (_callback != nullptr) {
+ mAudioTrackThread = sp<AudioTrackThread>::make(*this);
mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
// thread begins in paused state, and will not reference us until start()
}
@@ -631,7 +775,6 @@
goto exit;
}
- mUserData = user;
mLoopCount = 0;
mLoopStart = 0;
mLoopEnd = 0;
@@ -675,7 +818,7 @@
uint32_t channelMask,
size_t frameCount,
audio_output_flags_t flags,
- callback_t cbf,
+ legacy_callback_t callback,
void* user,
int32_t notificationFrames,
const sp<IMemory>& sharedBuffer,
@@ -694,11 +837,15 @@
attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(uid));
attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(pid));
attributionSource.token = sp<BBinder>::make();
- return set(streamType, sampleRate, format,
- static_cast<audio_channel_mask_t>(channelMask),
- frameCount, flags, cbf, user, notificationFrames, sharedBuffer,
- threadCanCallJava, sessionId, transferType, offloadInfo, attributionSource,
- pAttributes, doNotReconnect, maxRequiredSpeed, selectedDeviceId);
+ if (callback) {
+ mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
+ } else if (user) {
+ LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
+ }
+ return set(streamType, sampleRate, format, static_cast<audio_channel_mask_t>(channelMask),
+ frameCount, flags, mLegacyCallbackWrapper, notificationFrames, sharedBuffer,
+ threadCanCallJava, sessionId, transferType, offloadInfo, attributionSource,
+ pAttributes, doNotReconnect, maxRequiredSpeed, selectedDeviceId);
}
// -------------------------------------------------------------------------
@@ -1407,7 +1554,7 @@
status_t AudioTrack::setMarkerPosition(uint32_t marker)
{
// The only purpose of setting marker position is to get a callback
- if (mCbf == NULL || isOffloadedOrDirect()) {
+ if (!mCallback.promote() || isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
@@ -1440,7 +1587,7 @@
status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod)
{
// The only purpose of setting position update period is to get a callback
- if (mCbf == NULL || isOffloadedOrDirect()) {
+ if (!mCallback.promote() || isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
@@ -2209,10 +2356,14 @@
{
// Currently the AudioTrack thread is not created if there are no callbacks.
// Would it ever make sense to run the thread, even without callbacks?
- // If so, then replace this by checks at each use for mCbf != NULL.
+ // If so, then replace this by checks at each use for mCallback != NULL.
LOG_ALWAYS_FATAL_IF(mCblk == NULL);
-
mLock.lock();
+ sp<IAudioTrackCallback> callback = mCallback.promote();
+ if (!callback) {
+ mCallback = nullptr;
+ return NS_NEVER;
+ }
if (mAwaitBoost) {
mAwaitBoost = false;
mLock.unlock();
@@ -2310,7 +2461,7 @@
sp<AudioTrackClientProxy> proxy = mProxy;
// Determine the number of new loop callback(s) that will be needed, while locked.
- int loopCountNotifications = 0;
+ uint32_t loopCountNotifications = 0;
uint32_t loopPeriod = 0; // time in frames for next EVENT_LOOP_END or EVENT_BUFFER_END
if (mLoopCount > 0) {
@@ -2332,7 +2483,7 @@
}
// These fields don't need to be cached, because they are assigned only by set():
- // mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFlags
+ // mTransfer, mCallback, mUserData, mFormat, mFrameSize, mFlags
// mFlags is also assigned by createTrack_l(), but not the bit we care about.
mLock.unlock();
@@ -2357,7 +2508,7 @@
if (status != DEAD_OBJECT) {
// for DEAD_OBJECT, we do not send a EVENT_STREAM_END after stop();
// instead, the application should handle the EVENT_NEW_IAUDIOTRACK.
- mCbf(EVENT_STREAM_END, mUserData, NULL);
+ callback->onStreamEnd();
}
{
AutoMutex lock(mLock);
@@ -2380,28 +2531,27 @@
// perform callbacks while unlocked
if (newUnderrun) {
- mCbf(EVENT_UNDERRUN, mUserData, NULL);
+ callback->onUnderrun();
}
while (loopCountNotifications > 0) {
- mCbf(EVENT_LOOP_END, mUserData, NULL);
--loopCountNotifications;
+ callback->onLoopEnd(mLoopCount > 0 ? loopCountNotifications + mLoopCountNotified : -1);
}
if (flags & CBLK_BUFFER_END) {
- mCbf(EVENT_BUFFER_END, mUserData, NULL);
+ callback->onBufferEnd();
}
if (markerReached) {
- mCbf(EVENT_MARKER, mUserData, &markerPosition);
+ callback->onMarker(markerPosition.value());
}
while (newPosCount > 0) {
- size_t temp = newPosition.value(); // FIXME size_t != uint32_t
- mCbf(EVENT_NEW_POS, mUserData, &temp);
+ callback->onNewPos(newPosition.value());
newPosition += updatePeriod;
newPosCount--;
}
if (mObservedSequence != sequence) {
mObservedSequence = sequence;
- mCbf(EVENT_NEW_IAUDIOTRACK, mUserData, NULL);
+ callback->onNewIAudioTrack();
// for offloaded tracks, just wait for the upper layers to recreate the track
if (isOffloadedOrDirect()) {
return NS_INACTIVE;
@@ -2539,10 +2689,9 @@
// written in the next write() call, since it's not passed through the callback
audioBuffer.size += nonContig;
}
- mCbf(mTransfer == TRANSFER_CALLBACK ? EVENT_MORE_DATA : EVENT_CAN_WRITE_MORE_DATA,
- mUserData, &audioBuffer);
- size_t writtenSize = audioBuffer.size;
-
+ size_t writtenSize = (mTransfer == TRANSFER_CALLBACK)
+ ? callback->onMoreData(audioBuffer)
+ : callback->onCanWriteMoreData(audioBuffer);
// Validate on returned size
if (ssize_t(writtenSize) < 0 || writtenSize > reqSize) {
ALOGE("%s(%d): EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",