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