aaudio: fix device switch detection in legacy path
Implement device switch detection on legacy path (AudioTrack and
AudioRecord) based on audio routing callbacks forcing the stream state
to disconnected.
Bug: 33355262
Bug: 62090113
Test: tested with write_sine and input_monitor command line tools.
Change-Id: I9e0421fee233964b1bf318acb640569196a00f13
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index e566332..1e3119c 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -115,7 +115,11 @@
ALOGD("AudioStreamTrack::open(), request notificationFrames = %d, frameCount = %u",
notificationFrames, (uint)frameCount);
- mAudioTrack = new AudioTrack(
+ mAudioTrack = new AudioTrack();
+ if (getDeviceId() != AAUDIO_UNSPECIFIED) {
+ mAudioTrack->setOutputDevice(getDeviceId());
+ }
+ mAudioTrack->set(
(audio_stream_type_t) AUDIO_STREAM_MUSIC,
getSampleRate(),
format,
@@ -125,6 +129,8 @@
callback,
callbackData,
notificationFrames,
+ 0 /*sharedBuffer*/,
+ false /*threadCanCallJava*/,
AUDIO_SESSION_ALLOCATE,
streamTransferType
);
@@ -160,6 +166,7 @@
setState(AAUDIO_STREAM_STATE_OPEN);
setDeviceId(mAudioTrack->getRoutedDeviceId());
+ mAudioTrack->addAudioDeviceCallback(mDeviceCallback);
// Update performance mode based on the actual stream.
// For example, if the sample rate is not allowed then you won't get a FAST track.
@@ -229,6 +236,7 @@
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
} else {
+ onStart();
setState(AAUDIO_STREAM_STATE_STARTING);
}
return AAUDIO_OK;
@@ -246,6 +254,7 @@
AAudio_convertStreamStateToText(getState()));
return AAUDIO_ERROR_INVALID_STATE;
}
+ onStop();
setState(AAUDIO_STREAM_STATE_PAUSING);
mAudioTrack->pause();
status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
@@ -276,6 +285,7 @@
if (mAudioTrack.get() == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
+ onStop();
setState(AAUDIO_STREAM_STATE_STOPPING);
incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
mAudioTrack->stop();
@@ -339,6 +349,10 @@
return result;
}
+ if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
+ return AAUDIO_ERROR_DISCONNECTED;
+ }
+
// TODO add timeout to AudioTrack
bool blocking = timeoutNanoseconds > 0;
ssize_t bytesWritten = mAudioTrack->write(buffer, numBytes, blocking);
@@ -346,6 +360,12 @@
return 0;
} else if (bytesWritten < 0) {
ALOGE("invalid write, returned %d", (int)bytesWritten);
+ // in this context, a DEAD_OBJECT is more likely to be a disconnect notification due to
+ // AudioTrack invalidation
+ if (bytesWritten == DEAD_OBJECT) {
+ setState(AAUDIO_STREAM_STATE_DISCONNECTED);
+ return AAUDIO_ERROR_DISCONNECTED;
+ }
return AAudioConvert_androidToAAudioResult(bytesWritten);
}
int32_t framesWritten = (int32_t)(bytesWritten / bytesPerFrame);