blob: 7d49ea2bab8e53389220cda7e2af57f7e8b48284 [file] [log] [blame]
Eric Laurent6d607012021-07-05 11:54:40 +02001/*
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>
Eric Laurent2be8b292021-08-23 09:44:33 -070028#include <android/sensor.h>
Eric Laurent6d607012021-07-05 11:54:40 +020029#include <audio_utils/fixedfft.h>
30#include <cutils/bitops.h>
Eric Laurent2be8b292021-08-23 09:44:33 -070031#include <hardware/sensors.h>
Eric Laurent6d607012021-07-05 11:54:40 +020032#include <media/audiohal/EffectsFactoryHalInterface.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020033#include <media/stagefright/foundation/AHandler.h>
34#include <media/stagefright/foundation/AMessage.h>
35#include <media/ShmemCompat.h>
Eric Laurent6d607012021-07-05 11:54:40 +020036#include <mediautils/ServiceUtilities.h>
37#include <utils/Thread.h>
38
39#include "Spatializer.h"
40
41namespace android {
42
43using aidl_utils::statusTFromBinderStatus;
44using aidl_utils::binderStatusFromStatusT;
45using android::content::AttributionSourceState;
46using binder::Status;
Eric Laurent2be8b292021-08-23 09:44:33 -070047using media::HeadTrackingMode;
48using media::Pose3f;
Eric Laurent6d607012021-07-05 11:54:40 +020049using media::SpatializationLevel;
Eric Laurent2be8b292021-08-23 09:44:33 -070050using media::SpatializationMode;
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070051using media::SpatializerHeadTrackingMode;
Eric Laurent2be8b292021-08-23 09:44:33 -070052using media::SensorPoseProvider;
53
Eric Laurent2be8b292021-08-23 09:44:33 -070054using namespace std::chrono_literals;
Eric Laurent6d607012021-07-05 11:54:40 +020055
56#define VALUE_OR_RETURN_BINDER_STATUS(x) \
57 ({ auto _tmp = (x); \
58 if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
59 std::move(_tmp.value()); })
60
61#define RETURN_IF_BINDER_ERROR(x) \
62 { \
63 binder::Status _tmp = (x); \
64 if (!_tmp.isOk()) return _tmp; \
65 }
66
67// ---------------------------------------------------------------------------
68
Eric Laurent8a4259f2021-09-14 16:04:00 +020069class Spatializer::EngineCallbackHandler : public AHandler {
70public:
71 EngineCallbackHandler(wp<Spatializer> spatializer)
72 : mSpatializer(spatializer) {
73 }
74
75 enum {
76 // Device state callbacks
77 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
78 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
79 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
80 };
81 static constexpr const char *kNumFramesKey = "numFrames";
82 static constexpr const char *kModeKey = "mode";
83 static constexpr const char *kTranslation0Key = "translation0";
84 static constexpr const char *kTranslation1Key = "translation1";
85 static constexpr const char *kTranslation2Key = "translation2";
86 static constexpr const char *kRotation0Key = "rotation0";
87 static constexpr const char *kRotation1Key = "rotation1";
88 static constexpr const char *kRotation2Key = "rotation2";
89
90 void onMessageReceived(const sp<AMessage> &msg) override {
91 switch (msg->what()) {
92 case kWhatOnFramesProcessed: {
93 sp<Spatializer> spatializer = mSpatializer.promote();
94 if (spatializer == nullptr) {
95 ALOGW("%s: Cannot promote spatializer", __func__);
96 return;
97 }
98 int numFrames;
99 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
100 ALOGE("%s: Cannot find num frames!", __func__);
101 return;
102 }
103 if (numFrames > 0) {
104 spatializer->calculateHeadPose();
105 }
106 } break;
107 case kWhatOnHeadToStagePose: {
108 sp<Spatializer> spatializer = mSpatializer.promote();
109 if (spatializer == nullptr) {
110 ALOGW("%s: Cannot promote spatializer", __func__);
111 return;
112 }
113 std::vector<float> headToStage(sHeadPoseKeys.size());
114 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
115 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
116 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
117 return;
118 }
119 }
120 spatializer->onHeadToStagePoseMsg(headToStage);
121 } break;
122 case kWhatOnActualModeChange: {
123 sp<Spatializer> spatializer = mSpatializer.promote();
124 if (spatializer == nullptr) {
125 ALOGW("%s: Cannot promote spatializer", __func__);
126 return;
127 }
128 int mode;
129 if (!msg->findInt32(EngineCallbackHandler::kModeKey, &mode)) {
130 ALOGE("%s: Cannot find actualMode!", __func__);
131 return;
132 }
133 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
134 } break;
135 default:
136 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
137 }
138 }
139private:
140 wp<Spatializer> mSpatializer;
141};
142
143const std::vector<const char *> Spatializer::sHeadPoseKeys = {
144 Spatializer::EngineCallbackHandler::kTranslation0Key,
145 Spatializer::EngineCallbackHandler::kTranslation1Key,
146 Spatializer::EngineCallbackHandler::kTranslation2Key,
147 Spatializer::EngineCallbackHandler::kRotation0Key,
148 Spatializer::EngineCallbackHandler::kRotation1Key,
149 Spatializer::EngineCallbackHandler::kRotation2Key,
150};
151
152// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200153sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
154 sp<Spatializer> spatializer;
155
156 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
157 if (effectsFactoryHal == nullptr) {
158 ALOGW("%s failed to create effect factory interface", __func__);
159 return spatializer;
160 }
161
162 std::vector<effect_descriptor_t> descriptors;
163 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200164 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200165 if (status != NO_ERROR) {
166 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
167 return spatializer;
168 }
169 ALOG_ASSERT(!descriptors.empty(),
170 "%s getDescriptors() returned no error but empty list", __func__);
171
172 //TODO: get supported spatialization modes from FX engine or descriptor
173
174 sp<EffectHalInterface> effect;
175 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
176 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
177 ALOGI("%s FX create status %d effect %p", __func__, status, effect.get());
178
179 if (status == NO_ERROR && effect != nullptr) {
180 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700181 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
182 spatializer.clear();
183 }
Eric Laurent6d607012021-07-05 11:54:40 +0200184 }
185
186 return spatializer;
187}
188
Eric Laurent2be8b292021-08-23 09:44:33 -0700189Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
190 : mEngineDescriptor(engineDescriptor),
191 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200192 ALOGV("%s", __func__);
193}
194
Eric Laurent8a4259f2021-09-14 16:04:00 +0200195void Spatializer::onFirstRef() {
196 mLooper = new ALooper;
197 mLooper->setName("Spatializer-looper");
198 mLooper->start(
199 /*runOnCallingThread*/false,
200 /*canCallJava*/ false,
201 PRIORITY_AUDIO);
202
203 mHandler = new EngineCallbackHandler(this);
204 mLooper->registerHandler(mHandler);
205}
206
Eric Laurent6d607012021-07-05 11:54:40 +0200207Spatializer::~Spatializer() {
208 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200209 if (mLooper != nullptr) {
210 mLooper->stop();
211 mLooper->unregisterHandler(mHandler->id());
212 }
213 mLooper.clear();
214 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200215}
216
Eric Laurent2be8b292021-08-23 09:44:33 -0700217status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
218 ALOGV("%s", __func__);
219
220 std::vector<bool> supportsHeadTracking;
221 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
222 &supportsHeadTracking);
223 if (status != NO_ERROR) {
224 return status;
225 }
226 mSupportsHeadTracking = supportsHeadTracking[0];
227
228 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS, &mLevels);
229 if (status != NO_ERROR) {
230 return status;
231 }
232 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
233 &mSpatializationModes);
234 if (status != NO_ERROR) {
235 return status;
236 }
237 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
238 &mChannelMasks);
239 if (status != NO_ERROR) {
240 return status;
241 }
242 return NO_ERROR;
243}
244
245/** Gets the channel mask, sampling rate and format set for the spatializer input. */
246audio_config_base_t Spatializer::getAudioInConfig() const {
247 std::lock_guard lock(mLock);
248 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
249 // For now use highest supported channel count
250 uint32_t maxCount = 0;
251 for ( auto mask : mChannelMasks) {
252 if (audio_channel_count_from_out_mask(mask) > maxCount) {
253 config.channel_mask = mask;
254 }
255 }
256 return config;
257}
258
Eric Laurent6d607012021-07-05 11:54:40 +0200259status_t Spatializer::registerCallback(
260 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700261 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200262 if (callback == nullptr) {
263 return BAD_VALUE;
264 }
265
266 sp<IBinder> binder = IInterface::asBinder(callback);
267 status_t status = binder->linkToDeath(this);
268 if (status == NO_ERROR) {
269 mSpatializerCallback = callback;
270 }
271 ALOGV("%s status %d", __func__, status);
272 return status;
273}
274
275// IBinder::DeathRecipient
276void Spatializer::binderDied(__unused const wp<IBinder> &who) {
277 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700278 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200279 mLevel = SpatializationLevel::NONE;
280 mSpatializerCallback.clear();
281 }
282 ALOGV("%s", __func__);
283 mPolicyCallback->onCheckSpatializer();
284}
285
286// ISpatializer
287Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
288 ALOGV("%s", __func__);
289 if (levels == nullptr) {
290 return binderStatusFromStatusT(BAD_VALUE);
291 }
Eric Laurent6d607012021-07-05 11:54:40 +0200292 levels->push_back(SpatializationLevel::NONE);
Eric Laurent2be8b292021-08-23 09:44:33 -0700293 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200294 return Status::ok();
295}
296
Eric Laurent2be8b292021-08-23 09:44:33 -0700297Status Spatializer::setLevel(SpatializationLevel level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200298 ALOGV("%s level %d", __func__, (int)level);
299 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700300 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200301 return binderStatusFromStatusT(BAD_VALUE);
302 }
303 sp<media::INativeSpatializerCallback> callback;
304 bool levelChanged = false;
305 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700306 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200307 levelChanged = mLevel != level;
308 mLevel = level;
309 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700310
311 if (levelChanged && mEngine != nullptr) {
312 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL, std::vector<SpatializationLevel>{level});
313 }
Eric Laurent6d607012021-07-05 11:54:40 +0200314 }
315
316 if (levelChanged) {
317 mPolicyCallback->onCheckSpatializer();
318 if (callback != nullptr) {
319 callback->onLevelChanged(level);
320 }
321 }
322 return Status::ok();
323}
324
Eric Laurent2be8b292021-08-23 09:44:33 -0700325Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200326 if (level == nullptr) {
327 return binderStatusFromStatusT(BAD_VALUE);
328 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700329 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200330 *level = mLevel;
331 ALOGV("%s level %d", __func__, (int)*level);
332 return Status::ok();
333}
334
335Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700336 std::vector<SpatializerHeadTrackingMode>* modes) {
337 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200338 ALOGV("%s", __func__);
339 if (modes == nullptr) {
340 return binderStatusFromStatusT(BAD_VALUE);
341 }
Eric Laurent6d607012021-07-05 11:54:40 +0200342
Eric Laurent2be8b292021-08-23 09:44:33 -0700343 modes->push_back(SpatializerHeadTrackingMode::DISABLED);
344 if (mSupportsHeadTracking) {
345 if (mHeadSensor != nullptr) {
346 modes->push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
347 if (mScreenSensor != nullptr) {
348 modes->push_back(SpatializerHeadTrackingMode::RELATIVE_SCREEN);
349 }
350 }
Eric Laurent6d607012021-07-05 11:54:40 +0200351 }
352 return Status::ok();
353}
354
Eric Laurent2be8b292021-08-23 09:44:33 -0700355Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
356 ALOGV("%s mode %d", __func__, (int)mode);
357
358 if (!mSupportsHeadTracking) {
359 return binderStatusFromStatusT(INVALID_OPERATION);
360 }
361 std::lock_guard lock(mLock);
362 switch (mode) {
363 case SpatializerHeadTrackingMode::OTHER:
364 return binderStatusFromStatusT(BAD_VALUE);
365 case SpatializerHeadTrackingMode::DISABLED:
366 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
367 break;
368 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
369 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
370 break;
371 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
372 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
373 break;
374 }
375
376 if (mPoseController != nullptr) {
377 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
378 }
379
380 return Status::ok();
381}
382
383Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200384 if (mode == nullptr) {
385 return binderStatusFromStatusT(BAD_VALUE);
386 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700387 std::lock_guard lock(mLock);
388 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200389 ALOGV("%s mode %d", __func__, (int)*mode);
390 return Status::ok();
391}
392
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700393Status Spatializer::recenterHeadTracker() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700394 std::lock_guard lock(mLock);
395 if (mPoseController != nullptr) {
396 mPoseController->recenter();
397 }
Eric Laurent6d607012021-07-05 11:54:40 +0200398 return Status::ok();
399}
400
401Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200402 ALOGV("%s", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700403 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
404 if (!maybePose.has_value()) {
405 ALOGW("Invalid screenToStage vector.");
406 return binderStatusFromStatusT(BAD_VALUE);
407 }
408 std::lock_guard lock(mLock);
409 if (mPoseController != nullptr) {
410 mPoseController->setScreenToStagePose(maybePose.value());
411 }
Eric Laurent6d607012021-07-05 11:54:40 +0200412 return Status::ok();
413}
414
415Status Spatializer::release() {
416 ALOGV("%s", __func__);
417 bool levelChanged = false;
418 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700419 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200420 if (mSpatializerCallback == nullptr) {
421 return binderStatusFromStatusT(INVALID_OPERATION);
422 }
423
424 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
425 binder->unlinkToDeath(this);
426 mSpatializerCallback.clear();
427
428 levelChanged = mLevel != SpatializationLevel::NONE;
429 mLevel = SpatializationLevel::NONE;
430 }
431
432 if (levelChanged) {
433 mPolicyCallback->onCheckSpatializer();
434 }
435 return Status::ok();
436}
437
Eric Laurent2be8b292021-08-23 09:44:33 -0700438Status Spatializer::setHeadSensor(int sensorHandle) {
439 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
440 std::lock_guard lock(mLock);
441 if (sensorHandle == ASENSOR_INVALID) {
442 mHeadSensor = nullptr;
443 } else {
444 mHeadSensor = VALUE_OR_RETURN_BINDER_STATUS(getSensorFromHandle(sensorHandle));
445 }
446 if (mPoseController != nullptr) {
447 mPoseController->setHeadSensor(mHeadSensor);
448 }
449 return Status::ok();
450}
451
452Status Spatializer::setScreenSensor(int sensorHandle) {
453 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
454 std::lock_guard lock(mLock);
455 if (sensorHandle == ASENSOR_INVALID) {
456 mScreenSensor = nullptr;
457 } else {
458 mScreenSensor = VALUE_OR_RETURN_BINDER_STATUS(getSensorFromHandle(sensorHandle));
459 }
460 if (mPoseController != nullptr) {
461 mPoseController->setScreenSensor(mScreenSensor);
462 }
463 return Status::ok();
464}
465
466Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
467 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
468 std::lock_guard lock(mLock);
469 mDisplayOrientation = physicalToLogicalAngle;
470 if (mPoseController != nullptr) {
471 mPoseController->setDisplayOrientation(mDisplayOrientation);
472 }
473 return Status::ok();
474}
475
476Status Spatializer::setHingeAngle(float hingeAngle) {
477 std::lock_guard lock(mLock);
478 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
479 if (mEngine != nullptr) {
480 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
481 }
482 return Status::ok();
483}
484
485Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
486 ALOGV("%s", __func__);
487 if (modes == nullptr) {
488 return binderStatusFromStatusT(BAD_VALUE);
489 }
490 *modes = mSpatializationModes;
491 return Status::ok();
492}
493
494// SpatializerPoseController::Listener
495void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
496 ALOGV("%s", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700497 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200498 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
499 "%s invalid head to stage vector size %zu", __func__, vec.size());
500
501 sp<AMessage> msg =
502 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
503 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
504 msg->setFloat(sHeadPoseKeys[i], vec[i]);
505 }
506 msg->post();
507}
508
509void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
510 ALOGV("%s", __func__);
511 sp<media::INativeSpatializerCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700512 {
513 std::lock_guard lock(mLock);
514 callback = mSpatializerCallback;
515 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200516 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700517 }
518 }
519
520 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200521 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700522 }
523}
524
525void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200526 ALOGV("%s(%d)", __func__, (int)mode);
527 sp<AMessage> msg =
528 new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
529 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
530 msg->post();
531}
532
533void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
534 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent2be8b292021-08-23 09:44:33 -0700535 sp<media::INativeSpatializerCallback> callback;
536 SpatializerHeadTrackingMode spatializerMode;
537 {
538 std::lock_guard lock(mLock);
539 if (!mSupportsHeadTracking) {
540 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
541 } else {
542 switch (mode) {
543 case HeadTrackingMode::STATIC:
544 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
545 break;
546 case HeadTrackingMode::WORLD_RELATIVE:
547 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
548 break;
549 case HeadTrackingMode::SCREEN_RELATIVE:
550 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
551 break;
552 default:
553 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
554 }
555 }
556 mActualHeadTrackingMode = spatializerMode;
557 callback = mSpatializerCallback;
558 }
559 if (callback != nullptr) {
560 callback->onHeadTrackingModeChanged(spatializerMode);
561 }
562}
563
564/* static */
565ConversionResult<ASensorRef> Spatializer::getSensorFromHandle(int handle) {
566 ASensorManager* sensorManager =
567 ASensorManager_getInstanceForPackage("headtracker");
568 if (!sensorManager) {
569 ALOGE("Failed to get a sensor manager");
570 return base::unexpected(NO_INIT);
571 }
572 ASensorList sensorList;
573 int numSensors = ASensorManager_getSensorList(sensorManager, &sensorList);
574 for (int i = 0; i < numSensors; ++i) {
575 if (ASensor_getHandle(sensorList[i]) == handle) {
576 return sensorList[i];
577 }
578 }
579 return base::unexpected(BAD_VALUE);
580}
581
Eric Laurent6d607012021-07-05 11:54:40 +0200582status_t Spatializer::attachOutput(audio_io_handle_t output) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700583 std::shared_ptr<SpatializerPoseController> poseController;
584 {
585 std::lock_guard lock(mLock);
586 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
587 if (mOutput != AUDIO_IO_HANDLE_NONE) {
588 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
589 // remove FX instance
590 mEngine->setEnabled(false);
591 mEngine.clear();
592 }
593 // create FX instance on output
594 AttributionSourceState attributionSource = AttributionSourceState();
595 mEngine = new AudioEffect(attributionSource);
596 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
597 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
598 false /* probe */, true /* notifyFramesProcessed */);
599 status_t status = mEngine->initCheck();
600 ALOGV("%s mEngine create status %d", __func__, (int)status);
601 if (status != NO_ERROR) {
602 return status;
603 }
604
605 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
606 std::vector<SpatializationLevel>{mLevel});
607 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
608 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
609
610 mEngine->setEnabled(true);
611 mOutput = output;
612
613 mPoseController = std::make_shared<SpatializerPoseController>(
614 static_cast<SpatializerPoseController::Listener*>(this), 10ms, 50ms);
615 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
616 "%s could not allocate pose controller", __func__);
617
618 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
619 mPoseController->setHeadSensor(mHeadSensor);
620 mPoseController->setScreenSensor(mScreenSensor);
621 mPoseController->setDisplayOrientation(mDisplayOrientation);
622 poseController = mPoseController;
Eric Laurent6d607012021-07-05 11:54:40 +0200623 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700624 poseController->waitUntilCalculated();
Eric Laurent6d607012021-07-05 11:54:40 +0200625 return NO_ERROR;
626}
627
628audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700629 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200630 ALOGV("%s mOutput %d", __func__, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700631 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent6d607012021-07-05 11:54:40 +0200632 if (mOutput == AUDIO_IO_HANDLE_NONE) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700633 return output;
Eric Laurent6d607012021-07-05 11:54:40 +0200634 }
635 // remove FX instance
636 mEngine->setEnabled(false);
637 mEngine.clear();
Eric Laurent2be8b292021-08-23 09:44:33 -0700638 output = mOutput;
Eric Laurent6d607012021-07-05 11:54:40 +0200639 mOutput = AUDIO_IO_HANDLE_NONE;
Eric Laurent2be8b292021-08-23 09:44:33 -0700640 mPoseController.reset();
Eric Laurent6d607012021-07-05 11:54:40 +0200641 return output;
642}
643
Eric Laurent2be8b292021-08-23 09:44:33 -0700644void Spatializer::calculateHeadPose() {
645 ALOGV("%s", __func__);
646 std::lock_guard lock(mLock);
647 if (mPoseController != nullptr) {
648 mPoseController->calculateAsync();
649 }
650}
Eric Laurent6d607012021-07-05 11:54:40 +0200651
Eric Laurent2be8b292021-08-23 09:44:33 -0700652void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +0200653 if (user == nullptr) {
654 return;
655 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700656 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +0200657 switch (event) {
658 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -0700659 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent6d607012021-07-05 11:54:40 +0200660 ALOGD("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200661 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -0700662 } break;
Eric Laurent6d607012021-07-05 11:54:40 +0200663 default:
664 ALOGD("%s event %d", __func__, event);
665 break;
666 }
667}
668
Eric Laurent8a4259f2021-09-14 16:04:00 +0200669void Spatializer::postFramesProcessedMsg(int frames) {
670 sp<AMessage> msg =
671 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
672 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
673 msg->post();
674}
675
Eric Laurent6d607012021-07-05 11:54:40 +0200676// ---------------------------------------------------------------------------
677
678Spatializer::EffectClient::EffectClient(const sp<media::IEffectClient>& effectClient,
679 Spatializer& parent)
680 : BnEffect(),
681 mEffectClient(effectClient), mParent(parent) {
682}
683
684Spatializer::EffectClient::~EffectClient() {
685}
686
687// IEffect
688
689#define RETURN(code) \
690 *_aidl_return = (code); \
691 return Status::ok();
692
693// Write a POD value into a vector of bytes (clears the previous buffer
694// content).
695template<typename T>
696void writeToBuffer(const T& value, std::vector<uint8_t>* buffer) {
697 buffer->clear();
698 appendToBuffer(value, buffer);
699}
700
701Status Spatializer::EffectClient::enable(int32_t* _aidl_return) {
702 RETURN(OK);
703}
704
705Status Spatializer::EffectClient::disable(int32_t* _aidl_return) {
706 RETURN(OK);
707}
708
709Status Spatializer::EffectClient::command(int32_t cmdCode,
710 const std::vector<uint8_t>& cmdData __unused,
711 int32_t maxResponseSize __unused,
712 std::vector<uint8_t>* response __unused,
713 int32_t* _aidl_return) {
714
715 // reject commands reserved for internal use by audio framework if coming from outside
716 // of audioserver
717 switch(cmdCode) {
718 case EFFECT_CMD_ENABLE:
719 case EFFECT_CMD_DISABLE:
720 case EFFECT_CMD_SET_PARAM_DEFERRED:
721 case EFFECT_CMD_SET_PARAM_COMMIT:
722 RETURN(BAD_VALUE);
723 case EFFECT_CMD_SET_PARAM:
724 case EFFECT_CMD_GET_PARAM:
725 break;
726 default:
727 if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY) {
728 break;
729 }
730 android_errorWriteLog(0x534e4554, "62019992");
731 RETURN(BAD_VALUE);
732 }
733 (void)mParent;
734 RETURN(OK);
735}
736
737Status Spatializer::EffectClient::disconnect() {
738 mDisconnected = true;
739 return Status::ok();
740}
741
742Status Spatializer::EffectClient::getCblk(media::SharedFileRegion* _aidl_return) {
743 LOG_ALWAYS_FATAL_IF(!convertIMemoryToSharedFileRegion(mCblkMemory, _aidl_return));
744 return Status::ok();
745}
746
747} // namespace android