blob: 9baaf9372e4627fc6c6334db9d44eb0c8cccbd63 [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>
28#include <audio_utils/fixedfft.h>
29#include <cutils/bitops.h>
Eric Laurent2be8b292021-08-23 09:44:33 -070030#include <hardware/sensors.h>
Eric Laurent6d607012021-07-05 11:54:40 +020031#include <media/audiohal/EffectsFactoryHalInterface.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020032#include <media/stagefright/foundation/AHandler.h>
33#include <media/stagefright/foundation/AMessage.h>
34#include <media/ShmemCompat.h>
Eric Laurent6d607012021-07-05 11:54:40 +020035#include <mediautils/ServiceUtilities.h>
36#include <utils/Thread.h>
37
38#include "Spatializer.h"
39
40namespace android {
41
42using aidl_utils::statusTFromBinderStatus;
43using aidl_utils::binderStatusFromStatusT;
44using android::content::AttributionSourceState;
45using binder::Status;
Eric Laurent2be8b292021-08-23 09:44:33 -070046using media::HeadTrackingMode;
47using media::Pose3f;
Eric Laurent6d607012021-07-05 11:54:40 +020048using media::SpatializationLevel;
Eric Laurent2be8b292021-08-23 09:44:33 -070049using media::SpatializationMode;
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070050using media::SpatializerHeadTrackingMode;
Eric Laurent2be8b292021-08-23 09:44:33 -070051using media::SensorPoseProvider;
52
Eric Laurent2be8b292021-08-23 09:44:33 -070053using namespace std::chrono_literals;
Eric Laurent6d607012021-07-05 11:54:40 +020054
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
Eric Laurent6d607012021-07-05 11:54:40 +020060// ---------------------------------------------------------------------------
61
Eric Laurent8a4259f2021-09-14 16:04:00 +020062class Spatializer::EngineCallbackHandler : public AHandler {
63public:
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
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 }
132private:
133 wp<Spatializer> mSpatializer;
134};
135
136const 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// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200146sp<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 =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200157 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200158 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);
Eric Laurent2be8b292021-08-23 09:44:33 -0700174 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
175 spatializer.clear();
176 }
Eric Laurent6d607012021-07-05 11:54:40 +0200177 }
178
179 return spatializer;
180}
181
Eric Laurent2be8b292021-08-23 09:44:33 -0700182Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
183 : mEngineDescriptor(engineDescriptor),
184 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200185 ALOGV("%s", __func__);
186}
187
Eric Laurent8a4259f2021-09-14 16:04:00 +0200188void 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
Eric Laurent6d607012021-07-05 11:54:40 +0200200Spatializer::~Spatializer() {
201 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200202 if (mLooper != nullptr) {
203 mLooper->stop();
204 mLooper->unregisterHandler(mHandler->id());
205 }
206 mLooper.clear();
207 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200208}
209
Eric Laurent2be8b292021-08-23 09:44:33 -0700210status_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) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700217 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700218 return status;
219 }
220 mSupportsHeadTracking = supportsHeadTracking[0];
221
Andy Hung119dbdb2022-05-11 19:20:13 -0700222 std::vector<media::SpatializationLevel> spatializationLevels;
223 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
224 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700225 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700226 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700227 return status;
228 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700229 bool noneLevelFound = false;
230 bool activeLevelFound = false;
231 for (const auto spatializationLevel : spatializationLevels) {
232 if (!aidl_utils::isValidEnum(spatializationLevel)) {
233 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
234 continue;
235 }
236 if (spatializationLevel == media::SpatializationLevel::NONE) {
237 noneLevelFound = true;
238 } else {
239 activeLevelFound = true;
240 }
241 // we don't detect duplicates.
242 mLevels.emplace_back(spatializationLevel);
243 }
244 if (!noneLevelFound || !activeLevelFound) {
245 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
246 " and another valid level", __func__);
247 return BAD_VALUE;
248 }
249
250 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700251 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700252 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700253 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700254 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700255 return status;
256 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700257 for (const auto spatializationMode : spatializationModes) {
258 if (!aidl_utils::isValidEnum(spatializationMode)) {
259 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
260 continue;
261 }
262 // we don't detect duplicates.
263 mSpatializationModes.emplace_back(spatializationMode);
264 }
265 if (mSpatializationModes.empty()) {
266 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
267 return BAD_VALUE;
268 }
269
270 std::vector<audio_channel_mask_t> channelMasks;
271 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
272 &channelMasks);
273 if (status != NO_ERROR) {
274 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
275 return status;
276 }
277 for (const auto channelMask : channelMasks) {
278 if (!audio_is_channel_mask_spatialized(channelMask)) {
279 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
280 continue;
281 }
282 // we don't detect duplicates.
283 mChannelMasks.emplace_back(channelMask);
284 }
285 if (mChannelMasks.empty()) {
286 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
287 return BAD_VALUE;
288 }
289 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700290}
291
292/** Gets the channel mask, sampling rate and format set for the spatializer input. */
293audio_config_base_t Spatializer::getAudioInConfig() const {
294 std::lock_guard lock(mLock);
295 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
296 // For now use highest supported channel count
297 uint32_t maxCount = 0;
298 for ( auto mask : mChannelMasks) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700299 const size_t count = audio_channel_count_from_out_mask(mask);
300 if (count > maxCount) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700301 config.channel_mask = mask;
Andy Hung119dbdb2022-05-11 19:20:13 -0700302 maxCount = count;
Eric Laurent2be8b292021-08-23 09:44:33 -0700303 }
304 }
305 return config;
306}
307
Eric Laurent6d607012021-07-05 11:54:40 +0200308status_t Spatializer::registerCallback(
309 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700310 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200311 if (callback == nullptr) {
312 return BAD_VALUE;
313 }
314
315 sp<IBinder> binder = IInterface::asBinder(callback);
316 status_t status = binder->linkToDeath(this);
317 if (status == NO_ERROR) {
318 mSpatializerCallback = callback;
319 }
320 ALOGV("%s status %d", __func__, status);
321 return status;
322}
323
324// IBinder::DeathRecipient
325void Spatializer::binderDied(__unused const wp<IBinder> &who) {
326 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700327 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200328 mLevel = SpatializationLevel::NONE;
329 mSpatializerCallback.clear();
330 }
331 ALOGV("%s", __func__);
332 mPolicyCallback->onCheckSpatializer();
333}
334
335// ISpatializer
336Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
337 ALOGV("%s", __func__);
338 if (levels == nullptr) {
339 return binderStatusFromStatusT(BAD_VALUE);
340 }
Eric Laurent6d607012021-07-05 11:54:40 +0200341 levels->push_back(SpatializationLevel::NONE);
Eric Laurent2be8b292021-08-23 09:44:33 -0700342 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200343 return Status::ok();
344}
345
Eric Laurent2be8b292021-08-23 09:44:33 -0700346Status Spatializer::setLevel(SpatializationLevel level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200347 ALOGV("%s level %d", __func__, (int)level);
348 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700349 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200350 return binderStatusFromStatusT(BAD_VALUE);
351 }
352 sp<media::INativeSpatializerCallback> callback;
353 bool levelChanged = false;
354 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700355 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200356 levelChanged = mLevel != level;
357 mLevel = level;
358 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700359
360 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200361 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700362 }
Eric Laurent9249d342022-03-18 11:55:56 +0100363 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200364 }
365
366 if (levelChanged) {
367 mPolicyCallback->onCheckSpatializer();
368 if (callback != nullptr) {
369 callback->onLevelChanged(level);
370 }
371 }
372 return Status::ok();
373}
374
Eric Laurent2be8b292021-08-23 09:44:33 -0700375Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200376 if (level == nullptr) {
377 return binderStatusFromStatusT(BAD_VALUE);
378 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700379 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200380 *level = mLevel;
381 ALOGV("%s level %d", __func__, (int)*level);
382 return Status::ok();
383}
384
Eric Laurentc87402b2021-09-17 16:49:42 +0200385Status Spatializer::isHeadTrackingSupported(bool *supports) {
386 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
387 if (supports == nullptr) {
388 return binderStatusFromStatusT(BAD_VALUE);
389 }
390 std::lock_guard lock(mLock);
391 *supports = mSupportsHeadTracking;
392 return Status::ok();
393}
394
Eric Laurent6d607012021-07-05 11:54:40 +0200395Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700396 std::vector<SpatializerHeadTrackingMode>* modes) {
397 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200398 ALOGV("%s", __func__);
399 if (modes == nullptr) {
400 return binderStatusFromStatusT(BAD_VALUE);
401 }
Eric Laurent6d607012021-07-05 11:54:40 +0200402
Eric Laurent2be8b292021-08-23 09:44:33 -0700403 modes->push_back(SpatializerHeadTrackingMode::DISABLED);
404 if (mSupportsHeadTracking) {
Eric Laurent3815d852022-05-05 10:37:30 +0200405 modes->push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
Eric Laurent6d607012021-07-05 11:54:40 +0200406 }
407 return Status::ok();
408}
409
Eric Laurent2be8b292021-08-23 09:44:33 -0700410Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
411 ALOGV("%s mode %d", __func__, (int)mode);
412
413 if (!mSupportsHeadTracking) {
414 return binderStatusFromStatusT(INVALID_OPERATION);
415 }
416 std::lock_guard lock(mLock);
417 switch (mode) {
418 case SpatializerHeadTrackingMode::OTHER:
419 return binderStatusFromStatusT(BAD_VALUE);
420 case SpatializerHeadTrackingMode::DISABLED:
421 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
422 break;
423 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
424 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
425 break;
426 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
427 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
428 break;
429 }
430
Eric Laurent11094172022-04-05 18:27:42 +0200431 checkPoseController_l();
432 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700433
434 return Status::ok();
435}
436
437Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200438 if (mode == nullptr) {
439 return binderStatusFromStatusT(BAD_VALUE);
440 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700441 std::lock_guard lock(mLock);
442 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200443 ALOGV("%s mode %d", __func__, (int)*mode);
444 return Status::ok();
445}
446
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700447Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200448 if (!mSupportsHeadTracking) {
449 return binderStatusFromStatusT(INVALID_OPERATION);
450 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700451 std::lock_guard lock(mLock);
452 if (mPoseController != nullptr) {
453 mPoseController->recenter();
454 }
Eric Laurent6d607012021-07-05 11:54:40 +0200455 return Status::ok();
456}
457
458Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200459 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200460 if (!mSupportsHeadTracking) {
461 return binderStatusFromStatusT(INVALID_OPERATION);
462 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700463 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
464 if (!maybePose.has_value()) {
465 ALOGW("Invalid screenToStage vector.");
466 return binderStatusFromStatusT(BAD_VALUE);
467 }
468 std::lock_guard lock(mLock);
469 if (mPoseController != nullptr) {
470 mPoseController->setScreenToStagePose(maybePose.value());
471 }
Eric Laurent6d607012021-07-05 11:54:40 +0200472 return Status::ok();
473}
474
475Status Spatializer::release() {
476 ALOGV("%s", __func__);
477 bool levelChanged = false;
478 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700479 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200480 if (mSpatializerCallback == nullptr) {
481 return binderStatusFromStatusT(INVALID_OPERATION);
482 }
483
484 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
485 binder->unlinkToDeath(this);
486 mSpatializerCallback.clear();
487
488 levelChanged = mLevel != SpatializationLevel::NONE;
489 mLevel = SpatializationLevel::NONE;
490 }
491
492 if (levelChanged) {
493 mPolicyCallback->onCheckSpatializer();
494 }
495 return Status::ok();
496}
497
Eric Laurent2be8b292021-08-23 09:44:33 -0700498Status Spatializer::setHeadSensor(int sensorHandle) {
499 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200500 if (!mSupportsHeadTracking) {
501 return binderStatusFromStatusT(INVALID_OPERATION);
502 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700503 std::lock_guard lock(mLock);
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700504 mHeadSensor = sensorHandle;
Eric Laurent11094172022-04-05 18:27:42 +0200505 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100506 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700507 return Status::ok();
508}
509
510Status Spatializer::setScreenSensor(int sensorHandle) {
511 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200512 if (!mSupportsHeadTracking) {
513 return binderStatusFromStatusT(INVALID_OPERATION);
514 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700515 std::lock_guard lock(mLock);
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700516 mScreenSensor = sensorHandle;
Eric Laurente51f80e2022-04-14 10:20:38 +0200517 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700518 return Status::ok();
519}
520
521Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
522 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200523 if (!mSupportsHeadTracking) {
524 return binderStatusFromStatusT(INVALID_OPERATION);
525 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700526 std::lock_guard lock(mLock);
527 mDisplayOrientation = physicalToLogicalAngle;
528 if (mPoseController != nullptr) {
529 mPoseController->setDisplayOrientation(mDisplayOrientation);
530 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200531 if (mEngine != nullptr) {
532 setEffectParameter_l(
533 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
534 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700535 return Status::ok();
536}
537
538Status Spatializer::setHingeAngle(float hingeAngle) {
539 std::lock_guard lock(mLock);
540 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
541 if (mEngine != nullptr) {
542 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
543 }
544 return Status::ok();
545}
546
547Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
548 ALOGV("%s", __func__);
549 if (modes == nullptr) {
550 return binderStatusFromStatusT(BAD_VALUE);
551 }
552 *modes = mSpatializationModes;
553 return Status::ok();
554}
555
Eric Laurent67816e32021-09-16 15:18:40 +0200556Status Spatializer::registerHeadTrackingCallback(
557 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
558 ALOGV("%s callback %p", __func__, callback.get());
559 std::lock_guard lock(mLock);
560 if (!mSupportsHeadTracking) {
561 return binderStatusFromStatusT(INVALID_OPERATION);
562 }
563 mHeadTrackingCallback = callback;
564 return Status::ok();
565}
566
Eric Laurentc87402b2021-09-17 16:49:42 +0200567Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
568 ALOGV("%s key %d", __func__, key);
569 std::lock_guard lock(mLock);
570 status_t status = INVALID_OPERATION;
571 if (mEngine != nullptr) {
572 status = setEffectParameter_l(key, value);
573 }
574 return binderStatusFromStatusT(status);
575}
576
577Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700578 ALOGV("%s key %d value size %d", __func__, key,
579 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200580 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700581 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200582 }
583 std::lock_guard lock(mLock);
584 status_t status = INVALID_OPERATION;
585 if (mEngine != nullptr) {
586 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
587 status = getEffectParameter_l(key, value);
588 }
589 return binderStatusFromStatusT(status);
590}
591
592Status Spatializer::getOutput(int *output) {
593 ALOGV("%s", __func__);
594 if (output == nullptr) {
595 binderStatusFromStatusT(BAD_VALUE);
596 }
597 std::lock_guard lock(mLock);
598 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
599 ALOGV("%s got output %d", __func__, *output);
600 return Status::ok();
601}
602
Eric Laurent2be8b292021-08-23 09:44:33 -0700603// SpatializerPoseController::Listener
604void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
605 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200606 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
607 "onHeadToStagePose() called with no head tracking support!");
608
Eric Laurent2be8b292021-08-23 09:44:33 -0700609 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200610 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
611 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200612 sp<AMessage> msg =
613 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
614 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
615 msg->setFloat(sHeadPoseKeys[i], vec[i]);
616 }
617 msg->post();
618}
619
620void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
621 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200622 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700623 {
624 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200625 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700626 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200627 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700628 }
629 }
630
631 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200632 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700633 }
634}
635
636void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200637 ALOGV("%s(%d)", __func__, (int)mode);
638 sp<AMessage> msg =
639 new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
640 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
641 msg->post();
642}
643
644void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
645 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200646 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700647 SpatializerHeadTrackingMode spatializerMode;
648 {
649 std::lock_guard lock(mLock);
650 if (!mSupportsHeadTracking) {
651 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
652 } else {
653 switch (mode) {
654 case HeadTrackingMode::STATIC:
655 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
656 break;
657 case HeadTrackingMode::WORLD_RELATIVE:
658 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
659 break;
660 case HeadTrackingMode::SCREEN_RELATIVE:
661 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
662 break;
663 default:
664 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
665 }
666 }
667 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200668 if (mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200669 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
670 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
671 }
Eric Laurent67816e32021-09-16 15:18:40 +0200672 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700673 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200674 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700675 callback->onHeadTrackingModeChanged(spatializerMode);
676 }
677}
678
Eric Laurent15903592022-02-24 20:44:36 +0100679status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200680 bool outputChanged = false;
681 sp<media::INativeSpatializerCallback> callback;
682
Eric Laurent2be8b292021-08-23 09:44:33 -0700683 {
684 std::lock_guard lock(mLock);
685 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
686 if (mOutput != AUDIO_IO_HANDLE_NONE) {
687 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
688 // remove FX instance
689 mEngine->setEnabled(false);
690 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100691 mPoseController.reset();
Eric Laurent2be8b292021-08-23 09:44:33 -0700692 }
693 // create FX instance on output
694 AttributionSourceState attributionSource = AttributionSourceState();
695 mEngine = new AudioEffect(attributionSource);
696 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
697 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
698 false /* probe */, true /* notifyFramesProcessed */);
699 status_t status = mEngine->initCheck();
700 ALOGV("%s mEngine create status %d", __func__, (int)status);
701 if (status != NO_ERROR) {
702 return status;
703 }
704
Eric Laurent4a872862021-10-11 17:06:47 +0200705 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700706 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200707 mNumActiveTracks = numActiveTracks;
Eric Laurent2be8b292021-08-23 09:44:33 -0700708
Eric Laurent11094172022-04-05 18:27:42 +0200709 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200710 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200711 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100712 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200713 }
Eric Laurent4a872862021-10-11 17:06:47 +0200714 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200715 }
Eric Laurent4a872862021-10-11 17:06:47 +0200716
717 if (outputChanged && callback != nullptr) {
718 callback->onOutputChanged(output);
719 }
720
Eric Laurent6d607012021-07-05 11:54:40 +0200721 return NO_ERROR;
722}
723
724audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700725 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200726 sp<media::INativeSpatializerCallback> callback;
727
728 {
729 std::lock_guard lock(mLock);
730 ALOGV("%s mOutput %d", __func__, (int)mOutput);
731 if (mOutput == AUDIO_IO_HANDLE_NONE) {
732 return output;
733 }
734 // remove FX instance
735 mEngine->setEnabled(false);
736 mEngine.clear();
737 output = mOutput;
738 mOutput = AUDIO_IO_HANDLE_NONE;
739 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200740 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200741 }
Eric Laurent4a872862021-10-11 17:06:47 +0200742
743 if (callback != nullptr) {
744 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
745 }
Eric Laurent6d607012021-07-05 11:54:40 +0200746 return output;
747}
748
Eric Laurent15903592022-02-24 20:44:36 +0100749void Spatializer::updateActiveTracks(size_t numActiveTracks) {
750 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200751 if (mNumActiveTracks != numActiveTracks) {
752 mNumActiveTracks = numActiveTracks;
753 checkEngineState_l();
754 checkSensorsState_l();
755 }
Eric Laurent15903592022-02-24 20:44:36 +0100756}
757
Eric Laurent9249d342022-03-18 11:55:56 +0100758void Spatializer::checkSensorsState_l() {
Eric Laurent15903592022-02-24 20:44:36 +0100759 if (mSupportsHeadTracking && mPoseController != nullptr) {
Eric Laurent9249d342022-03-18 11:55:56 +0100760 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent15903592022-02-24 20:44:36 +0100761 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
762 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
763 mPoseController->setHeadSensor(mHeadSensor);
Eric Laurent9249d342022-03-18 11:55:56 +0100764 mPoseController->setScreenSensor(mScreenSensor);
Eric Laurent15903592022-02-24 20:44:36 +0100765 } else {
766 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent9249d342022-03-18 11:55:56 +0100767 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent15903592022-02-24 20:44:36 +0100768 }
769 }
770}
771
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200772void Spatializer::checkEngineState_l() {
773 if (mEngine != nullptr) {
774 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
775 mEngine->setEnabled(true);
776 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
777 std::vector<SpatializationLevel>{mLevel});
778 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
779 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
780 } else {
781 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
782 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
783 mEngine->setEnabled(false);
784 }
785 }
786}
787
Eric Laurent11094172022-04-05 18:27:42 +0200788void Spatializer::checkPoseController_l() {
789 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
790 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
791
792 if (isControllerNeeded && mPoseController == nullptr) {
793 mPoseController = std::make_shared<SpatializerPoseController>(
794 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +0200795 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +0200796 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
797 "%s could not allocate pose controller", __func__);
798 mPoseController->setDisplayOrientation(mDisplayOrientation);
799 } else if (!isControllerNeeded && mPoseController != nullptr) {
800 mPoseController.reset();
801 }
802 if (mPoseController != nullptr) {
803 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
804 }
805}
806
Eric Laurent2be8b292021-08-23 09:44:33 -0700807void Spatializer::calculateHeadPose() {
808 ALOGV("%s", __func__);
809 std::lock_guard lock(mLock);
810 if (mPoseController != nullptr) {
811 mPoseController->calculateAsync();
812 }
813}
Eric Laurent6d607012021-07-05 11:54:40 +0200814
Eric Laurent2be8b292021-08-23 09:44:33 -0700815void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +0200816 if (user == nullptr) {
817 return;
818 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700819 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +0200820 switch (event) {
821 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -0700822 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +0100823 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200824 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -0700825 } break;
Eric Laurent6d607012021-07-05 11:54:40 +0200826 default:
Eric Laurent9249d342022-03-18 11:55:56 +0100827 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +0200828 break;
829 }
830}
831
Eric Laurent8a4259f2021-09-14 16:04:00 +0200832void Spatializer::postFramesProcessedMsg(int frames) {
833 sp<AMessage> msg =
834 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
835 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
836 msg->post();
837}
838
Eric Laurent6d607012021-07-05 11:54:40 +0200839} // namespace android