blob: e8b599a47fc593297322bfc3604edffb6250f8ec [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>
Andy Hunga461a002022-05-17 10:36:02 -070034#include <media/MediaMetricsItem.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020035#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
Andy Hunga461a002022-05-17 10:36:02 -070061audio_channel_mask_t getMaxChannelMask(std::vector<audio_channel_mask_t> masks) {
62 uint32_t maxCount = 0;
63 audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
64 for (auto mask : masks) {
65 const size_t count = audio_channel_count_from_out_mask(mask);
66 if (count > maxCount) {
67 maxMask = mask;
68 maxCount = count;
69 }
70 }
71 return maxMask;
72}
73
Eric Laurent6d607012021-07-05 11:54:40 +020074// ---------------------------------------------------------------------------
75
Eric Laurent8a4259f2021-09-14 16:04:00 +020076class Spatializer::EngineCallbackHandler : public AHandler {
77public:
78 EngineCallbackHandler(wp<Spatializer> spatializer)
79 : mSpatializer(spatializer) {
80 }
81
82 enum {
83 // Device state callbacks
84 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
85 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
86 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
87 };
88 static constexpr const char *kNumFramesKey = "numFrames";
89 static constexpr const char *kModeKey = "mode";
90 static constexpr const char *kTranslation0Key = "translation0";
91 static constexpr const char *kTranslation1Key = "translation1";
92 static constexpr const char *kTranslation2Key = "translation2";
93 static constexpr const char *kRotation0Key = "rotation0";
94 static constexpr const char *kRotation1Key = "rotation1";
95 static constexpr const char *kRotation2Key = "rotation2";
96
97 void onMessageReceived(const sp<AMessage> &msg) override {
98 switch (msg->what()) {
99 case kWhatOnFramesProcessed: {
100 sp<Spatializer> spatializer = mSpatializer.promote();
101 if (spatializer == nullptr) {
102 ALOGW("%s: Cannot promote spatializer", __func__);
103 return;
104 }
105 int numFrames;
106 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
107 ALOGE("%s: Cannot find num frames!", __func__);
108 return;
109 }
110 if (numFrames > 0) {
111 spatializer->calculateHeadPose();
112 }
113 } break;
114 case kWhatOnHeadToStagePose: {
115 sp<Spatializer> spatializer = mSpatializer.promote();
116 if (spatializer == nullptr) {
117 ALOGW("%s: Cannot promote spatializer", __func__);
118 return;
119 }
120 std::vector<float> headToStage(sHeadPoseKeys.size());
121 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
122 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
123 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
124 return;
125 }
126 }
127 spatializer->onHeadToStagePoseMsg(headToStage);
128 } break;
129 case kWhatOnActualModeChange: {
130 sp<Spatializer> spatializer = mSpatializer.promote();
131 if (spatializer == nullptr) {
132 ALOGW("%s: Cannot promote spatializer", __func__);
133 return;
134 }
135 int mode;
136 if (!msg->findInt32(EngineCallbackHandler::kModeKey, &mode)) {
137 ALOGE("%s: Cannot find actualMode!", __func__);
138 return;
139 }
140 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
141 } break;
142 default:
143 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
144 }
145 }
146private:
147 wp<Spatializer> mSpatializer;
148};
149
150const std::vector<const char *> Spatializer::sHeadPoseKeys = {
151 Spatializer::EngineCallbackHandler::kTranslation0Key,
152 Spatializer::EngineCallbackHandler::kTranslation1Key,
153 Spatializer::EngineCallbackHandler::kTranslation2Key,
154 Spatializer::EngineCallbackHandler::kRotation0Key,
155 Spatializer::EngineCallbackHandler::kRotation1Key,
156 Spatializer::EngineCallbackHandler::kRotation2Key,
157};
158
159// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200160sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
161 sp<Spatializer> spatializer;
162
163 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
164 if (effectsFactoryHal == nullptr) {
165 ALOGW("%s failed to create effect factory interface", __func__);
166 return spatializer;
167 }
168
169 std::vector<effect_descriptor_t> descriptors;
170 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200171 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200172 if (status != NO_ERROR) {
173 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
174 return spatializer;
175 }
176 ALOG_ASSERT(!descriptors.empty(),
177 "%s getDescriptors() returned no error but empty list", __func__);
178
179 //TODO: get supported spatialization modes from FX engine or descriptor
180
181 sp<EffectHalInterface> effect;
182 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
183 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
184 ALOGI("%s FX create status %d effect %p", __func__, status, effect.get());
185
186 if (status == NO_ERROR && effect != nullptr) {
187 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700188 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
189 spatializer.clear();
190 }
Eric Laurent6d607012021-07-05 11:54:40 +0200191 }
192
193 return spatializer;
194}
195
Eric Laurent2be8b292021-08-23 09:44:33 -0700196Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
197 : mEngineDescriptor(engineDescriptor),
198 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200199 ALOGV("%s", __func__);
200}
201
Eric Laurent8a4259f2021-09-14 16:04:00 +0200202void Spatializer::onFirstRef() {
203 mLooper = new ALooper;
204 mLooper->setName("Spatializer-looper");
205 mLooper->start(
206 /*runOnCallingThread*/false,
207 /*canCallJava*/ false,
208 PRIORITY_AUDIO);
209
210 mHandler = new EngineCallbackHandler(this);
211 mLooper->registerHandler(mHandler);
212}
213
Eric Laurent6d607012021-07-05 11:54:40 +0200214Spatializer::~Spatializer() {
215 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200216 if (mLooper != nullptr) {
217 mLooper->stop();
218 mLooper->unregisterHandler(mHandler->id());
219 }
220 mLooper.clear();
221 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200222}
223
Eric Laurent2be8b292021-08-23 09:44:33 -0700224status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
225 ALOGV("%s", __func__);
226
227 std::vector<bool> supportsHeadTracking;
228 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
229 &supportsHeadTracking);
230 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700231 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700232 return status;
233 }
234 mSupportsHeadTracking = supportsHeadTracking[0];
235
Andy Hung119dbdb2022-05-11 19:20:13 -0700236 std::vector<media::SpatializationLevel> spatializationLevels;
237 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
238 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700239 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700240 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700241 return status;
242 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700243 bool noneLevelFound = false;
244 bool activeLevelFound = false;
245 for (const auto spatializationLevel : spatializationLevels) {
246 if (!aidl_utils::isValidEnum(spatializationLevel)) {
247 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
248 continue;
249 }
250 if (spatializationLevel == media::SpatializationLevel::NONE) {
251 noneLevelFound = true;
252 } else {
253 activeLevelFound = true;
254 }
255 // we don't detect duplicates.
256 mLevels.emplace_back(spatializationLevel);
257 }
258 if (!noneLevelFound || !activeLevelFound) {
259 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
260 " and another valid level", __func__);
261 return BAD_VALUE;
262 }
263
264 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700265 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700266 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700267 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700268 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700269 return status;
270 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700271 for (const auto spatializationMode : spatializationModes) {
272 if (!aidl_utils::isValidEnum(spatializationMode)) {
273 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
274 continue;
275 }
276 // we don't detect duplicates.
277 mSpatializationModes.emplace_back(spatializationMode);
278 }
279 if (mSpatializationModes.empty()) {
280 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
281 return BAD_VALUE;
282 }
283
284 std::vector<audio_channel_mask_t> channelMasks;
285 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
286 &channelMasks);
287 if (status != NO_ERROR) {
288 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
289 return status;
290 }
291 for (const auto channelMask : channelMasks) {
292 if (!audio_is_channel_mask_spatialized(channelMask)) {
293 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
294 continue;
295 }
296 // we don't detect duplicates.
297 mChannelMasks.emplace_back(channelMask);
298 }
299 if (mChannelMasks.empty()) {
300 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
301 return BAD_VALUE;
302 }
Andy Hunga461a002022-05-17 10:36:02 -0700303
304 // Currently we expose only RELATIVE_WORLD.
305 // This is a limitation of the head tracking library based on a UX choice.
306 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
307 if (mSupportsHeadTracking) {
308 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
309 }
310 mediametrics::LogItem(mMetricsId)
311 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
312 .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)getMaxChannelMask(mChannelMasks))
313 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
314 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
315 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
316 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
317 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700318 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700319}
320
321/** Gets the channel mask, sampling rate and format set for the spatializer input. */
322audio_config_base_t Spatializer::getAudioInConfig() const {
323 std::lock_guard lock(mLock);
324 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
325 // For now use highest supported channel count
Andy Hunga461a002022-05-17 10:36:02 -0700326 config.channel_mask = getMaxChannelMask(mChannelMasks);
Eric Laurent2be8b292021-08-23 09:44:33 -0700327 return config;
328}
329
Eric Laurent6d607012021-07-05 11:54:40 +0200330status_t Spatializer::registerCallback(
331 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700332 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200333 if (callback == nullptr) {
334 return BAD_VALUE;
335 }
336
337 sp<IBinder> binder = IInterface::asBinder(callback);
338 status_t status = binder->linkToDeath(this);
339 if (status == NO_ERROR) {
340 mSpatializerCallback = callback;
341 }
342 ALOGV("%s status %d", __func__, status);
343 return status;
344}
345
346// IBinder::DeathRecipient
347void Spatializer::binderDied(__unused const wp<IBinder> &who) {
348 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700349 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200350 mLevel = SpatializationLevel::NONE;
351 mSpatializerCallback.clear();
352 }
353 ALOGV("%s", __func__);
354 mPolicyCallback->onCheckSpatializer();
355}
356
357// ISpatializer
358Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
359 ALOGV("%s", __func__);
360 if (levels == nullptr) {
361 return binderStatusFromStatusT(BAD_VALUE);
362 }
Andy Hunga461a002022-05-17 10:36:02 -0700363 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700364 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200365 return Status::ok();
366}
367
Eric Laurent2be8b292021-08-23 09:44:33 -0700368Status Spatializer::setLevel(SpatializationLevel level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200369 ALOGV("%s level %d", __func__, (int)level);
370 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700371 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200372 return binderStatusFromStatusT(BAD_VALUE);
373 }
374 sp<media::INativeSpatializerCallback> callback;
375 bool levelChanged = false;
376 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700377 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200378 levelChanged = mLevel != level;
379 mLevel = level;
380 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700381
382 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200383 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700384 }
Eric Laurent9249d342022-03-18 11:55:56 +0100385 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200386 }
387
388 if (levelChanged) {
389 mPolicyCallback->onCheckSpatializer();
390 if (callback != nullptr) {
391 callback->onLevelChanged(level);
392 }
393 }
394 return Status::ok();
395}
396
Eric Laurent2be8b292021-08-23 09:44:33 -0700397Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200398 if (level == nullptr) {
399 return binderStatusFromStatusT(BAD_VALUE);
400 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700401 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200402 *level = mLevel;
403 ALOGV("%s level %d", __func__, (int)*level);
404 return Status::ok();
405}
406
Eric Laurentc87402b2021-09-17 16:49:42 +0200407Status Spatializer::isHeadTrackingSupported(bool *supports) {
408 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
409 if (supports == nullptr) {
410 return binderStatusFromStatusT(BAD_VALUE);
411 }
412 std::lock_guard lock(mLock);
413 *supports = mSupportsHeadTracking;
414 return Status::ok();
415}
416
Eric Laurent6d607012021-07-05 11:54:40 +0200417Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700418 std::vector<SpatializerHeadTrackingMode>* modes) {
419 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200420 ALOGV("%s", __func__);
421 if (modes == nullptr) {
422 return binderStatusFromStatusT(BAD_VALUE);
423 }
Andy Hunga461a002022-05-17 10:36:02 -0700424 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200425 return Status::ok();
426}
427
Eric Laurent2be8b292021-08-23 09:44:33 -0700428Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
429 ALOGV("%s mode %d", __func__, (int)mode);
430
431 if (!mSupportsHeadTracking) {
432 return binderStatusFromStatusT(INVALID_OPERATION);
433 }
434 std::lock_guard lock(mLock);
435 switch (mode) {
436 case SpatializerHeadTrackingMode::OTHER:
437 return binderStatusFromStatusT(BAD_VALUE);
438 case SpatializerHeadTrackingMode::DISABLED:
439 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
440 break;
441 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
442 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
443 break;
444 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
445 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
446 break;
447 }
448
Eric Laurent11094172022-04-05 18:27:42 +0200449 checkPoseController_l();
450 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700451
452 return Status::ok();
453}
454
455Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200456 if (mode == nullptr) {
457 return binderStatusFromStatusT(BAD_VALUE);
458 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700459 std::lock_guard lock(mLock);
460 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200461 ALOGV("%s mode %d", __func__, (int)*mode);
462 return Status::ok();
463}
464
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700465Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200466 if (!mSupportsHeadTracking) {
467 return binderStatusFromStatusT(INVALID_OPERATION);
468 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700469 std::lock_guard lock(mLock);
470 if (mPoseController != nullptr) {
471 mPoseController->recenter();
472 }
Eric Laurent6d607012021-07-05 11:54:40 +0200473 return Status::ok();
474}
475
476Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200477 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200478 if (!mSupportsHeadTracking) {
479 return binderStatusFromStatusT(INVALID_OPERATION);
480 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700481 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
482 if (!maybePose.has_value()) {
483 ALOGW("Invalid screenToStage vector.");
484 return binderStatusFromStatusT(BAD_VALUE);
485 }
486 std::lock_guard lock(mLock);
487 if (mPoseController != nullptr) {
488 mPoseController->setScreenToStagePose(maybePose.value());
489 }
Eric Laurent6d607012021-07-05 11:54:40 +0200490 return Status::ok();
491}
492
493Status Spatializer::release() {
494 ALOGV("%s", __func__);
495 bool levelChanged = false;
496 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700497 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200498 if (mSpatializerCallback == nullptr) {
499 return binderStatusFromStatusT(INVALID_OPERATION);
500 }
501
502 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
503 binder->unlinkToDeath(this);
504 mSpatializerCallback.clear();
505
506 levelChanged = mLevel != SpatializationLevel::NONE;
507 mLevel = SpatializationLevel::NONE;
508 }
509
510 if (levelChanged) {
511 mPolicyCallback->onCheckSpatializer();
512 }
513 return Status::ok();
514}
515
Eric Laurent2be8b292021-08-23 09:44:33 -0700516Status Spatializer::setHeadSensor(int sensorHandle) {
517 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200518 if (!mSupportsHeadTracking) {
519 return binderStatusFromStatusT(INVALID_OPERATION);
520 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700521 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700522 if (mHeadSensor != sensorHandle) {
523 mHeadSensor = sensorHandle;
524 checkPoseController_l();
525 checkSensorsState_l();
526 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700527 return Status::ok();
528}
529
530Status Spatializer::setScreenSensor(int sensorHandle) {
531 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200532 if (!mSupportsHeadTracking) {
533 return binderStatusFromStatusT(INVALID_OPERATION);
534 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700535 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700536 if (mScreenSensor != sensorHandle) {
537 mScreenSensor = sensorHandle;
538 // TODO: consider a new method setHeadAndScreenSensor()
539 // because we generally set both at the same time.
540 // This will avoid duplicated work and recentering.
541 checkSensorsState_l();
542 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700543 return Status::ok();
544}
545
546Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
547 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200548 if (!mSupportsHeadTracking) {
549 return binderStatusFromStatusT(INVALID_OPERATION);
550 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700551 std::lock_guard lock(mLock);
552 mDisplayOrientation = physicalToLogicalAngle;
553 if (mPoseController != nullptr) {
554 mPoseController->setDisplayOrientation(mDisplayOrientation);
555 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200556 if (mEngine != nullptr) {
557 setEffectParameter_l(
558 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
559 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700560 return Status::ok();
561}
562
563Status Spatializer::setHingeAngle(float hingeAngle) {
564 std::lock_guard lock(mLock);
565 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
566 if (mEngine != nullptr) {
567 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
568 }
569 return Status::ok();
570}
571
572Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
573 ALOGV("%s", __func__);
574 if (modes == nullptr) {
575 return binderStatusFromStatusT(BAD_VALUE);
576 }
577 *modes = mSpatializationModes;
578 return Status::ok();
579}
580
Eric Laurent67816e32021-09-16 15:18:40 +0200581Status Spatializer::registerHeadTrackingCallback(
582 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
583 ALOGV("%s callback %p", __func__, callback.get());
584 std::lock_guard lock(mLock);
585 if (!mSupportsHeadTracking) {
586 return binderStatusFromStatusT(INVALID_OPERATION);
587 }
588 mHeadTrackingCallback = callback;
589 return Status::ok();
590}
591
Eric Laurentc87402b2021-09-17 16:49:42 +0200592Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
593 ALOGV("%s key %d", __func__, key);
594 std::lock_guard lock(mLock);
595 status_t status = INVALID_OPERATION;
596 if (mEngine != nullptr) {
597 status = setEffectParameter_l(key, value);
598 }
599 return binderStatusFromStatusT(status);
600}
601
602Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700603 ALOGV("%s key %d value size %d", __func__, key,
604 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200605 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700606 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200607 }
608 std::lock_guard lock(mLock);
609 status_t status = INVALID_OPERATION;
610 if (mEngine != nullptr) {
611 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
612 status = getEffectParameter_l(key, value);
613 }
614 return binderStatusFromStatusT(status);
615}
616
617Status Spatializer::getOutput(int *output) {
618 ALOGV("%s", __func__);
619 if (output == nullptr) {
620 binderStatusFromStatusT(BAD_VALUE);
621 }
622 std::lock_guard lock(mLock);
623 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
624 ALOGV("%s got output %d", __func__, *output);
625 return Status::ok();
626}
627
Eric Laurent2be8b292021-08-23 09:44:33 -0700628// SpatializerPoseController::Listener
629void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
630 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200631 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
632 "onHeadToStagePose() called with no head tracking support!");
633
Eric Laurent2be8b292021-08-23 09:44:33 -0700634 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200635 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
636 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200637 sp<AMessage> msg =
638 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
639 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
640 msg->setFloat(sHeadPoseKeys[i], vec[i]);
641 }
642 msg->post();
643}
644
645void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
646 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200647 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700648 {
649 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200650 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700651 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200652 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700653 }
654 }
655
656 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200657 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700658 }
659}
660
661void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200662 ALOGV("%s(%d)", __func__, (int)mode);
663 sp<AMessage> msg =
664 new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
665 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
666 msg->post();
667}
668
669void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
670 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200671 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700672 SpatializerHeadTrackingMode spatializerMode;
673 {
674 std::lock_guard lock(mLock);
675 if (!mSupportsHeadTracking) {
676 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
677 } else {
678 switch (mode) {
679 case HeadTrackingMode::STATIC:
680 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
681 break;
682 case HeadTrackingMode::WORLD_RELATIVE:
683 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
684 break;
685 case HeadTrackingMode::SCREEN_RELATIVE:
686 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
687 break;
688 default:
689 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
690 }
691 }
692 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200693 if (mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200694 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
695 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
696 }
Eric Laurent67816e32021-09-16 15:18:40 +0200697 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700698 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200699 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700700 callback->onHeadTrackingModeChanged(spatializerMode);
701 }
702}
703
Eric Laurent15903592022-02-24 20:44:36 +0100704status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200705 bool outputChanged = false;
706 sp<media::INativeSpatializerCallback> callback;
707
Eric Laurent2be8b292021-08-23 09:44:33 -0700708 {
709 std::lock_guard lock(mLock);
710 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
711 if (mOutput != AUDIO_IO_HANDLE_NONE) {
712 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
713 // remove FX instance
714 mEngine->setEnabled(false);
715 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100716 mPoseController.reset();
Eric Laurentee398ad2022-05-03 18:19:35 +0200717 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700718 }
Eric Laurentee398ad2022-05-03 18:19:35 +0200719
Eric Laurent2be8b292021-08-23 09:44:33 -0700720 // create FX instance on output
721 AttributionSourceState attributionSource = AttributionSourceState();
722 mEngine = new AudioEffect(attributionSource);
723 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
724 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
725 false /* probe */, true /* notifyFramesProcessed */);
726 status_t status = mEngine->initCheck();
727 ALOGV("%s mEngine create status %d", __func__, (int)status);
728 if (status != NO_ERROR) {
729 return status;
730 }
731
Eric Laurent4a872862021-10-11 17:06:47 +0200732 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700733 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200734 mNumActiveTracks = numActiveTracks;
Eric Laurentee398ad2022-05-03 18:19:35 +0200735 AudioSystem::addSupportedLatencyModesCallback(this);
736
737 std::vector<audio_latency_mode_t> latencyModes;
738 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
739 if (status == OK) {
740 mSupportedLatencyModes = latencyModes;
741 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700742
Eric Laurent11094172022-04-05 18:27:42 +0200743 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200744 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200745 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100746 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200747 }
Eric Laurent4a872862021-10-11 17:06:47 +0200748 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200749 }
Eric Laurent4a872862021-10-11 17:06:47 +0200750
751 if (outputChanged && callback != nullptr) {
752 callback->onOutputChanged(output);
753 }
754
Eric Laurent6d607012021-07-05 11:54:40 +0200755 return NO_ERROR;
756}
757
758audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700759 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200760 sp<media::INativeSpatializerCallback> callback;
761
762 {
763 std::lock_guard lock(mLock);
764 ALOGV("%s mOutput %d", __func__, (int)mOutput);
765 if (mOutput == AUDIO_IO_HANDLE_NONE) {
766 return output;
767 }
768 // remove FX instance
769 mEngine->setEnabled(false);
770 mEngine.clear();
Eric Laurentee398ad2022-05-03 18:19:35 +0200771 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200772 output = mOutput;
773 mOutput = AUDIO_IO_HANDLE_NONE;
774 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200775 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200776 }
Eric Laurent4a872862021-10-11 17:06:47 +0200777
778 if (callback != nullptr) {
779 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
780 }
Eric Laurent6d607012021-07-05 11:54:40 +0200781 return output;
782}
783
Eric Laurentee398ad2022-05-03 18:19:35 +0200784void Spatializer::onSupportedLatencyModesChanged(
785 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
786 std::lock_guard lock(mLock);
787 if (output == mOutput) {
788 mSupportedLatencyModes = modes;
789 checkSensorsState_l();
790 }
791}
792
Eric Laurent15903592022-02-24 20:44:36 +0100793void Spatializer::updateActiveTracks(size_t numActiveTracks) {
794 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200795 if (mNumActiveTracks != numActiveTracks) {
796 mNumActiveTracks = numActiveTracks;
797 checkEngineState_l();
798 checkSensorsState_l();
799 }
Eric Laurent15903592022-02-24 20:44:36 +0100800}
801
Eric Laurent9249d342022-03-18 11:55:56 +0100802void Spatializer::checkSensorsState_l() {
Eric Laurentee398ad2022-05-03 18:19:35 +0200803 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
804 bool lowLatencySupported = mSupportedLatencyModes.empty()
805 || (std::find(mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
806 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end());
807 if (mSupportsHeadTracking && mPoseController != nullptr && lowLatencySupported) {
Eric Laurent9249d342022-03-18 11:55:56 +0100808 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent15903592022-02-24 20:44:36 +0100809 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
810 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
811 mPoseController->setHeadSensor(mHeadSensor);
Eric Laurent9249d342022-03-18 11:55:56 +0100812 mPoseController->setScreenSensor(mScreenSensor);
Eric Laurentee398ad2022-05-03 18:19:35 +0200813 requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent15903592022-02-24 20:44:36 +0100814 } else {
815 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent9249d342022-03-18 11:55:56 +0100816 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent15903592022-02-24 20:44:36 +0100817 }
818 }
Eric Laurentee398ad2022-05-03 18:19:35 +0200819 if (mOutput != AUDIO_IO_HANDLE_NONE) {
820 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
821 }
Eric Laurent15903592022-02-24 20:44:36 +0100822}
823
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200824void Spatializer::checkEngineState_l() {
825 if (mEngine != nullptr) {
826 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
827 mEngine->setEnabled(true);
828 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
829 std::vector<SpatializationLevel>{mLevel});
830 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
831 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
832 } else {
833 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
834 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
835 mEngine->setEnabled(false);
836 }
837 }
838}
839
Eric Laurent11094172022-04-05 18:27:42 +0200840void Spatializer::checkPoseController_l() {
841 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
842 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
843
844 if (isControllerNeeded && mPoseController == nullptr) {
845 mPoseController = std::make_shared<SpatializerPoseController>(
846 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +0200847 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +0200848 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
849 "%s could not allocate pose controller", __func__);
850 mPoseController->setDisplayOrientation(mDisplayOrientation);
851 } else if (!isControllerNeeded && mPoseController != nullptr) {
852 mPoseController.reset();
853 }
854 if (mPoseController != nullptr) {
855 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
856 }
857}
858
Eric Laurent2be8b292021-08-23 09:44:33 -0700859void Spatializer::calculateHeadPose() {
860 ALOGV("%s", __func__);
861 std::lock_guard lock(mLock);
862 if (mPoseController != nullptr) {
863 mPoseController->calculateAsync();
864 }
865}
Eric Laurent6d607012021-07-05 11:54:40 +0200866
Eric Laurent2be8b292021-08-23 09:44:33 -0700867void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +0200868 if (user == nullptr) {
869 return;
870 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700871 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +0200872 switch (event) {
873 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -0700874 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +0100875 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200876 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -0700877 } break;
Eric Laurent6d607012021-07-05 11:54:40 +0200878 default:
Eric Laurent9249d342022-03-18 11:55:56 +0100879 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +0200880 break;
881 }
882}
883
Eric Laurent8a4259f2021-09-14 16:04:00 +0200884void Spatializer::postFramesProcessedMsg(int frames) {
885 sp<AMessage> msg =
886 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
887 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
888 msg->post();
889}
890
Eric Laurent6d607012021-07-05 11:54:40 +0200891} // namespace android