Spatializer: process callbacks in separate thread
Add a Looper and Handler to process events from the engine
and pose controler callback to avoid cross mutex deadlocks.
Bug: 188502620
Test: manual test with mock spatializer
Change-Id: I1342602259b147727c704ad7bbeb1b3a68c7b231
Merged-In: I1342602259b147727c704ad7bbeb1b3a68c7b231
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index c5506a3..7d49ea2 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -29,8 +29,10 @@
#include <audio_utils/fixedfft.h>
#include <cutils/bitops.h>
#include <hardware/sensors.h>
-#include <media/ShmemCompat.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/ShmemCompat.h>
#include <mediautils/ServiceUtilities.h>
#include <utils/Thread.h>
@@ -49,7 +51,6 @@
using media::SpatializerHeadTrackingMode;
using media::SensorPoseProvider;
-
using namespace std::chrono_literals;
#define VALUE_OR_RETURN_BINDER_STATUS(x) \
@@ -65,6 +66,90 @@
// ---------------------------------------------------------------------------
+class Spatializer::EngineCallbackHandler : public AHandler {
+public:
+ EngineCallbackHandler(wp<Spatializer> spatializer)
+ : mSpatializer(spatializer) {
+ }
+
+ enum {
+ // Device state callbacks
+ kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
+ kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
+ kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
+ };
+ static constexpr const char *kNumFramesKey = "numFrames";
+ static constexpr const char *kModeKey = "mode";
+ static constexpr const char *kTranslation0Key = "translation0";
+ static constexpr const char *kTranslation1Key = "translation1";
+ static constexpr const char *kTranslation2Key = "translation2";
+ static constexpr const char *kRotation0Key = "rotation0";
+ static constexpr const char *kRotation1Key = "rotation1";
+ static constexpr const char *kRotation2Key = "rotation2";
+
+ void onMessageReceived(const sp<AMessage> &msg) override {
+ switch (msg->what()) {
+ case kWhatOnFramesProcessed: {
+ sp<Spatializer> spatializer = mSpatializer.promote();
+ if (spatializer == nullptr) {
+ ALOGW("%s: Cannot promote spatializer", __func__);
+ return;
+ }
+ int numFrames;
+ if (!msg->findInt32(kNumFramesKey, &numFrames)) {
+ ALOGE("%s: Cannot find num frames!", __func__);
+ return;
+ }
+ if (numFrames > 0) {
+ spatializer->calculateHeadPose();
+ }
+ } break;
+ case kWhatOnHeadToStagePose: {
+ sp<Spatializer> spatializer = mSpatializer.promote();
+ if (spatializer == nullptr) {
+ ALOGW("%s: Cannot promote spatializer", __func__);
+ return;
+ }
+ std::vector<float> headToStage(sHeadPoseKeys.size());
+ for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
+ if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
+ ALOGE("%s: Cannot find kTranslation0Key!", __func__);
+ return;
+ }
+ }
+ spatializer->onHeadToStagePoseMsg(headToStage);
+ } break;
+ case kWhatOnActualModeChange: {
+ sp<Spatializer> spatializer = mSpatializer.promote();
+ if (spatializer == nullptr) {
+ ALOGW("%s: Cannot promote spatializer", __func__);
+ return;
+ }
+ int mode;
+ if (!msg->findInt32(EngineCallbackHandler::kModeKey, &mode)) {
+ ALOGE("%s: Cannot find actualMode!", __func__);
+ return;
+ }
+ spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
+ } break;
+ default:
+ LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
+ }
+ }
+private:
+ wp<Spatializer> mSpatializer;
+};
+
+const std::vector<const char *> Spatializer::sHeadPoseKeys = {
+ Spatializer::EngineCallbackHandler::kTranslation0Key,
+ Spatializer::EngineCallbackHandler::kTranslation1Key,
+ Spatializer::EngineCallbackHandler::kTranslation2Key,
+ Spatializer::EngineCallbackHandler::kRotation0Key,
+ Spatializer::EngineCallbackHandler::kRotation1Key,
+ Spatializer::EngineCallbackHandler::kRotation2Key,
+};
+
+// ---------------------------------------------------------------------------
sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
sp<Spatializer> spatializer;
@@ -107,8 +192,26 @@
ALOGV("%s", __func__);
}
+void Spatializer::onFirstRef() {
+ mLooper = new ALooper;
+ mLooper->setName("Spatializer-looper");
+ mLooper->start(
+ /*runOnCallingThread*/false,
+ /*canCallJava*/ false,
+ PRIORITY_AUDIO);
+
+ mHandler = new EngineCallbackHandler(this);
+ mLooper->registerHandler(mHandler);
+}
+
Spatializer::~Spatializer() {
ALOGV("%s", __func__);
+ if (mLooper != nullptr) {
+ mLooper->stop();
+ mLooper->unregisterHandler(mHandler->id());
+ }
+ mLooper.clear();
+ mHandler.clear();
}
status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
@@ -391,23 +494,44 @@
// SpatializerPoseController::Listener
void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
ALOGV("%s", __func__);
- sp<media::INativeSpatializerCallback> callback;
auto vec = headToStage.toVector();
+ LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
+ "%s invalid head to stage vector size %zu", __func__, vec.size());
+
+ sp<AMessage> msg =
+ new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
+ for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
+ msg->setFloat(sHeadPoseKeys[i], vec[i]);
+ }
+ msg->post();
+}
+
+void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
+ ALOGV("%s", __func__);
+ sp<media::INativeSpatializerCallback> callback;
{
std::lock_guard lock(mLock);
callback = mSpatializerCallback;
if (mEngine != nullptr) {
- setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, vec);
+ setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
}
}
if (callback != nullptr) {
- callback->onHeadToSoundStagePoseUpdated(vec);
+ callback->onHeadToSoundStagePoseUpdated(headToStage);
}
}
void Spatializer::onActualModeChange(HeadTrackingMode mode) {
- ALOGV("onActualModeChange(%d)", (int) mode);
+ ALOGV("%s(%d)", __func__, (int)mode);
+ sp<AMessage> msg =
+ new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
+ msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
+ msg->post();
+}
+
+void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
+ ALOGV("%s(%d)", __func__, (int) mode);
sp<media::INativeSpatializerCallback> callback;
SpatializerHeadTrackingMode spatializerMode;
{
@@ -534,9 +658,7 @@
case AudioEffect::EVENT_FRAMES_PROCESSED: {
int frames = info == nullptr ? 0 : *(int*)info;
ALOGD("%s frames processed %d for me %p", __func__, frames, me);
- if (frames > 0) {
- me->calculateHeadPose();
- }
+ me->postFramesProcessedMsg(frames);
} break;
default:
ALOGD("%s event %d", __func__, event);
@@ -544,6 +666,13 @@
}
}
+void Spatializer::postFramesProcessedMsg(int frames) {
+ sp<AMessage> msg =
+ new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
+ msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
+ msg->post();
+}
+
// ---------------------------------------------------------------------------
Spatializer::EffectClient::EffectClient(const sp<media::IEffectClient>& effectClient,