Merge "Serializer: fix allocator / deallocator mismatch" into sc-dev
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 63ae5cd..bae82f6 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1798,17 +1798,19 @@
}
status_t CCodec::setSurface(const sp<Surface> &surface) {
- Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
- const std::unique_ptr<Config> &config = *configLocked;
- if (config->mTunneled && config->mSidebandHandle != nullptr) {
- sp<ANativeWindow> nativeWindow = static_cast<ANativeWindow *>(surface.get());
- status_t err = native_window_set_sideband_stream(
- nativeWindow.get(),
- const_cast<native_handle_t *>(config->mSidebandHandle->handle()));
- if (err != OK) {
- ALOGE("NativeWindow(%p) native_window_set_sideband_stream(%p) failed! (err %d).",
- nativeWindow.get(), config->mSidebandHandle->handle(), err);
- return err;
+ {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ if (config->mTunneled && config->mSidebandHandle != nullptr) {
+ sp<ANativeWindow> nativeWindow = static_cast<ANativeWindow *>(surface.get());
+ status_t err = native_window_set_sideband_stream(
+ nativeWindow.get(),
+ const_cast<native_handle_t *>(config->mSidebandHandle->handle()));
+ if (err != OK) {
+ ALOGE("NativeWindow(%p) native_window_set_sideband_stream(%p) failed! (err %d).",
+ nativeWindow.get(), config->mSidebandHandle->handle(), err);
+ return err;
+ }
}
}
return mChannel->setSurface(surface);
@@ -2149,80 +2151,88 @@
}
// handle configuration changes in work done
- Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
- const std::unique_ptr<Config> &config = *configLocked;
- Config::Watcher<C2StreamInitDataInfo::output> initData =
- config->watch<C2StreamInitDataInfo::output>();
- if (!work->worklets.empty()
- && (work->worklets.front()->output.flags
- & C2FrameData::FLAG_DISCARD_FRAME) == 0) {
+ const C2StreamInitDataInfo::output *initData = nullptr;
+ sp<AMessage> outputFormat = nullptr;
+ {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ Config::Watcher<C2StreamInitDataInfo::output> initDataWatcher =
+ config->watch<C2StreamInitDataInfo::output>();
+ if (!work->worklets.empty()
+ && (work->worklets.front()->output.flags
+ & C2FrameData::FLAG_DISCARD_FRAME) == 0) {
- // copy buffer info to config
- std::vector<std::unique_ptr<C2Param>> updates;
- for (const std::unique_ptr<C2Param> ¶m
- : work->worklets.front()->output.configUpdate) {
- updates.push_back(C2Param::Copy(*param));
- }
- unsigned stream = 0;
- for (const std::shared_ptr<C2Buffer> &buf : work->worklets.front()->output.buffers) {
- for (const std::shared_ptr<const C2Info> &info : buf->info()) {
- // move all info into output-stream #0 domain
- updates.emplace_back(C2Param::CopyAsStream(*info, true /* output */, stream));
+ // copy buffer info to config
+ std::vector<std::unique_ptr<C2Param>> updates;
+ for (const std::unique_ptr<C2Param> ¶m
+ : work->worklets.front()->output.configUpdate) {
+ updates.push_back(C2Param::Copy(*param));
+ }
+ unsigned stream = 0;
+ std::vector<std::shared_ptr<C2Buffer>> &outputBuffers =
+ work->worklets.front()->output.buffers;
+ for (const std::shared_ptr<C2Buffer> &buf : outputBuffers) {
+ for (const std::shared_ptr<const C2Info> &info : buf->info()) {
+ // move all info into output-stream #0 domain
+ updates.emplace_back(
+ C2Param::CopyAsStream(*info, true /* output */, stream));
+ }
+
+ const std::vector<C2ConstGraphicBlock> blocks = buf->data().graphicBlocks();
+ // for now only do the first block
+ if (!blocks.empty()) {
+ // ALOGV("got output buffer with crop %u,%u+%u,%u and size %u,%u",
+ // block.crop().left, block.crop().top,
+ // block.crop().width, block.crop().height,
+ // block.width(), block.height());
+ const C2ConstGraphicBlock &block = blocks[0];
+ updates.emplace_back(new C2StreamCropRectInfo::output(
+ stream, block.crop()));
+ updates.emplace_back(new C2StreamPictureSizeInfo::output(
+ stream, block.crop().width, block.crop().height));
+ }
+ ++stream;
}
- const std::vector<C2ConstGraphicBlock> blocks = buf->data().graphicBlocks();
- // for now only do the first block
- if (!blocks.empty()) {
- // ALOGV("got output buffer with crop %u,%u+%u,%u and size %u,%u",
- // block.crop().left, block.crop().top,
- // block.crop().width, block.crop().height,
- // block.width(), block.height());
- const C2ConstGraphicBlock &block = blocks[0];
- updates.emplace_back(new C2StreamCropRectInfo::output(stream, block.crop()));
- updates.emplace_back(new C2StreamPictureSizeInfo::output(
- stream, block.crop().width, block.crop().height));
- }
- ++stream;
- }
+ sp<AMessage> oldFormat = config->mOutputFormat;
+ config->updateConfiguration(updates, config->mOutputDomain);
+ RevertOutputFormatIfNeeded(oldFormat, config->mOutputFormat);
- sp<AMessage> outputFormat = config->mOutputFormat;
- config->updateConfiguration(updates, config->mOutputDomain);
- RevertOutputFormatIfNeeded(outputFormat, config->mOutputFormat);
-
- // copy standard infos to graphic buffers if not already present (otherwise, we
- // may overwrite the actual intermediate value with a final value)
- stream = 0;
- const static C2Param::Index stdGfxInfos[] = {
- C2StreamRotationInfo::output::PARAM_TYPE,
- C2StreamColorAspectsInfo::output::PARAM_TYPE,
- C2StreamDataSpaceInfo::output::PARAM_TYPE,
- C2StreamHdrStaticInfo::output::PARAM_TYPE,
- C2StreamHdr10PlusInfo::output::PARAM_TYPE,
- C2StreamPixelAspectRatioInfo::output::PARAM_TYPE,
- C2StreamSurfaceScalingInfo::output::PARAM_TYPE
- };
- for (const std::shared_ptr<C2Buffer> &buf : work->worklets.front()->output.buffers) {
- if (buf->data().graphicBlocks().size()) {
- for (C2Param::Index ix : stdGfxInfos) {
- if (!buf->hasInfo(ix)) {
- const C2Param *param =
- config->getConfigParameterValue(ix.withStream(stream));
- if (param) {
- std::shared_ptr<C2Param> info(C2Param::Copy(*param));
- buf->setInfo(std::static_pointer_cast<C2Info>(info));
+ // copy standard infos to graphic buffers if not already present (otherwise, we
+ // may overwrite the actual intermediate value with a final value)
+ stream = 0;
+ const static C2Param::Index stdGfxInfos[] = {
+ C2StreamRotationInfo::output::PARAM_TYPE,
+ C2StreamColorAspectsInfo::output::PARAM_TYPE,
+ C2StreamDataSpaceInfo::output::PARAM_TYPE,
+ C2StreamHdrStaticInfo::output::PARAM_TYPE,
+ C2StreamHdr10PlusInfo::output::PARAM_TYPE,
+ C2StreamPixelAspectRatioInfo::output::PARAM_TYPE,
+ C2StreamSurfaceScalingInfo::output::PARAM_TYPE
+ };
+ for (const std::shared_ptr<C2Buffer> &buf : outputBuffers) {
+ if (buf->data().graphicBlocks().size()) {
+ for (C2Param::Index ix : stdGfxInfos) {
+ if (!buf->hasInfo(ix)) {
+ const C2Param *param =
+ config->getConfigParameterValue(ix.withStream(stream));
+ if (param) {
+ std::shared_ptr<C2Param> info(C2Param::Copy(*param));
+ buf->setInfo(std::static_pointer_cast<C2Info>(info));
+ }
}
}
}
+ ++stream;
}
- ++stream;
}
+ if (config->mInputSurface) {
+ config->mInputSurface->onInputBufferDone(work->input.ordinal.frameIndex);
+ }
+ initData = initDataWatcher.hasChanged() ? initDataWatcher.update().get() : nullptr;
+ outputFormat = config->mOutputFormat;
}
- if (config->mInputSurface) {
- config->mInputSurface->onInputBufferDone(work->input.ordinal.frameIndex);
- }
- mChannel->onWorkDone(
- std::move(work), config->mOutputFormat,
- initData.hasChanged() ? initData.update().get() : nullptr);
+ mChannel->onWorkDone(std::move(work), outputFormat, initData);
break;
}
case kWhatWatch: {
@@ -2307,9 +2317,13 @@
pendingDeadline = true;
}
}
- Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
- const std::unique_ptr<Config> &config = *configLocked;
- if (config->mTunneled == false && name.empty()) {
+ bool tunneled = false;
+ {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ tunneled = config->mTunneled;
+ }
+ if (!tunneled && name.empty()) {
constexpr std::chrono::steady_clock::duration kWorkDurationThreshold = 3s;
std::chrono::steady_clock::duration elapsed = mChannel->elapsed();
if (elapsed >= kWorkDurationThreshold) {
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 1bbe443..f4a40a8 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -20,6 +20,7 @@
#include <algorithm>
#include <audio_utils/primitives.h>
#include <aaudio/AAudio.h>
+#include <media/MediaMetricsItem.h>
#include "client/AudioStreamInternalCapture.h"
#include "utility/AudioClock.h"
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 3f17e6b..71bde90 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -19,6 +19,7 @@
#define ATRACE_TAG ATRACE_TAG_AUDIO
+#include <media/MediaMetricsItem.h>
#include <utils/Trace.h>
#include "client/AudioStreamInternalPlay.h"
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index e8f71be..ef83c8e 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -59,6 +59,10 @@
if (!mMetricsId.empty()) {
android::mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM)
+ .set(AMEDIAMETRICS_PROP_ENCODINGREQUESTED,
+ android::toString(mDeviceFormat).c_str())
+ .set(AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL,
+ AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
.record();
}
@@ -124,7 +128,12 @@
.set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
.set(AMEDIAMETRICS_PROP_SHARINGMODE,
- AudioGlobal_convertSharingModeToText(getSharingMode()));
+ AudioGlobal_convertSharingModeToText(getSharingMode()))
+ .set(AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, getBufferCapacity())
+ .set(AMEDIAMETRICS_PROP_BURSTFRAMES, getFramesPerBurst())
+ .set(AMEDIAMETRICS_PROP_DIRECTION,
+ AudioGlobal_convertDirectionToText(getDirection()));
+
if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
item.set(AMEDIAMETRICS_PROP_PLAYERIID, mPlayerBase->getPlayerIId());
}
@@ -338,6 +347,22 @@
return AAUDIO_OK;
}
+void AudioStream::close_l() {
+ // Releasing the stream will set the state to CLOSING.
+ assert(getState() == AAUDIO_STREAM_STATE_CLOSING);
+ // setState() prevents a transition from CLOSING to any state other than CLOSED.
+ // State is checked by destructor.
+ setState(AAUDIO_STREAM_STATE_CLOSED);
+
+ if (!mMetricsId.empty()) {
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_FRAMESTRANSFERRED,
+ getDirection() == AAUDIO_DIRECTION_INPUT ? getFramesWritten()
+ : getFramesRead())
+ .record();
+ }
+}
+
void AudioStream::setState(aaudio_stream_state_t state) {
ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
if (state == mState) {
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index abf62f3..3930964 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -146,13 +146,7 @@
* Free any resources not already freed by release_l().
* Assume release_l() already called.
*/
- virtual void close_l() REQUIRES(mStreamLock) {
- // Releasing the stream will set the state to CLOSING.
- assert(getState() == AAUDIO_STREAM_STATE_CLOSING);
- // setState() prevents a transition from CLOSING to any state other than CLOSED.
- // State is checked by destructor.
- setState(AAUDIO_STREAM_STATE_CLOSED);
- }
+ virtual void close_l() REQUIRES(mStreamLock);
public:
// This is only used to identify a stream in the logs without
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index de4f8d4..383bae8 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -160,6 +160,12 @@
#define AMEDIAMETRICS_PROP_VOLUME_LEFT "volume.left" // double (AudioTrack)
#define AMEDIAMETRICS_PROP_VOLUME_RIGHT "volume.right" // double (AudioTrack)
#define AMEDIAMETRICS_PROP_WHERE "where" // string value
+// EncodingRequested is the encoding format requested by the app
+#define AMEDIAMETRICS_PROP_ENCODINGREQUESTED "encodingRequested" // string
+// PerformanceModeActual is the actual selected performance mode, could be "none', "loeLatency" or
+// "powerSaving"
+#define AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL "performanceModeActual" // string
+#define AMEDIAMETRICS_PROP_FRAMESTRANSFERRED "framesTransferred" // int64_t, transferred frames
// Timing values: millisecond values are suffixed with MS and the type is double
// nanosecond values are suffixed with NS and the type is int64.
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index 2b797b8..dbc68b2 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -245,7 +245,7 @@
});
}));
- // Handle legacy aaudio stream statistics
+ // Handle legacy aaudio playback stream statistics
mActions.addAction(
AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
@@ -254,6 +254,15 @@
mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
}));
+ // Handle legacy aaudio capture stream statistics
+ mActions.addAction(
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
+ std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
+ std::make_shared<AnalyticsActions::Function>(
+ [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
+ mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
+ }));
+
// Handle mmap aaudio stream statistics
mActions.addAction(
AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." AMEDIAMETRICS_PROP_EVENT,
@@ -949,7 +958,8 @@
key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
int64_t totalFramesTransferred = -1;
- // TODO: log and get total frames transferred
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_FRAMESTRANSFERRED, &totalFramesTransferred);
std::string perfModeRequestedStr;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
@@ -957,8 +967,11 @@
const auto perfModeRequested =
types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);
- int32_t perfModeActual = 0;
- // TODO: log and get actual performance mode
+ std::string perfModeActualStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL, &perfModeActualStr);
+ const auto perfModeActual =
+ types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeActualStr);
std::string sharingModeStr;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
@@ -972,8 +985,10 @@
std::string serializedDeviceTypes;
// TODO: only routed device id is logged, but no device type
- int32_t formatApp = 0;
- // TODO: log format from app
+ std::string formatAppStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_ENCODINGREQUESTED, &formatAppStr);
+ const auto formatApp = types::lookup<types::ENCODING, int32_t>(formatAppStr);
std::string formatDeviceStr;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
@@ -981,7 +996,8 @@
const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);
std::string logSessionId;
- // TODO: log logSessionId
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_LOGSESSIONID, &logSessionId);
int32_t sampleRate = 0;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
@@ -1001,11 +1017,11 @@
<< " channel_count:" << channelCount
<< " total_frames_transferred:" << totalFramesTransferred
<< " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
- << " perf_mode_actual:" << perfModeActual
+ << " perf_mode_actual:" << perfModeActual << "(" << perfModeActualStr << ")"
<< " sharing:" << sharingMode << "(" << sharingModeStr << ")"
<< " xrun_count:" << xrunCount
<< " device_type:" << serializedDeviceTypes
- << " format_app:" << formatApp
+ << " format_app:" << formatApp << "(" << formatAppStr << ")"
<< " format_device: " << formatDevice << "(" << formatDeviceStr << ")"
<< " log_session_id: " << logSessionId
<< " sample_rate: " << sampleRate
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index faea58f..13dd3d3 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -38,6 +38,10 @@
using namespace android; // TODO just import names needed
using namespace aaudio; // TODO just import names needed
+AAudioServiceEndpoint::~AAudioServiceEndpoint() {
+ ALOGD("%s() called", __func__);
+}
+
std::string AAudioServiceEndpoint::dump() const NO_THREAD_SAFETY_ANALYSIS {
std::stringstream result;
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index 72090c2..a7f63d3 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -43,7 +43,7 @@
, public AAudioStreamParameters {
public:
- virtual ~AAudioServiceEndpoint() = default;
+ virtual ~AAudioServiceEndpoint();
virtual std::string dump() const;
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 556710d..7294a58 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -51,8 +51,6 @@
: mMmapStream(nullptr)
, mAAudioService(audioService) {}
-AAudioServiceEndpointMMAP::~AAudioServiceEndpointMMAP() {}
-
std::string AAudioServiceEndpointMMAP::dump() const {
std::stringstream result;
@@ -357,7 +355,10 @@
// This is called by AudioFlinger when it wants to destroy a stream.
void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t portHandle) {
ALOGD("%s(portHandle = %d) called", __func__, portHandle);
- std::thread asyncTask(&AAudioServiceEndpointMMAP::handleTearDownAsync, this, portHandle);
+ android::sp<AAudioServiceEndpointMMAP> holdEndpoint(this);
+ std::thread asyncTask([holdEndpoint, portHandle]() {
+ holdEndpoint->handleTearDownAsync(portHandle);
+ });
asyncTask.detach();
}
@@ -378,9 +379,11 @@
ALOGD("%s() called with dev %d, old = %d", __func__, deviceId, getDeviceId());
if (getDeviceId() != deviceId) {
if (getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
- std::thread asyncTask([this, deviceId]() {
- disconnectRegisteredStreams();
- setDeviceId(deviceId);
+ android::sp<AAudioServiceEndpointMMAP> holdEndpoint(this);
+ std::thread asyncTask([holdEndpoint, deviceId]() {
+ ALOGD("onRoutingChanged() asyncTask launched");
+ holdEndpoint->disconnectRegisteredStreams();
+ holdEndpoint->setDeviceId(deviceId);
});
asyncTask.detach();
} else {
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index 24b161d..5a53885 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -44,7 +44,7 @@
public:
explicit AAudioServiceEndpointMMAP(android::AAudioService &audioService);
- virtual ~AAudioServiceEndpointMMAP();
+ virtual ~AAudioServiceEndpointMMAP() = default;
std::string dump() const override;
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 8638f36..dbacd75 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -67,8 +67,7 @@
// If the stream is deleted when OPEN or in use then audio resources will leak.
// This would indicate an internal error. So we want to find this ASAP.
LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
- || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
- || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
+ || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED),
"service stream %p still open, state = %d",
this, getState());
}
@@ -229,7 +228,7 @@
aaudio_result_t result = AAUDIO_OK;
if (auto state = getState();
- state == AAUDIO_STREAM_STATE_CLOSED || state == AAUDIO_STREAM_STATE_DISCONNECTED) {
+ state == AAUDIO_STREAM_STATE_CLOSED || isDisconnected_l()) {
ALOGW("%s() already CLOSED, returns INVALID_STATE, handle = %d",
__func__, getHandle());
return AAUDIO_ERROR_INVALID_STATE;
@@ -261,8 +260,14 @@
sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
setState(AAUDIO_STREAM_STATE_STARTED);
mThreadEnabled.store(true);
+ // Make sure this object does not get deleted before the run() method
+ // can protect it by making a strong pointer.
+ incStrong(nullptr); // See run() method.
result = mTimestampThread.start(this);
- if (result != AAUDIO_OK) goto error;
+ if (result != AAUDIO_OK) {
+ decStrong(nullptr); // run() can't do it so we have to do it here.
+ goto error;
+ }
return result;
@@ -336,7 +341,12 @@
setState(AAUDIO_STREAM_STATE_STOPPING);
+ // Temporarily unlock because we are joining the timestamp thread and it may try
+ // to acquire mLock.
+ mLock.unlock();
result = stopTimestampThread();
+ mLock.lock();
+
if (result != AAUDIO_OK) {
disconnect_l();
return result;
@@ -396,7 +406,12 @@
__attribute__((no_sanitize("integer")))
void AAudioServiceStreamBase::run() {
ALOGD("%s() %s entering >>>>>>>>>>>>>> TIMESTAMPS", __func__, getTypeText());
+ // Hold onto the ref counted stream until the end.
+ android::sp<AAudioServiceStreamBase> holdStream(this);
TimestampScheduler timestampScheduler;
+ // Balance the incStrong from when the thread was launched.
+ holdStream->decStrong(nullptr);
+
timestampScheduler.setBurstPeriod(mFramesPerBurst, getSampleRate());
timestampScheduler.start(AudioClock::getNanoseconds());
int64_t nextTime = timestampScheduler.nextAbsoluteTime();
@@ -432,8 +447,7 @@
}
void AAudioServiceStreamBase::disconnect_l() {
- if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED
- && getState() != AAUDIO_STREAM_STATE_CLOSED) {
+ if (!isDisconnected_l() && getState() != AAUDIO_STREAM_STATE_CLOSED) {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
@@ -441,7 +455,7 @@
.record();
sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
- setState(AAUDIO_STREAM_STATE_DISCONNECTED);
+ setDisconnected_l(true);
}
}
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index 8e5c8ef..c42df0f 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -265,6 +265,13 @@
aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
+ bool isDisconnected_l() const REQUIRES(mLock) {
+ return mDisconnected;
+ }
+ void setDisconnected_l(bool flag) REQUIRES(mLock) {
+ mDisconnected = flag;
+ }
+
pid_t mRegisteredClientThread = ILLEGAL_THREAD_ID;
std::mutex mUpMessageQueueLock;
@@ -322,6 +329,8 @@
// for example a full message queue. Note that this atomic is unrelated to mCloseNeeded.
std::atomic<bool> mSuspended{false};
+ bool mDisconnected GUARDED_BY(mLock) {false};
+
protected:
// Locking order is important.
// Acquire mLock before acquiring AAudioServiceEndpoint::mLockStreams