Merge "Update Soundpool callback interface" into tm-dev
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//#define LOG_NDEBUG 0
|
//#define LOG_NDEBUG 0
|
||||||
|
#include <utility>
|
||||||
#define LOG_TAG "SoundPool::Stream"
|
#define LOG_TAG "SoundPool::Stream"
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <android/content/AttributionSourceState.h>
|
#include <android/content/AttributionSourceState.h>
|
||||||
@@ -309,13 +310,11 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
|
|||||||
}
|
}
|
||||||
if (mAudioTrack == nullptr) {
|
if (mAudioTrack == nullptr) {
|
||||||
// mToggle toggles each time a track is started on a given stream.
|
// mToggle toggles each time a track is started on a given stream.
|
||||||
// The toggle is concatenated with the Stream address and passed to AudioTrack
|
// This enables the detection of callbacks received from the old
|
||||||
// as callback user data. This enables the detection of callbacks received from the old
|
|
||||||
// audio track while the new one is being started and avoids processing them with
|
// audio track while the new one is being started and avoids processing them with
|
||||||
// wrong audio audio buffer size (mAudioBufferSize)
|
// wrong audio audio buffer size (mAudioBufferSize)
|
||||||
auto toggle = mToggle ^ 1;
|
auto toggle = mToggle ^ 1;
|
||||||
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
||||||
void* userData = reinterpret_cast<void*>((uintptr_t)this | toggle);
|
|
||||||
audio_channel_mask_t soundChannelMask = sound->getChannelMask();
|
audio_channel_mask_t soundChannelMask = sound->getChannelMask();
|
||||||
// When sound contains a valid channel mask, use it as is.
|
// When sound contains a valid channel mask, use it as is.
|
||||||
// Otherwise, use stream count to calculate channel mask.
|
// Otherwise, use stream count to calculate channel mask.
|
||||||
@@ -327,10 +326,11 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
|
|||||||
android::content::AttributionSourceState attributionSource;
|
android::content::AttributionSourceState attributionSource;
|
||||||
attributionSource.packageName = mStreamManager->getOpPackageName();
|
attributionSource.packageName = mStreamManager->getOpPackageName();
|
||||||
attributionSource.token = sp<BBinder>::make();
|
attributionSource.token = sp<BBinder>::make();
|
||||||
|
mCallback = sp<StreamCallback>::make(this, toggle),
|
||||||
// TODO b/182469354 make consistent with AudioRecord, add util for native source
|
// TODO b/182469354 make consistent with AudioRecord, add util for native source
|
||||||
mAudioTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
|
mAudioTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
|
||||||
channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
|
channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
|
||||||
staticCallback, userData,
|
mCallback,
|
||||||
0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
|
0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
|
||||||
AudioTrack::TRANSFER_DEFAULT,
|
AudioTrack::TRANSFER_DEFAULT,
|
||||||
nullptr /*offloadInfo*/, attributionSource,
|
nullptr /*offloadInfo*/, attributionSource,
|
||||||
@@ -375,16 +375,55 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
|
|||||||
mStreamID = nextStreamID; // prefer this to be the last, as it is an atomic sync point
|
mStreamID = nextStreamID; // prefer this to be the last, as it is an atomic sync point
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
int Stream::getCorrespondingStreamID() {
|
||||||
void Stream::staticCallback(int event, void* user, void* info)
|
std::lock_guard lock(mLock);
|
||||||
{
|
return static_cast<int>(mAudioTrack ? mStreamID : getPairStream()->mStreamID);
|
||||||
const auto userAsInt = (uintptr_t)user;
|
}
|
||||||
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
size_t Stream::StreamCallback::onMoreData(const AudioTrack::Buffer&) {
|
||||||
auto stream = reinterpret_cast<Stream*>(userAsInt & ~1);
|
ALOGW("%s streamID %d Unexpected EVENT_MORE_DATA for static track",
|
||||||
stream->callback(event, info, int(userAsInt & 1), 0 /* tries */);
|
__func__, mStream->getCorrespondingStreamID());
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::callback(int event, void* info, int toggle, int tries)
|
void Stream::StreamCallback::onUnderrun() {
|
||||||
|
ALOGW("%s streamID %d Unexpected EVENT_UNDERRUN for static track",
|
||||||
|
__func__, mStream->getCorrespondingStreamID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::StreamCallback::onLoopEnd(int32_t) {
|
||||||
|
ALOGV("%s streamID %d EVENT_LOOP_END", __func__, mStream->getCorrespondingStreamID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::StreamCallback::onMarker(uint32_t) {
|
||||||
|
ALOGW("%s streamID %d Unexpected EVENT_MARKER for static track",
|
||||||
|
__func__, mStream->getCorrespondingStreamID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::StreamCallback::onNewPos(uint32_t) {
|
||||||
|
ALOGW("%s streamID %d Unexpected EVENT_NEW_POS for static track",
|
||||||
|
__func__, mStream->getCorrespondingStreamID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::StreamCallback::onBufferEnd() {
|
||||||
|
mStream->onBufferEnd(mToggle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::StreamCallback::onNewIAudioTrack() {
|
||||||
|
ALOGV("%s streamID %d NEW_IAUDIOTRACK", __func__, mStream->getCorrespondingStreamID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::StreamCallback::onStreamEnd() {
|
||||||
|
ALOGW("%s streamID %d Unexpected EVENT_STREAM_END for static track",
|
||||||
|
__func__, mStream->getCorrespondingStreamID());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Stream::StreamCallback::onCanWriteMoreData(const AudioTrack::Buffer&) {
|
||||||
|
ALOGW("%s streamID %d Unexpected EVENT_CAN_WRITE_MORE_DATA for static track",
|
||||||
|
__func__, mStream->getCorrespondingStreamID());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::onBufferEnd(int toggle, int tries)
|
||||||
{
|
{
|
||||||
int32_t activeStreamIDToRestart = 0;
|
int32_t activeStreamIDToRestart = 0;
|
||||||
{
|
{
|
||||||
@@ -400,7 +439,7 @@ void Stream::callback(int event, void* info, int toggle, int tries)
|
|||||||
if (tries < 3) {
|
if (tries < 3) {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
ALOGV("%s streamID %d going to pair stream", __func__, (int)mStreamID);
|
ALOGV("%s streamID %d going to pair stream", __func__, (int)mStreamID);
|
||||||
getPairStream()->callback(event, info, toggle, tries + 1);
|
getPairStream()->onBufferEnd(toggle, tries + 1);
|
||||||
} else {
|
} else {
|
||||||
ALOGW("%s streamID %d cannot find track", __func__, (int)mStreamID);
|
ALOGW("%s streamID %d cannot find track", __func__, (int)mStreamID);
|
||||||
}
|
}
|
||||||
@@ -410,32 +449,11 @@ void Stream::callback(int event, void* info, int toggle, int tries)
|
|||||||
ALOGD("%s streamID %d wrong toggle", __func__, (int)mStreamID);
|
ALOGD("%s streamID %d wrong toggle", __func__, (int)mStreamID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (event) {
|
|
||||||
case AudioTrack::EVENT_MORE_DATA:
|
|
||||||
ALOGW("%s streamID %d Invalid EVENT_MORE_DATA for static track",
|
|
||||||
__func__, (int)mStreamID);
|
|
||||||
break;
|
|
||||||
case AudioTrack::EVENT_UNDERRUN:
|
|
||||||
ALOGW("%s streamID %d Invalid EVENT_UNDERRUN for static track",
|
|
||||||
__func__, (int)mStreamID);
|
|
||||||
break;
|
|
||||||
case AudioTrack::EVENT_BUFFER_END:
|
|
||||||
ALOGV("%s streamID %d EVENT_BUFFER_END", __func__, (int)mStreamID);
|
ALOGV("%s streamID %d EVENT_BUFFER_END", __func__, (int)mStreamID);
|
||||||
if (mState != IDLE) {
|
if (mState != IDLE) {
|
||||||
activeStreamIDToRestart = mStreamID;
|
activeStreamIDToRestart = mStreamID;
|
||||||
mStopTimeNs = systemTime();
|
mStopTimeNs = systemTime();
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case AudioTrack::EVENT_LOOP_END:
|
|
||||||
ALOGV("%s streamID %d EVENT_LOOP_END", __func__, (int)mStreamID);
|
|
||||||
break;
|
|
||||||
case AudioTrack::EVENT_NEW_IAUDIOTRACK:
|
|
||||||
ALOGV("%s streamID %d NEW_IAUDIOTRACK", __func__, (int)mStreamID);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ALOGW("%s streamID %d Invalid event %d", __func__, (int)mStreamID, event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} // lock ends here. This is on the callback thread, no need to be precise.
|
} // lock ends here. This is on the callback thread, no need to be precise.
|
||||||
if (activeStreamIDToRestart > 0) {
|
if (activeStreamIDToRestart > 0) {
|
||||||
// Restart only if a particular streamID is still current and active.
|
// Restart only if a particular streamID is still current and active.
|
||||||
|
|||||||
@@ -124,6 +124,35 @@ public:
|
|||||||
// This never changes. See top of header.
|
// This never changes. See top of header.
|
||||||
Stream* getPairStream() const;
|
Stream* getPairStream() const;
|
||||||
|
|
||||||
|
// Stream ID of ourselves, or the pair depending on who holds the AudioTrack
|
||||||
|
int getCorrespondingStreamID();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// AudioTrack callback interface implementation
|
||||||
|
class StreamCallback : public AudioTrack::IAudioTrackCallback {
|
||||||
|
public:
|
||||||
|
StreamCallback(Stream * stream, bool toggle) : mStream(stream), mToggle(toggle) {}
|
||||||
|
size_t onMoreData(const AudioTrack::Buffer& buffer) override;
|
||||||
|
void onUnderrun() override;
|
||||||
|
void onLoopEnd(int32_t loopsRemaining) override;
|
||||||
|
void onMarker(uint32_t markerPosition) override;
|
||||||
|
void onNewPos(uint32_t newPos) override;
|
||||||
|
void onBufferEnd() override;
|
||||||
|
void onNewIAudioTrack() override;
|
||||||
|
void onStreamEnd() override;
|
||||||
|
size_t onCanWriteMoreData(const AudioTrack::Buffer& buffer) override;
|
||||||
|
|
||||||
|
// Holding a raw ptr is technically unsafe, but, Stream objects persist
|
||||||
|
// through the lifetime of the StreamManager through the use of a
|
||||||
|
// unique_ptr<Stream[]>. Ensuring lifetime will cause us to give up
|
||||||
|
// locality as well as pay RefBase/sp performance cost, which we are
|
||||||
|
// unwilling to do. Non-owning refs to unique_ptrs are idiomatically raw
|
||||||
|
// ptrs, as below.
|
||||||
|
Stream * const mStream;
|
||||||
|
const bool mToggle;
|
||||||
|
};
|
||||||
|
|
||||||
|
sp<StreamCallback> mCallback;
|
||||||
private:
|
private:
|
||||||
// garbage is used to release tracks and data outside of any lock.
|
// garbage is used to release tracks and data outside of any lock.
|
||||||
void play_l(const std::shared_ptr<Sound>& sound, int streamID,
|
void play_l(const std::shared_ptr<Sound>& sound, int streamID,
|
||||||
@@ -133,9 +162,7 @@ private:
|
|||||||
void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);
|
void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);
|
||||||
|
|
||||||
// For use with AudioTrack callback.
|
// For use with AudioTrack callback.
|
||||||
static void staticCallback(int event, void* user, void* info);
|
void onBufferEnd(int toggle, int tries) NO_THREAD_SAFETY_ANALYSIS;
|
||||||
void callback(int event, void* info, int toggle, int tries)
|
|
||||||
NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock
|
|
||||||
|
|
||||||
// StreamManager should be set on construction and not changed.
|
// StreamManager should be set on construction and not changed.
|
||||||
// release mLock before calling into StreamManager
|
// release mLock before calling into StreamManager
|
||||||
|
|||||||
Reference in New Issue
Block a user