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