1 /*
2 **
3 ** Copyright 2021, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 
19 #define LOG_TAG "Spatializer"
20 //#define LOG_NDEBUG 0
21 #include <utils/Log.h>
22 
23 #include <limits.h>
24 #include <stdint.h>
25 #include <sys/types.h>
26 
27 #include <android/content/AttributionSourceState.h>
28 #include <audio_utils/fixedfft.h>
29 #include <cutils/bitops.h>
30 #include <hardware/sensors.h>
31 #include <media/audiohal/EffectsFactoryHalInterface.h>
32 #include <media/stagefright/foundation/AHandler.h>
33 #include <media/stagefright/foundation/AMessage.h>
34 #include <media/ShmemCompat.h>
35 #include <mediautils/ServiceUtilities.h>
36 #include <utils/Thread.h>
37 
38 #include "Spatializer.h"
39 
40 namespace android {
41 
42 using aidl_utils::statusTFromBinderStatus;
43 using aidl_utils::binderStatusFromStatusT;
44 using android::content::AttributionSourceState;
45 using binder::Status;
46 using media::HeadTrackingMode;
47 using media::Pose3f;
48 using media::SpatializationLevel;
49 using media::SpatializationMode;
50 using media::SpatializerHeadTrackingMode;
51 using media::SensorPoseProvider;
52 
53 using namespace std::chrono_literals;
54 
55 #define VALUE_OR_RETURN_BINDER_STATUS(x) \
56     ({ auto _tmp = (x); \
57        if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
58        std::move(_tmp.value()); })
59 
60 // ---------------------------------------------------------------------------
61 
62 class Spatializer::EngineCallbackHandler : public AHandler {
63 public:
EngineCallbackHandler(wp<Spatializer> spatializer)64     EngineCallbackHandler(wp<Spatializer> spatializer)
65             : mSpatializer(spatializer) {
66     }
67 
68     enum {
69         // Device state callbacks
70         kWhatOnFramesProcessed,    // AudioEffect::EVENT_FRAMES_PROCESSED
71         kWhatOnHeadToStagePose,    // SpatializerPoseController::Listener::onHeadToStagePose
72         kWhatOnActualModeChange,   // SpatializerPoseController::Listener::onActualModeChange
73     };
74     static constexpr const char *kNumFramesKey = "numFrames";
75     static constexpr const char *kModeKey = "mode";
76     static constexpr const char *kTranslation0Key = "translation0";
77     static constexpr const char *kTranslation1Key = "translation1";
78     static constexpr const char *kTranslation2Key = "translation2";
79     static constexpr const char *kRotation0Key = "rotation0";
80     static constexpr const char *kRotation1Key = "rotation1";
81     static constexpr const char *kRotation2Key = "rotation2";
82 
onMessageReceived(const sp<AMessage> & msg)83     void onMessageReceived(const sp<AMessage> &msg) override {
84         switch (msg->what()) {
85             case kWhatOnFramesProcessed: {
86                 sp<Spatializer> spatializer = mSpatializer.promote();
87                 if (spatializer == nullptr) {
88                     ALOGW("%s: Cannot promote spatializer", __func__);
89                     return;
90                 }
91                 int numFrames;
92                 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
93                     ALOGE("%s: Cannot find num frames!", __func__);
94                     return;
95                 }
96                 if (numFrames > 0) {
97                     spatializer->calculateHeadPose();
98                 }
99                 } break;
100             case kWhatOnHeadToStagePose: {
101                 sp<Spatializer> spatializer = mSpatializer.promote();
102                 if (spatializer == nullptr) {
103                     ALOGW("%s: Cannot promote spatializer", __func__);
104                     return;
105                 }
106                 std::vector<float> headToStage(sHeadPoseKeys.size());
107                 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
108                     if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
109                         ALOGE("%s: Cannot find kTranslation0Key!", __func__);
110                         return;
111                     }
112                 }
113                 spatializer->onHeadToStagePoseMsg(headToStage);
114                 } break;
115             case kWhatOnActualModeChange: {
116                 sp<Spatializer> spatializer = mSpatializer.promote();
117                 if (spatializer == nullptr) {
118                     ALOGW("%s: Cannot promote spatializer", __func__);
119                     return;
120                 }
121                 int mode;
122                 if (!msg->findInt32(EngineCallbackHandler::kModeKey, &mode)) {
123                     ALOGE("%s: Cannot find actualMode!", __func__);
124                     return;
125                 }
126                 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
127                 } break;
128             default:
129                 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
130         }
131     }
132 private:
133     wp<Spatializer> mSpatializer;
134 };
135 
136 const std::vector<const char *> Spatializer::sHeadPoseKeys = {
137     Spatializer::EngineCallbackHandler::kTranslation0Key,
138     Spatializer::EngineCallbackHandler::kTranslation1Key,
139     Spatializer::EngineCallbackHandler::kTranslation2Key,
140     Spatializer::EngineCallbackHandler::kRotation0Key,
141     Spatializer::EngineCallbackHandler::kRotation1Key,
142     Spatializer::EngineCallbackHandler::kRotation2Key,
143 };
144 
145 // ---------------------------------------------------------------------------
create(SpatializerPolicyCallback * callback)146 sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
147     sp<Spatializer> spatializer;
148 
149     sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
150     if (effectsFactoryHal == nullptr) {
151         ALOGW("%s failed to create effect factory interface", __func__);
152         return spatializer;
153     }
154 
155     std::vector<effect_descriptor_t> descriptors;
156     status_t status =
157             effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
158     if (status != NO_ERROR) {
159         ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
160         return spatializer;
161     }
162     ALOG_ASSERT(!descriptors.empty(),
163             "%s getDescriptors() returned no error but empty list", __func__);
164 
165     //TODO: get supported spatialization modes from FX engine or descriptor
166 
167     sp<EffectHalInterface> effect;
168     status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
169             AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
170     ALOGI("%s FX create status %d effect %p", __func__, status, effect.get());
171 
172     if (status == NO_ERROR && effect != nullptr) {
173         spatializer = new Spatializer(descriptors[0], callback);
174         if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
175             spatializer.clear();
176         }
177     }
178 
179     return spatializer;
180 }
181 
Spatializer(effect_descriptor_t engineDescriptor,SpatializerPolicyCallback * callback)182 Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
183     : mEngineDescriptor(engineDescriptor),
184       mPolicyCallback(callback) {
185     ALOGV("%s", __func__);
186 }
187 
onFirstRef()188 void Spatializer::onFirstRef() {
189     mLooper = new ALooper;
190     mLooper->setName("Spatializer-looper");
191     mLooper->start(
192             /*runOnCallingThread*/false,
193             /*canCallJava*/       false,
194             PRIORITY_AUDIO);
195 
196     mHandler = new EngineCallbackHandler(this);
197     mLooper->registerHandler(mHandler);
198 }
199 
~Spatializer()200 Spatializer::~Spatializer() {
201     ALOGV("%s", __func__);
202     if (mLooper != nullptr) {
203         mLooper->stop();
204         mLooper->unregisterHandler(mHandler->id());
205     }
206     mLooper.clear();
207     mHandler.clear();
208 }
209 
loadEngineConfiguration(sp<EffectHalInterface> effect)210 status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
211     ALOGV("%s", __func__);
212 
213     std::vector<bool> supportsHeadTracking;
214     status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
215                                          &supportsHeadTracking);
216     if (status != NO_ERROR) {
217         return status;
218     }
219     mSupportsHeadTracking = supportsHeadTracking[0];
220 
221     status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS, &mLevels);
222     if (status != NO_ERROR) {
223         return status;
224     }
225     status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
226                                 &mSpatializationModes);
227     if (status != NO_ERROR) {
228         return status;
229     }
230     status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
231                                  &mChannelMasks);
232     if (status != NO_ERROR) {
233         return status;
234     }
235     return NO_ERROR;
236 }
237 
238 /** Gets the channel mask, sampling rate and format set for the spatializer input. */
getAudioInConfig() const239 audio_config_base_t Spatializer::getAudioInConfig() const {
240     std::lock_guard lock(mLock);
241     audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
242     // For now use highest supported channel count
243     uint32_t maxCount = 0;
244     for ( auto mask : mChannelMasks) {
245         if (audio_channel_count_from_out_mask(mask) > maxCount) {
246             config.channel_mask = mask;
247         }
248     }
249     return config;
250 }
251 
registerCallback(const sp<media::INativeSpatializerCallback> & callback)252 status_t Spatializer::registerCallback(
253         const sp<media::INativeSpatializerCallback>& callback) {
254     std::lock_guard lock(mLock);
255     if (callback == nullptr) {
256         return BAD_VALUE;
257     }
258 
259     sp<IBinder> binder = IInterface::asBinder(callback);
260     status_t status = binder->linkToDeath(this);
261     if (status == NO_ERROR) {
262         mSpatializerCallback = callback;
263     }
264     ALOGV("%s status %d", __func__, status);
265     return status;
266 }
267 
268 // IBinder::DeathRecipient
binderDied(__unused const wp<IBinder> & who)269 void Spatializer::binderDied(__unused const wp<IBinder> &who) {
270     {
271         std::lock_guard lock(mLock);
272         mLevel = SpatializationLevel::NONE;
273         mSpatializerCallback.clear();
274     }
275     ALOGV("%s", __func__);
276     mPolicyCallback->onCheckSpatializer();
277 }
278 
279 // ISpatializer
getSupportedLevels(std::vector<SpatializationLevel> * levels)280 Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
281     ALOGV("%s", __func__);
282     if (levels == nullptr) {
283         return binderStatusFromStatusT(BAD_VALUE);
284     }
285     levels->push_back(SpatializationLevel::NONE);
286     levels->insert(levels->end(), mLevels.begin(), mLevels.end());
287     return Status::ok();
288 }
289 
setLevel(SpatializationLevel level)290 Status Spatializer::setLevel(SpatializationLevel level) {
291     ALOGV("%s level %d", __func__, (int)level);
292     if (level != SpatializationLevel::NONE
293             && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
294         return binderStatusFromStatusT(BAD_VALUE);
295     }
296     sp<media::INativeSpatializerCallback> callback;
297     bool levelChanged = false;
298     {
299         std::lock_guard lock(mLock);
300         levelChanged = mLevel != level;
301         mLevel = level;
302         callback = mSpatializerCallback;
303 
304         if (levelChanged && mEngine != nullptr) {
305             setEffectParameter_l(SPATIALIZER_PARAM_LEVEL, std::vector<SpatializationLevel>{level});
306         }
307     }
308 
309     if (levelChanged) {
310         mPolicyCallback->onCheckSpatializer();
311         if (callback != nullptr) {
312             callback->onLevelChanged(level);
313         }
314     }
315     return Status::ok();
316 }
317 
getLevel(SpatializationLevel * level)318 Status Spatializer::getLevel(SpatializationLevel *level) {
319     if (level == nullptr) {
320         return binderStatusFromStatusT(BAD_VALUE);
321     }
322     std::lock_guard lock(mLock);
323     *level = mLevel;
324     ALOGV("%s level %d", __func__, (int)*level);
325     return Status::ok();
326 }
327 
isHeadTrackingSupported(bool * supports)328 Status Spatializer::isHeadTrackingSupported(bool *supports) {
329     ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
330     if (supports == nullptr) {
331         return binderStatusFromStatusT(BAD_VALUE);
332     }
333     std::lock_guard lock(mLock);
334     *supports = mSupportsHeadTracking;
335     return Status::ok();
336 }
337 
getSupportedHeadTrackingModes(std::vector<SpatializerHeadTrackingMode> * modes)338 Status Spatializer::getSupportedHeadTrackingModes(
339         std::vector<SpatializerHeadTrackingMode>* modes) {
340     std::lock_guard lock(mLock);
341     ALOGV("%s", __func__);
342     if (modes == nullptr) {
343         return binderStatusFromStatusT(BAD_VALUE);
344     }
345 
346     modes->push_back(SpatializerHeadTrackingMode::DISABLED);
347     if (mSupportsHeadTracking) {
348         if (mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
349             modes->push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
350             if (mScreenSensor != SpatializerPoseController::INVALID_SENSOR) {
351                 modes->push_back(SpatializerHeadTrackingMode::RELATIVE_SCREEN);
352             }
353         }
354     }
355     return Status::ok();
356 }
357 
setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode)358 Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
359     ALOGV("%s mode %d", __func__, (int)mode);
360 
361     if (!mSupportsHeadTracking) {
362         return binderStatusFromStatusT(INVALID_OPERATION);
363     }
364     std::lock_guard lock(mLock);
365     switch (mode) {
366         case SpatializerHeadTrackingMode::OTHER:
367             return binderStatusFromStatusT(BAD_VALUE);
368         case SpatializerHeadTrackingMode::DISABLED:
369             mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
370             break;
371         case SpatializerHeadTrackingMode::RELATIVE_WORLD:
372             mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
373             break;
374         case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
375             mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
376             break;
377     }
378 
379     if (mPoseController != nullptr) {
380         mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
381     }
382 
383     return Status::ok();
384 }
385 
getActualHeadTrackingMode(SpatializerHeadTrackingMode * mode)386 Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
387     if (mode == nullptr) {
388         return binderStatusFromStatusT(BAD_VALUE);
389     }
390     std::lock_guard lock(mLock);
391     *mode = mActualHeadTrackingMode;
392     ALOGV("%s mode %d", __func__, (int)*mode);
393     return Status::ok();
394 }
395 
recenterHeadTracker()396 Status Spatializer::recenterHeadTracker() {
397     if (!mSupportsHeadTracking) {
398         return binderStatusFromStatusT(INVALID_OPERATION);
399     }
400     std::lock_guard lock(mLock);
401     if (mPoseController != nullptr) {
402         mPoseController->recenter();
403     }
404     return Status::ok();
405 }
406 
setGlobalTransform(const std::vector<float> & screenToStage)407 Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
408     ALOGV("%s", __func__);
409     if (!mSupportsHeadTracking) {
410         return binderStatusFromStatusT(INVALID_OPERATION);
411     }
412     std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
413     if (!maybePose.has_value()) {
414         ALOGW("Invalid screenToStage vector.");
415         return binderStatusFromStatusT(BAD_VALUE);
416     }
417     std::lock_guard lock(mLock);
418     if (mPoseController != nullptr) {
419         mPoseController->setScreenToStagePose(maybePose.value());
420     }
421     return Status::ok();
422 }
423 
release()424 Status Spatializer::release() {
425     ALOGV("%s", __func__);
426     bool levelChanged = false;
427     {
428         std::lock_guard lock(mLock);
429         if (mSpatializerCallback == nullptr) {
430             return binderStatusFromStatusT(INVALID_OPERATION);
431         }
432 
433         sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
434         binder->unlinkToDeath(this);
435         mSpatializerCallback.clear();
436 
437         levelChanged = mLevel != SpatializationLevel::NONE;
438         mLevel = SpatializationLevel::NONE;
439     }
440 
441     if (levelChanged) {
442         mPolicyCallback->onCheckSpatializer();
443     }
444     return Status::ok();
445 }
446 
setHeadSensor(int sensorHandle)447 Status Spatializer::setHeadSensor(int sensorHandle) {
448     ALOGV("%s sensorHandle %d", __func__, sensorHandle);
449     if (!mSupportsHeadTracking) {
450         return binderStatusFromStatusT(INVALID_OPERATION);
451     }
452     std::lock_guard lock(mLock);
453     mHeadSensor = sensorHandle;
454     if (mPoseController != nullptr) {
455         mPoseController->setHeadSensor(mHeadSensor);
456     }
457     return Status::ok();
458 }
459 
setScreenSensor(int sensorHandle)460 Status Spatializer::setScreenSensor(int sensorHandle) {
461     ALOGV("%s sensorHandle %d", __func__, sensorHandle);
462     if (!mSupportsHeadTracking) {
463         return binderStatusFromStatusT(INVALID_OPERATION);
464     }
465     std::lock_guard lock(mLock);
466     mScreenSensor = sensorHandle;
467     if (mPoseController != nullptr) {
468         mPoseController->setScreenSensor(mScreenSensor);
469     }
470     return Status::ok();
471 }
472 
setDisplayOrientation(float physicalToLogicalAngle)473 Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
474     ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
475     if (!mSupportsHeadTracking) {
476         return binderStatusFromStatusT(INVALID_OPERATION);
477     }
478     std::lock_guard lock(mLock);
479     mDisplayOrientation = physicalToLogicalAngle;
480     if (mPoseController != nullptr) {
481         mPoseController->setDisplayOrientation(mDisplayOrientation);
482     }
483     if (mEngine != nullptr) {
484         setEffectParameter_l(
485             SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
486     }
487     return Status::ok();
488 }
489 
setHingeAngle(float hingeAngle)490 Status Spatializer::setHingeAngle(float hingeAngle) {
491     std::lock_guard lock(mLock);
492     ALOGV("%s hingeAngle %f", __func__, hingeAngle);
493     if (mEngine != nullptr) {
494         setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
495     }
496     return Status::ok();
497 }
498 
getSupportedModes(std::vector<SpatializationMode> * modes)499 Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
500     ALOGV("%s", __func__);
501     if (modes == nullptr) {
502         return binderStatusFromStatusT(BAD_VALUE);
503     }
504     *modes = mSpatializationModes;
505     return Status::ok();
506 }
507 
registerHeadTrackingCallback(const sp<media::ISpatializerHeadTrackingCallback> & callback)508 Status Spatializer::registerHeadTrackingCallback(
509         const sp<media::ISpatializerHeadTrackingCallback>& callback) {
510     ALOGV("%s callback %p", __func__, callback.get());
511     std::lock_guard lock(mLock);
512     if (!mSupportsHeadTracking) {
513         return binderStatusFromStatusT(INVALID_OPERATION);
514     }
515     mHeadTrackingCallback = callback;
516     return Status::ok();
517 }
518 
setParameter(int key,const std::vector<unsigned char> & value)519 Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
520     ALOGV("%s key %d", __func__, key);
521     std::lock_guard lock(mLock);
522     status_t status = INVALID_OPERATION;
523     if (mEngine != nullptr) {
524         status = setEffectParameter_l(key, value);
525     }
526     return binderStatusFromStatusT(status);
527 }
528 
getParameter(int key,std::vector<unsigned char> * value)529 Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
530     ALOGV("%s key %d value size %d", __func__, key,
531           (value != nullptr ? (int)value->size() : -1));
532     if (value == nullptr) {
533         return binderStatusFromStatusT(BAD_VALUE);
534     }
535     std::lock_guard lock(mLock);
536     status_t status = INVALID_OPERATION;
537     if (mEngine != nullptr) {
538         ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
539         status = getEffectParameter_l(key, value);
540     }
541     return binderStatusFromStatusT(status);
542 }
543 
getOutput(int * output)544 Status Spatializer::getOutput(int *output) {
545     ALOGV("%s", __func__);
546     if (output == nullptr) {
547         binderStatusFromStatusT(BAD_VALUE);
548     }
549     std::lock_guard lock(mLock);
550     *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
551     ALOGV("%s got output %d", __func__, *output);
552     return Status::ok();
553 }
554 
555 // SpatializerPoseController::Listener
onHeadToStagePose(const Pose3f & headToStage)556 void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
557     ALOGV("%s", __func__);
558     LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
559             "onHeadToStagePose() called with no head tracking support!");
560 
561     auto vec = headToStage.toVector();
562     LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
563             "%s invalid head to stage vector size %zu", __func__, vec.size());
564 
565     sp<AMessage> msg =
566             new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
567     for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
568         msg->setFloat(sHeadPoseKeys[i], vec[i]);
569     }
570     msg->post();
571 }
572 
onHeadToStagePoseMsg(const std::vector<float> & headToStage)573 void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
574     ALOGV("%s", __func__);
575     sp<media::ISpatializerHeadTrackingCallback> callback;
576     {
577         std::lock_guard lock(mLock);
578         callback = mHeadTrackingCallback;
579         if (mEngine != nullptr) {
580             setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
581         }
582     }
583 
584     if (callback != nullptr) {
585         callback->onHeadToSoundStagePoseUpdated(headToStage);
586     }
587 }
588 
onActualModeChange(HeadTrackingMode mode)589 void Spatializer::onActualModeChange(HeadTrackingMode mode) {
590     ALOGV("%s(%d)", __func__, (int)mode);
591     sp<AMessage> msg =
592             new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
593     msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
594     msg->post();
595 }
596 
onActualModeChangeMsg(HeadTrackingMode mode)597 void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
598     ALOGV("%s(%d)", __func__, (int) mode);
599     sp<media::ISpatializerHeadTrackingCallback> callback;
600     SpatializerHeadTrackingMode spatializerMode;
601     {
602         std::lock_guard lock(mLock);
603         if (!mSupportsHeadTracking) {
604             spatializerMode = SpatializerHeadTrackingMode::DISABLED;
605         } else {
606             switch (mode) {
607                 case HeadTrackingMode::STATIC:
608                     spatializerMode = SpatializerHeadTrackingMode::DISABLED;
609                     break;
610                 case HeadTrackingMode::WORLD_RELATIVE:
611                     spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
612                     break;
613                 case HeadTrackingMode::SCREEN_RELATIVE:
614                     spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
615                     break;
616                 default:
617                     LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
618             }
619         }
620         mActualHeadTrackingMode = spatializerMode;
621         callback = mHeadTrackingCallback;
622     }
623     if (callback != nullptr) {
624         callback->onHeadTrackingModeChanged(spatializerMode);
625     }
626 }
627 
attachOutput(audio_io_handle_t output)628 status_t Spatializer::attachOutput(audio_io_handle_t output) {
629     std::shared_ptr<SpatializerPoseController> poseController;
630     bool outputChanged = false;
631     sp<media::INativeSpatializerCallback> callback;
632 
633     {
634         std::lock_guard lock(mLock);
635         ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
636         if (mOutput != AUDIO_IO_HANDLE_NONE) {
637             LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
638             // remove FX instance
639             mEngine->setEnabled(false);
640             mEngine.clear();
641         }
642         // create FX instance on output
643         AttributionSourceState attributionSource = AttributionSourceState();
644         mEngine = new AudioEffect(attributionSource);
645         mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
646                      this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
647                      false /* probe */, true /* notifyFramesProcessed */);
648         status_t status = mEngine->initCheck();
649         ALOGV("%s mEngine create status %d", __func__, (int)status);
650         if (status != NO_ERROR) {
651             return status;
652         }
653 
654         setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
655                              std::vector<SpatializationLevel>{mLevel});
656         setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
657                              std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
658 
659         mEngine->setEnabled(true);
660         outputChanged = mOutput != output;
661         mOutput = output;
662 
663         if (mSupportsHeadTracking) {
664             mPoseController = std::make_shared<SpatializerPoseController>(
665                     static_cast<SpatializerPoseController::Listener*>(this), 10ms, 50ms);
666             LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
667                                 "%s could not allocate pose controller", __func__);
668 
669             mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
670             mPoseController->setHeadSensor(mHeadSensor);
671             mPoseController->setScreenSensor(mScreenSensor);
672             mPoseController->setDisplayOrientation(mDisplayOrientation);
673             poseController = mPoseController;
674         }
675         callback = mSpatializerCallback;
676     }
677     if (poseController != nullptr) {
678         poseController->waitUntilCalculated();
679     }
680 
681     if (outputChanged && callback != nullptr) {
682         callback->onOutputChanged(output);
683     }
684 
685     return NO_ERROR;
686 }
687 
detachOutput()688 audio_io_handle_t Spatializer::detachOutput() {
689     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
690     sp<media::INativeSpatializerCallback> callback;
691 
692     {
693         std::lock_guard lock(mLock);
694         ALOGV("%s mOutput %d", __func__, (int)mOutput);
695         if (mOutput == AUDIO_IO_HANDLE_NONE) {
696             return output;
697         }
698         // remove FX instance
699         mEngine->setEnabled(false);
700         mEngine.clear();
701         output = mOutput;
702         mOutput = AUDIO_IO_HANDLE_NONE;
703         mPoseController.reset();
704 
705         callback = mSpatializerCallback;
706     }
707 
708     if (callback != nullptr) {
709         callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
710     }
711     return output;
712 }
713 
calculateHeadPose()714 void Spatializer::calculateHeadPose() {
715     ALOGV("%s", __func__);
716     std::lock_guard lock(mLock);
717     if (mPoseController != nullptr) {
718         mPoseController->calculateAsync();
719     }
720 }
721 
engineCallback(int32_t event,void * user,void * info)722 void Spatializer::engineCallback(int32_t event, void *user, void *info) {
723     if (user == nullptr) {
724         return;
725     }
726     Spatializer* const me = reinterpret_cast<Spatializer *>(user);
727     switch (event) {
728         case AudioEffect::EVENT_FRAMES_PROCESSED: {
729             int frames = info == nullptr ? 0 : *(int*)info;
730             ALOGD("%s frames processed %d for me %p", __func__, frames, me);
731             me->postFramesProcessedMsg(frames);
732         } break;
733         default:
734             ALOGD("%s event %d", __func__, event);
735             break;
736     }
737 }
738 
postFramesProcessedMsg(int frames)739 void Spatializer::postFramesProcessedMsg(int frames) {
740     sp<AMessage> msg =
741             new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
742     msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
743     msg->post();
744 }
745 
746 } // namespace android
747