blob: 3b466d7a16e4f73369fdc260311c4a649bd7f5a3 [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) {
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 }
Eric Laurentb4f42a92022-01-17 17:37:31 +0100230 return getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
Eric Laurent2be8b292021-08-23 09:44:33 -0700231 &mChannelMasks);
Eric Laurent2be8b292021-08-23 09:44:33 -0700232}
233
234/** Gets the channel mask, sampling rate and format set for the spatializer input. */
235audio_config_base_t Spatializer::getAudioInConfig() const {
236 std::lock_guard lock(mLock);
237 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
238 // For now use highest supported channel count
239 uint32_t maxCount = 0;
240 for ( auto mask : mChannelMasks) {
241 if (audio_channel_count_from_out_mask(mask) > maxCount) {
242 config.channel_mask = mask;
243 }
244 }
245 return config;
246}
247
Eric Laurent6d607012021-07-05 11:54:40 +0200248status_t Spatializer::registerCallback(
249 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700250 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200251 if (callback == nullptr) {
252 return BAD_VALUE;
253 }
254
255 sp<IBinder> binder = IInterface::asBinder(callback);
256 status_t status = binder->linkToDeath(this);
257 if (status == NO_ERROR) {
258 mSpatializerCallback = callback;
259 }
260 ALOGV("%s status %d", __func__, status);
261 return status;
262}
263
264// IBinder::DeathRecipient
265void Spatializer::binderDied(__unused const wp<IBinder> &who) {
266 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700267 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200268 mLevel = SpatializationLevel::NONE;
269 mSpatializerCallback.clear();
270 }
271 ALOGV("%s", __func__);
272 mPolicyCallback->onCheckSpatializer();
273}
274
275// ISpatializer
276Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
277 ALOGV("%s", __func__);
278 if (levels == nullptr) {
279 return binderStatusFromStatusT(BAD_VALUE);
280 }
Eric Laurent6d607012021-07-05 11:54:40 +0200281 levels->push_back(SpatializationLevel::NONE);
Eric Laurent2be8b292021-08-23 09:44:33 -0700282 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200283 return Status::ok();
284}
285
Eric Laurent2be8b292021-08-23 09:44:33 -0700286Status Spatializer::setLevel(SpatializationLevel level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200287 ALOGV("%s level %d", __func__, (int)level);
288 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700289 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200290 return binderStatusFromStatusT(BAD_VALUE);
291 }
292 sp<media::INativeSpatializerCallback> callback;
293 bool levelChanged = false;
294 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700295 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200296 levelChanged = mLevel != level;
297 mLevel = level;
298 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700299
300 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200301 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700302 }
Eric Laurent9249d342022-03-18 11:55:56 +0100303 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200304 }
305
306 if (levelChanged) {
307 mPolicyCallback->onCheckSpatializer();
308 if (callback != nullptr) {
309 callback->onLevelChanged(level);
310 }
311 }
312 return Status::ok();
313}
314
Eric Laurent2be8b292021-08-23 09:44:33 -0700315Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200316 if (level == nullptr) {
317 return binderStatusFromStatusT(BAD_VALUE);
318 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700319 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200320 *level = mLevel;
321 ALOGV("%s level %d", __func__, (int)*level);
322 return Status::ok();
323}
324
Eric Laurentc87402b2021-09-17 16:49:42 +0200325Status Spatializer::isHeadTrackingSupported(bool *supports) {
326 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
327 if (supports == nullptr) {
328 return binderStatusFromStatusT(BAD_VALUE);
329 }
330 std::lock_guard lock(mLock);
331 *supports = mSupportsHeadTracking;
332 return Status::ok();
333}
334
Eric Laurent6d607012021-07-05 11:54:40 +0200335Status 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) {
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700345 if (mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700346 modes->push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700347 if (mScreenSensor != SpatializerPoseController::INVALID_SENSOR) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700348 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
Eric Laurent11094172022-04-05 18:27:42 +0200376 checkPoseController_l();
377 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700378
379 return Status::ok();
380}
381
382Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200383 if (mode == nullptr) {
384 return binderStatusFromStatusT(BAD_VALUE);
385 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700386 std::lock_guard lock(mLock);
387 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200388 ALOGV("%s mode %d", __func__, (int)*mode);
389 return Status::ok();
390}
391
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700392Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200393 if (!mSupportsHeadTracking) {
394 return binderStatusFromStatusT(INVALID_OPERATION);
395 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700396 std::lock_guard lock(mLock);
397 if (mPoseController != nullptr) {
398 mPoseController->recenter();
399 }
Eric Laurent6d607012021-07-05 11:54:40 +0200400 return Status::ok();
401}
402
403Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200404 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200405 if (!mSupportsHeadTracking) {
406 return binderStatusFromStatusT(INVALID_OPERATION);
407 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700408 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
409 if (!maybePose.has_value()) {
410 ALOGW("Invalid screenToStage vector.");
411 return binderStatusFromStatusT(BAD_VALUE);
412 }
413 std::lock_guard lock(mLock);
414 if (mPoseController != nullptr) {
415 mPoseController->setScreenToStagePose(maybePose.value());
416 }
Eric Laurent6d607012021-07-05 11:54:40 +0200417 return Status::ok();
418}
419
420Status Spatializer::release() {
421 ALOGV("%s", __func__);
422 bool levelChanged = false;
423 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700424 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200425 if (mSpatializerCallback == nullptr) {
426 return binderStatusFromStatusT(INVALID_OPERATION);
427 }
428
429 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
430 binder->unlinkToDeath(this);
431 mSpatializerCallback.clear();
432
433 levelChanged = mLevel != SpatializationLevel::NONE;
434 mLevel = SpatializationLevel::NONE;
435 }
436
437 if (levelChanged) {
438 mPolicyCallback->onCheckSpatializer();
439 }
440 return Status::ok();
441}
442
Eric Laurent2be8b292021-08-23 09:44:33 -0700443Status Spatializer::setHeadSensor(int sensorHandle) {
444 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200445 if (!mSupportsHeadTracking) {
446 return binderStatusFromStatusT(INVALID_OPERATION);
447 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700448 std::lock_guard lock(mLock);
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700449 mHeadSensor = sensorHandle;
Eric Laurent11094172022-04-05 18:27:42 +0200450 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100451 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700452 return Status::ok();
453}
454
455Status Spatializer::setScreenSensor(int sensorHandle) {
456 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200457 if (!mSupportsHeadTracking) {
458 return binderStatusFromStatusT(INVALID_OPERATION);
459 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700460 std::lock_guard lock(mLock);
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700461 mScreenSensor = sensorHandle;
Eric Laurent11094172022-04-05 18:27:42 +0200462 if (mPoseController != nullptr) {
463 mPoseController->setScreenSensor(mScreenSensor);
464 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700465 return Status::ok();
466}
467
468Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
469 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200470 if (!mSupportsHeadTracking) {
471 return binderStatusFromStatusT(INVALID_OPERATION);
472 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700473 std::lock_guard lock(mLock);
474 mDisplayOrientation = physicalToLogicalAngle;
475 if (mPoseController != nullptr) {
476 mPoseController->setDisplayOrientation(mDisplayOrientation);
477 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200478 if (mEngine != nullptr) {
479 setEffectParameter_l(
480 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
481 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700482 return Status::ok();
483}
484
485Status Spatializer::setHingeAngle(float hingeAngle) {
486 std::lock_guard lock(mLock);
487 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
488 if (mEngine != nullptr) {
489 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
490 }
491 return Status::ok();
492}
493
494Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
495 ALOGV("%s", __func__);
496 if (modes == nullptr) {
497 return binderStatusFromStatusT(BAD_VALUE);
498 }
499 *modes = mSpatializationModes;
500 return Status::ok();
501}
502
Eric Laurent67816e32021-09-16 15:18:40 +0200503Status Spatializer::registerHeadTrackingCallback(
504 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
505 ALOGV("%s callback %p", __func__, callback.get());
506 std::lock_guard lock(mLock);
507 if (!mSupportsHeadTracking) {
508 return binderStatusFromStatusT(INVALID_OPERATION);
509 }
510 mHeadTrackingCallback = callback;
511 return Status::ok();
512}
513
Eric Laurentc87402b2021-09-17 16:49:42 +0200514Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
515 ALOGV("%s key %d", __func__, key);
516 std::lock_guard lock(mLock);
517 status_t status = INVALID_OPERATION;
518 if (mEngine != nullptr) {
519 status = setEffectParameter_l(key, value);
520 }
521 return binderStatusFromStatusT(status);
522}
523
524Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700525 ALOGV("%s key %d value size %d", __func__, key,
526 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200527 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700528 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200529 }
530 std::lock_guard lock(mLock);
531 status_t status = INVALID_OPERATION;
532 if (mEngine != nullptr) {
533 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
534 status = getEffectParameter_l(key, value);
535 }
536 return binderStatusFromStatusT(status);
537}
538
539Status Spatializer::getOutput(int *output) {
540 ALOGV("%s", __func__);
541 if (output == nullptr) {
542 binderStatusFromStatusT(BAD_VALUE);
543 }
544 std::lock_guard lock(mLock);
545 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
546 ALOGV("%s got output %d", __func__, *output);
547 return Status::ok();
548}
549
Eric Laurent2be8b292021-08-23 09:44:33 -0700550// SpatializerPoseController::Listener
551void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
552 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200553 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
554 "onHeadToStagePose() called with no head tracking support!");
555
Eric Laurent2be8b292021-08-23 09:44:33 -0700556 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200557 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
558 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200559 sp<AMessage> msg =
560 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
561 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
562 msg->setFloat(sHeadPoseKeys[i], vec[i]);
563 }
564 msg->post();
565}
566
567void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
568 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200569 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700570 {
571 std::lock_guard lock(mLock);
Eric Laurent15903592022-02-24 20:44:36 +0100572 if (mActualHeadTrackingMode == SpatializerHeadTrackingMode::DISABLED) {
573 return;
574 }
Eric Laurent67816e32021-09-16 15:18:40 +0200575 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700576 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200577 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700578 }
579 }
580
581 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200582 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700583 }
584}
585
586void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200587 ALOGV("%s(%d)", __func__, (int)mode);
588 sp<AMessage> msg =
589 new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
590 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
591 msg->post();
592}
593
594void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
595 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200596 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700597 SpatializerHeadTrackingMode spatializerMode;
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200598 bool modeChanged = false;
Eric Laurent2be8b292021-08-23 09:44:33 -0700599 {
600 std::lock_guard lock(mLock);
601 if (!mSupportsHeadTracking) {
602 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
603 } else {
604 switch (mode) {
605 case HeadTrackingMode::STATIC:
606 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
607 break;
608 case HeadTrackingMode::WORLD_RELATIVE:
609 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
610 break;
611 case HeadTrackingMode::SCREEN_RELATIVE:
612 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
613 break;
614 default:
615 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
616 }
617 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200618 modeChanged = mActualHeadTrackingMode != spatializerMode;
Eric Laurent2be8b292021-08-23 09:44:33 -0700619 mActualHeadTrackingMode = spatializerMode;
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200620 if (modeChanged && mEngine != nullptr) {
621 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
622 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
623 }
Eric Laurent67816e32021-09-16 15:18:40 +0200624 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700625 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200626 if (callback != nullptr && modeChanged) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700627 callback->onHeadTrackingModeChanged(spatializerMode);
628 }
629}
630
Eric Laurent15903592022-02-24 20:44:36 +0100631status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700632 std::shared_ptr<SpatializerPoseController> poseController;
Eric Laurent4a872862021-10-11 17:06:47 +0200633 bool outputChanged = false;
634 sp<media::INativeSpatializerCallback> callback;
635
Eric Laurent2be8b292021-08-23 09:44:33 -0700636 {
637 std::lock_guard lock(mLock);
638 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
639 if (mOutput != AUDIO_IO_HANDLE_NONE) {
640 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
641 // remove FX instance
642 mEngine->setEnabled(false);
643 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100644 mPoseController.reset();
Eric Laurent2be8b292021-08-23 09:44:33 -0700645 }
646 // create FX instance on output
647 AttributionSourceState attributionSource = AttributionSourceState();
648 mEngine = new AudioEffect(attributionSource);
649 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
650 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
651 false /* probe */, true /* notifyFramesProcessed */);
652 status_t status = mEngine->initCheck();
653 ALOGV("%s mEngine create status %d", __func__, (int)status);
654 if (status != NO_ERROR) {
655 return status;
656 }
657
Eric Laurent4a872862021-10-11 17:06:47 +0200658 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700659 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200660 mNumActiveTracks = numActiveTracks;
Eric Laurent2be8b292021-08-23 09:44:33 -0700661
Eric Laurent11094172022-04-05 18:27:42 +0200662 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200663 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200664 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100665 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200666 poseController = mPoseController;
667 }
Eric Laurent4a872862021-10-11 17:06:47 +0200668 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200669 }
Eric Laurent780be4a2021-09-16 10:44:24 +0200670 if (poseController != nullptr) {
Eric Laurent11094172022-04-05 18:27:42 +0200671 poseController->calculateAsync();
Eric Laurent780be4a2021-09-16 10:44:24 +0200672 poseController->waitUntilCalculated();
673 }
Eric Laurent4a872862021-10-11 17:06:47 +0200674
675 if (outputChanged && callback != nullptr) {
676 callback->onOutputChanged(output);
677 }
678
Eric Laurent6d607012021-07-05 11:54:40 +0200679 return NO_ERROR;
680}
681
682audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700683 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200684 sp<media::INativeSpatializerCallback> callback;
685
686 {
687 std::lock_guard lock(mLock);
688 ALOGV("%s mOutput %d", __func__, (int)mOutput);
689 if (mOutput == AUDIO_IO_HANDLE_NONE) {
690 return output;
691 }
692 // remove FX instance
693 mEngine->setEnabled(false);
694 mEngine.clear();
695 output = mOutput;
696 mOutput = AUDIO_IO_HANDLE_NONE;
697 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200698 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200699 }
Eric Laurent4a872862021-10-11 17:06:47 +0200700
701 if (callback != nullptr) {
702 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
703 }
Eric Laurent6d607012021-07-05 11:54:40 +0200704 return output;
705}
706
Eric Laurent15903592022-02-24 20:44:36 +0100707void Spatializer::updateActiveTracks(size_t numActiveTracks) {
708 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200709 if (mNumActiveTracks != numActiveTracks) {
710 mNumActiveTracks = numActiveTracks;
711 checkEngineState_l();
712 checkSensorsState_l();
713 }
Eric Laurent15903592022-02-24 20:44:36 +0100714}
715
Eric Laurent9249d342022-03-18 11:55:56 +0100716void Spatializer::checkSensorsState_l() {
Eric Laurent15903592022-02-24 20:44:36 +0100717 if (mSupportsHeadTracking && mPoseController != nullptr) {
Eric Laurent9249d342022-03-18 11:55:56 +0100718 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent15903592022-02-24 20:44:36 +0100719 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
720 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
721 mPoseController->setHeadSensor(mHeadSensor);
Eric Laurent9249d342022-03-18 11:55:56 +0100722 mPoseController->setScreenSensor(mScreenSensor);
Eric Laurent15903592022-02-24 20:44:36 +0100723 } else {
724 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent9249d342022-03-18 11:55:56 +0100725 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent15903592022-02-24 20:44:36 +0100726 }
727 }
728}
729
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200730void Spatializer::checkEngineState_l() {
731 if (mEngine != nullptr) {
732 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
733 mEngine->setEnabled(true);
734 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
735 std::vector<SpatializationLevel>{mLevel});
736 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
737 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
738 } else {
739 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
740 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
741 mEngine->setEnabled(false);
742 }
743 }
744}
745
Eric Laurent11094172022-04-05 18:27:42 +0200746void Spatializer::checkPoseController_l() {
747 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
748 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
749
750 if (isControllerNeeded && mPoseController == nullptr) {
751 mPoseController = std::make_shared<SpatializerPoseController>(
752 static_cast<SpatializerPoseController::Listener*>(this),
753 10ms, std::chrono::microseconds::max());
754 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
755 "%s could not allocate pose controller", __func__);
756 mPoseController->setDisplayOrientation(mDisplayOrientation);
757 } else if (!isControllerNeeded && mPoseController != nullptr) {
758 mPoseController.reset();
759 }
760 if (mPoseController != nullptr) {
761 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
762 }
763}
764
Eric Laurent2be8b292021-08-23 09:44:33 -0700765void Spatializer::calculateHeadPose() {
766 ALOGV("%s", __func__);
767 std::lock_guard lock(mLock);
768 if (mPoseController != nullptr) {
769 mPoseController->calculateAsync();
770 }
771}
Eric Laurent6d607012021-07-05 11:54:40 +0200772
Eric Laurent2be8b292021-08-23 09:44:33 -0700773void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +0200774 if (user == nullptr) {
775 return;
776 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700777 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +0200778 switch (event) {
779 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -0700780 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +0100781 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200782 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -0700783 } break;
Eric Laurent6d607012021-07-05 11:54:40 +0200784 default:
Eric Laurent9249d342022-03-18 11:55:56 +0100785 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +0200786 break;
787 }
788}
789
Eric Laurent8a4259f2021-09-14 16:04:00 +0200790void Spatializer::postFramesProcessedMsg(int frames) {
791 sp<AMessage> msg =
792 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
793 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
794 msg->post();
795}
796
Eric Laurent6d607012021-07-05 11:54:40 +0200797} // namespace android