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,