blob: f19665db8accecd740b759d7efed6196f1c0d347 [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
Shunkai Yao5a251df2022-07-22 18:42:27 +000018#include <string>
Eric Laurent6d607012021-07-05 11:54:40 +020019#define LOG_TAG "Spatializer"
20//#define LOG_NDEBUG 0
21#include <utils/Log.h>
22
Shunkai Yao5a251df2022-07-22 18:42:27 +000023#include <inttypes.h>
Eric Laurent6d607012021-07-05 11:54:40 +020024#include <limits.h>
25#include <stdint.h>
26#include <sys/types.h>
27
28#include <android/content/AttributionSourceState.h>
29#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>
Andy Hunga461a002022-05-17 10:36:02 -070035#include <media/MediaMetricsItem.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020036#include <media/ShmemCompat.h>
Eric Laurent6d607012021-07-05 11:54:40 +020037#include <mediautils/ServiceUtilities.h>
38#include <utils/Thread.h>
39
40#include "Spatializer.h"
41
42namespace android {
43
44using aidl_utils::statusTFromBinderStatus;
45using aidl_utils::binderStatusFromStatusT;
46using android::content::AttributionSourceState;
47using binder::Status;
Eric Laurent2be8b292021-08-23 09:44:33 -070048using media::HeadTrackingMode;
49using media::Pose3f;
Eric Laurent6d607012021-07-05 11:54:40 +020050using media::SpatializationLevel;
Eric Laurent2be8b292021-08-23 09:44:33 -070051using media::SpatializationMode;
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070052using media::SpatializerHeadTrackingMode;
Eric Laurent2be8b292021-08-23 09:44:33 -070053using media::SensorPoseProvider;
54
Eric Laurent2be8b292021-08-23 09:44:33 -070055using namespace std::chrono_literals;
Eric Laurent6d607012021-07-05 11:54:40 +020056
57#define VALUE_OR_RETURN_BINDER_STATUS(x) \
58 ({ auto _tmp = (x); \
59 if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
60 std::move(_tmp.value()); })
61
Andy Hunga461a002022-05-17 10:36:02 -070062audio_channel_mask_t getMaxChannelMask(std::vector<audio_channel_mask_t> masks) {
63 uint32_t maxCount = 0;
64 audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
65 for (auto mask : masks) {
66 const size_t count = audio_channel_count_from_out_mask(mask);
67 if (count > maxCount) {
68 maxMask = mask;
69 maxCount = count;
70 }
71 }
72 return maxMask;
73}
74
Eric Laurent6d607012021-07-05 11:54:40 +020075// ---------------------------------------------------------------------------
76
Eric Laurent8a4259f2021-09-14 16:04:00 +020077class Spatializer::EngineCallbackHandler : public AHandler {
78public:
79 EngineCallbackHandler(wp<Spatializer> spatializer)
80 : mSpatializer(spatializer) {
81 }
82
83 enum {
84 // Device state callbacks
85 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
86 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
87 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
88 };
89 static constexpr const char *kNumFramesKey = "numFrames";
90 static constexpr const char *kModeKey = "mode";
91 static constexpr const char *kTranslation0Key = "translation0";
92 static constexpr const char *kTranslation1Key = "translation1";
93 static constexpr const char *kTranslation2Key = "translation2";
94 static constexpr const char *kRotation0Key = "rotation0";
95 static constexpr const char *kRotation1Key = "rotation1";
96 static constexpr const char *kRotation2Key = "rotation2";
97
98 void onMessageReceived(const sp<AMessage> &msg) override {
99 switch (msg->what()) {
100 case kWhatOnFramesProcessed: {
101 sp<Spatializer> spatializer = mSpatializer.promote();
102 if (spatializer == nullptr) {
103 ALOGW("%s: Cannot promote spatializer", __func__);
104 return;
105 }
106 int numFrames;
107 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
108 ALOGE("%s: Cannot find num frames!", __func__);
109 return;
110 }
111 if (numFrames > 0) {
112 spatializer->calculateHeadPose();
113 }
114 } break;
115 case kWhatOnHeadToStagePose: {
116 sp<Spatializer> spatializer = mSpatializer.promote();
117 if (spatializer == nullptr) {
118 ALOGW("%s: Cannot promote spatializer", __func__);
119 return;
120 }
121 std::vector<float> headToStage(sHeadPoseKeys.size());
122 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
123 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
124 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
125 return;
126 }
127 }
128 spatializer->onHeadToStagePoseMsg(headToStage);
129 } break;
130 case kWhatOnActualModeChange: {
131 sp<Spatializer> spatializer = mSpatializer.promote();
132 if (spatializer == nullptr) {
133 ALOGW("%s: Cannot promote spatializer", __func__);
134 return;
135 }
136 int mode;
137 if (!msg->findInt32(EngineCallbackHandler::kModeKey, &mode)) {
138 ALOGE("%s: Cannot find actualMode!", __func__);
139 return;
140 }
141 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
142 } break;
143 default:
144 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
145 }
146 }
147private:
148 wp<Spatializer> mSpatializer;
149};
150
151const std::vector<const char *> Spatializer::sHeadPoseKeys = {
152 Spatializer::EngineCallbackHandler::kTranslation0Key,
153 Spatializer::EngineCallbackHandler::kTranslation1Key,
154 Spatializer::EngineCallbackHandler::kTranslation2Key,
155 Spatializer::EngineCallbackHandler::kRotation0Key,
156 Spatializer::EngineCallbackHandler::kRotation1Key,
157 Spatializer::EngineCallbackHandler::kRotation2Key,
158};
159
160// ---------------------------------------------------------------------------
Shunkai Yao5a251df2022-07-22 18:42:27 +0000161
162// Convert recorded sensor data to string with level indentation.
Shunkai Yao7de40382022-08-25 00:44:04 +0000163std::string Spatializer::HeadToStagePoseRecorder::toString(unsigned level) const {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000164 std::string prefixSpace(level, ' ');
165 return mPoseRecordLog.dumpToString((prefixSpace + " ").c_str(), Spatializer::mMaxLocalLogLine);
166}
167
168// Compute sensor data, record into local log when it is time.
Shunkai Yao7de40382022-08-25 00:44:04 +0000169void Spatializer::HeadToStagePoseRecorder::record(const std::vector<float>& headToStage) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000170 if (headToStage.size() != mPoseVectorSize) return;
171
172 if (mNumOfSampleSinceLastRecord++ == 0) {
173 mFirstSampleTimestamp = std::chrono::steady_clock::now();
174 }
175 // if it's time, do record and reset.
176 if (shouldRecordLog()) {
177 poseSumToAverage();
178 mPoseRecordLog.log(
Shunkai Yao7de40382022-08-25 00:44:04 +0000179 "mean: %s, min: %s, max %s, calculated %d samples in %0.4f second(s)",
Shunkai Yao5a251df2022-07-22 18:42:27 +0000180 Spatializer::toString<double>(mPoseRadianSum, true /* radianToDegree */).c_str(),
181 Spatializer::toString<float>(mMinPoseAngle, true /* radianToDegree */).c_str(),
182 Spatializer::toString<float>(mMaxPoseAngle, true /* radianToDegree */).c_str(),
Shunkai Yao7de40382022-08-25 00:44:04 +0000183 mNumOfSampleSinceLastRecord, mNumOfSecondsSinceLastRecord.count());
184 resetRecord();
Shunkai Yao5a251df2022-07-22 18:42:27 +0000185 }
186 // update stream average.
187 for (int i = 0; i < mPoseVectorSize; i++) {
188 mPoseRadianSum[i] += headToStage[i];
189 mMaxPoseAngle[i] = std::max(mMaxPoseAngle[i], headToStage[i]);
190 mMinPoseAngle[i] = std::min(mMinPoseAngle[i], headToStage[i]);
191 }
192 return;
193}
194
195// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200196sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
197 sp<Spatializer> spatializer;
198
199 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
200 if (effectsFactoryHal == nullptr) {
201 ALOGW("%s failed to create effect factory interface", __func__);
202 return spatializer;
203 }
204
205 std::vector<effect_descriptor_t> descriptors;
206 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200207 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200208 if (status != NO_ERROR) {
209 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
210 return spatializer;
211 }
212 ALOG_ASSERT(!descriptors.empty(),
213 "%s getDescriptors() returned no error but empty list", __func__);
214
Shunkai Yao5a251df2022-07-22 18:42:27 +0000215 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200216 sp<EffectHalInterface> effect;
217 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
218 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000219 ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
220 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200221
222 if (status == NO_ERROR && effect != nullptr) {
223 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700224 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
225 spatializer.clear();
226 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000227 spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
228 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200229 }
230
231 return spatializer;
232}
233
Eric Laurent2be8b292021-08-23 09:44:33 -0700234Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
235 : mEngineDescriptor(engineDescriptor),
236 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200237 ALOGV("%s", __func__);
238}
239
Eric Laurent8a4259f2021-09-14 16:04:00 +0200240void Spatializer::onFirstRef() {
241 mLooper = new ALooper;
242 mLooper->setName("Spatializer-looper");
243 mLooper->start(
244 /*runOnCallingThread*/false,
245 /*canCallJava*/ false,
246 PRIORITY_AUDIO);
247
248 mHandler = new EngineCallbackHandler(this);
249 mLooper->registerHandler(mHandler);
250}
251
Eric Laurent6d607012021-07-05 11:54:40 +0200252Spatializer::~Spatializer() {
253 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200254 if (mLooper != nullptr) {
255 mLooper->stop();
256 mLooper->unregisterHandler(mHandler->id());
257 }
258 mLooper.clear();
259 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200260}
261
Eric Laurent2be8b292021-08-23 09:44:33 -0700262status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
263 ALOGV("%s", __func__);
264
265 std::vector<bool> supportsHeadTracking;
266 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
267 &supportsHeadTracking);
268 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700269 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700270 return status;
271 }
272 mSupportsHeadTracking = supportsHeadTracking[0];
273
Andy Hung119dbdb2022-05-11 19:20:13 -0700274 std::vector<media::SpatializationLevel> spatializationLevels;
275 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
276 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700277 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700278 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700279 return status;
280 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700281 bool noneLevelFound = false;
282 bool activeLevelFound = false;
283 for (const auto spatializationLevel : spatializationLevels) {
284 if (!aidl_utils::isValidEnum(spatializationLevel)) {
285 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
286 continue;
287 }
288 if (spatializationLevel == media::SpatializationLevel::NONE) {
289 noneLevelFound = true;
290 } else {
291 activeLevelFound = true;
292 }
293 // we don't detect duplicates.
294 mLevels.emplace_back(spatializationLevel);
295 }
296 if (!noneLevelFound || !activeLevelFound) {
297 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
298 " and another valid level", __func__);
299 return BAD_VALUE;
300 }
301
302 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700303 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700304 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700305 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700306 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700307 return status;
308 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000309
Andy Hung119dbdb2022-05-11 19:20:13 -0700310 for (const auto spatializationMode : spatializationModes) {
311 if (!aidl_utils::isValidEnum(spatializationMode)) {
312 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
313 continue;
314 }
315 // we don't detect duplicates.
316 mSpatializationModes.emplace_back(spatializationMode);
317 }
318 if (mSpatializationModes.empty()) {
319 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
320 return BAD_VALUE;
321 }
322
323 std::vector<audio_channel_mask_t> channelMasks;
324 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
325 &channelMasks);
326 if (status != NO_ERROR) {
327 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
328 return status;
329 }
330 for (const auto channelMask : channelMasks) {
331 if (!audio_is_channel_mask_spatialized(channelMask)) {
332 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
333 continue;
334 }
335 // we don't detect duplicates.
336 mChannelMasks.emplace_back(channelMask);
337 }
338 if (mChannelMasks.empty()) {
339 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
340 return BAD_VALUE;
341 }
Andy Hunga461a002022-05-17 10:36:02 -0700342
343 // Currently we expose only RELATIVE_WORLD.
344 // This is a limitation of the head tracking library based on a UX choice.
345 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
346 if (mSupportsHeadTracking) {
347 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
348 }
349 mediametrics::LogItem(mMetricsId)
350 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
351 .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)getMaxChannelMask(mChannelMasks))
352 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
353 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
354 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
355 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
356 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700357 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700358}
359
360/** Gets the channel mask, sampling rate and format set for the spatializer input. */
361audio_config_base_t Spatializer::getAudioInConfig() const {
362 std::lock_guard lock(mLock);
363 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
364 // For now use highest supported channel count
Andy Hunga461a002022-05-17 10:36:02 -0700365 config.channel_mask = getMaxChannelMask(mChannelMasks);
Eric Laurent2be8b292021-08-23 09:44:33 -0700366 return config;
367}
368
Eric Laurent6d607012021-07-05 11:54:40 +0200369status_t Spatializer::registerCallback(
370 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700371 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200372 if (callback == nullptr) {
373 return BAD_VALUE;
374 }
375
Eric Laurentb57604f2022-08-31 16:07:50 +0200376 if (mSpatializerCallback != nullptr) {
377 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
378 ALOGW("%s: Registering callback %p again",
379 __func__, mSpatializerCallback.get());
380 return NO_ERROR;
381 }
382 ALOGE("%s: Already one client registered with callback %p",
383 __func__, mSpatializerCallback.get());
384 return INVALID_OPERATION;
385 }
386
Eric Laurent6d607012021-07-05 11:54:40 +0200387 sp<IBinder> binder = IInterface::asBinder(callback);
388 status_t status = binder->linkToDeath(this);
389 if (status == NO_ERROR) {
390 mSpatializerCallback = callback;
391 }
392 ALOGV("%s status %d", __func__, status);
393 return status;
394}
395
396// IBinder::DeathRecipient
397void Spatializer::binderDied(__unused const wp<IBinder> &who) {
398 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700399 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200400 mLevel = SpatializationLevel::NONE;
401 mSpatializerCallback.clear();
402 }
403 ALOGV("%s", __func__);
404 mPolicyCallback->onCheckSpatializer();
405}
406
407// ISpatializer
408Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
409 ALOGV("%s", __func__);
410 if (levels == nullptr) {
411 return binderStatusFromStatusT(BAD_VALUE);
412 }
Andy Hunga461a002022-05-17 10:36:02 -0700413 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700414 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200415 return Status::ok();
416}
417
Eric Laurent2be8b292021-08-23 09:44:33 -0700418Status Spatializer::setLevel(SpatializationLevel level) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000419 ALOGV("%s level %s", __func__, media::toString(level).c_str());
420 mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
Eric Laurent6d607012021-07-05 11:54:40 +0200421 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700422 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200423 return binderStatusFromStatusT(BAD_VALUE);
424 }
425 sp<media::INativeSpatializerCallback> callback;
426 bool levelChanged = false;
427 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700428 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200429 levelChanged = mLevel != level;
430 mLevel = level;
431 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700432
433 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200434 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700435 }
Eric Laurent9249d342022-03-18 11:55:56 +0100436 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200437 }
438
439 if (levelChanged) {
440 mPolicyCallback->onCheckSpatializer();
441 if (callback != nullptr) {
442 callback->onLevelChanged(level);
443 }
444 }
445 return Status::ok();
446}
447
Eric Laurent2be8b292021-08-23 09:44:33 -0700448Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200449 if (level == nullptr) {
450 return binderStatusFromStatusT(BAD_VALUE);
451 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700452 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200453 *level = mLevel;
454 ALOGV("%s level %d", __func__, (int)*level);
455 return Status::ok();
456}
457
Eric Laurentc87402b2021-09-17 16:49:42 +0200458Status Spatializer::isHeadTrackingSupported(bool *supports) {
459 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
460 if (supports == nullptr) {
461 return binderStatusFromStatusT(BAD_VALUE);
462 }
463 std::lock_guard lock(mLock);
464 *supports = mSupportsHeadTracking;
465 return Status::ok();
466}
467
Eric Laurent6d607012021-07-05 11:54:40 +0200468Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700469 std::vector<SpatializerHeadTrackingMode>* modes) {
470 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200471 ALOGV("%s", __func__);
472 if (modes == nullptr) {
473 return binderStatusFromStatusT(BAD_VALUE);
474 }
Andy Hunga461a002022-05-17 10:36:02 -0700475 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200476 return Status::ok();
477}
478
Eric Laurent2be8b292021-08-23 09:44:33 -0700479Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000480 ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700481
482 if (!mSupportsHeadTracking) {
483 return binderStatusFromStatusT(INVALID_OPERATION);
484 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000485 mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700486 std::lock_guard lock(mLock);
487 switch (mode) {
488 case SpatializerHeadTrackingMode::OTHER:
489 return binderStatusFromStatusT(BAD_VALUE);
490 case SpatializerHeadTrackingMode::DISABLED:
491 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
492 break;
493 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
494 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
495 break;
496 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
497 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
498 break;
499 }
500
Eric Laurent11094172022-04-05 18:27:42 +0200501 checkPoseController_l();
502 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700503
504 return Status::ok();
505}
506
507Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200508 if (mode == nullptr) {
509 return binderStatusFromStatusT(BAD_VALUE);
510 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700511 std::lock_guard lock(mLock);
512 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200513 ALOGV("%s mode %d", __func__, (int)*mode);
514 return Status::ok();
515}
516
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700517Status Spatializer::recenterHeadTracker() {
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);
522 if (mPoseController != nullptr) {
523 mPoseController->recenter();
524 }
Eric Laurent6d607012021-07-05 11:54:40 +0200525 return Status::ok();
526}
527
528Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200529 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200530 if (!mSupportsHeadTracking) {
531 return binderStatusFromStatusT(INVALID_OPERATION);
532 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700533 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
534 if (!maybePose.has_value()) {
535 ALOGW("Invalid screenToStage vector.");
536 return binderStatusFromStatusT(BAD_VALUE);
537 }
538 std::lock_guard lock(mLock);
539 if (mPoseController != nullptr) {
Shunkai Yao7de40382022-08-25 00:44:04 +0000540 mLocalLog.log("%s with screenToStage %s", __func__, toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700541 mPoseController->setScreenToStagePose(maybePose.value());
542 }
Eric Laurent6d607012021-07-05 11:54:40 +0200543 return Status::ok();
544}
545
546Status Spatializer::release() {
547 ALOGV("%s", __func__);
548 bool levelChanged = false;
549 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700550 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200551 if (mSpatializerCallback == nullptr) {
552 return binderStatusFromStatusT(INVALID_OPERATION);
553 }
554
555 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
556 binder->unlinkToDeath(this);
557 mSpatializerCallback.clear();
558
559 levelChanged = mLevel != SpatializationLevel::NONE;
560 mLevel = SpatializationLevel::NONE;
561 }
562
563 if (levelChanged) {
564 mPolicyCallback->onCheckSpatializer();
565 }
566 return Status::ok();
567}
568
Eric Laurent2be8b292021-08-23 09:44:33 -0700569Status Spatializer::setHeadSensor(int sensorHandle) {
570 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200571 if (!mSupportsHeadTracking) {
572 return binderStatusFromStatusT(INVALID_OPERATION);
573 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700574 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700575 if (mHeadSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000576 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700577 mHeadSensor = sensorHandle;
578 checkPoseController_l();
579 checkSensorsState_l();
580 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700581 return Status::ok();
582}
583
584Status Spatializer::setScreenSensor(int sensorHandle) {
585 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200586 if (!mSupportsHeadTracking) {
587 return binderStatusFromStatusT(INVALID_OPERATION);
588 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700589 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700590 if (mScreenSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000591 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700592 mScreenSensor = sensorHandle;
593 // TODO: consider a new method setHeadAndScreenSensor()
594 // because we generally set both at the same time.
595 // This will avoid duplicated work and recentering.
596 checkSensorsState_l();
597 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700598 return Status::ok();
599}
600
601Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
602 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200603 if (!mSupportsHeadTracking) {
604 return binderStatusFromStatusT(INVALID_OPERATION);
605 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700606 std::lock_guard lock(mLock);
607 mDisplayOrientation = physicalToLogicalAngle;
Shunkai Yao5a251df2022-07-22 18:42:27 +0000608 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700609 if (mPoseController != nullptr) {
610 mPoseController->setDisplayOrientation(mDisplayOrientation);
611 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200612 if (mEngine != nullptr) {
613 setEffectParameter_l(
614 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
615 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700616 return Status::ok();
617}
618
619Status Spatializer::setHingeAngle(float hingeAngle) {
620 std::lock_guard lock(mLock);
621 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
622 if (mEngine != nullptr) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000623 mLocalLog.log("%s with %f", __func__, hingeAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700624 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
625 }
626 return Status::ok();
627}
628
629Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
630 ALOGV("%s", __func__);
631 if (modes == nullptr) {
632 return binderStatusFromStatusT(BAD_VALUE);
633 }
634 *modes = mSpatializationModes;
635 return Status::ok();
636}
637
Eric Laurent67816e32021-09-16 15:18:40 +0200638Status Spatializer::registerHeadTrackingCallback(
639 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
640 ALOGV("%s callback %p", __func__, callback.get());
641 std::lock_guard lock(mLock);
642 if (!mSupportsHeadTracking) {
643 return binderStatusFromStatusT(INVALID_OPERATION);
644 }
645 mHeadTrackingCallback = callback;
646 return Status::ok();
647}
648
Eric Laurentc87402b2021-09-17 16:49:42 +0200649Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
650 ALOGV("%s key %d", __func__, key);
651 std::lock_guard lock(mLock);
652 status_t status = INVALID_OPERATION;
653 if (mEngine != nullptr) {
654 status = setEffectParameter_l(key, value);
655 }
656 return binderStatusFromStatusT(status);
657}
658
659Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700660 ALOGV("%s key %d value size %d", __func__, key,
661 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200662 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700663 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200664 }
665 std::lock_guard lock(mLock);
666 status_t status = INVALID_OPERATION;
667 if (mEngine != nullptr) {
668 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
669 status = getEffectParameter_l(key, value);
670 }
671 return binderStatusFromStatusT(status);
672}
673
674Status Spatializer::getOutput(int *output) {
675 ALOGV("%s", __func__);
676 if (output == nullptr) {
677 binderStatusFromStatusT(BAD_VALUE);
678 }
679 std::lock_guard lock(mLock);
680 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
681 ALOGV("%s got output %d", __func__, *output);
682 return Status::ok();
683}
684
Eric Laurent2be8b292021-08-23 09:44:33 -0700685// SpatializerPoseController::Listener
686void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
687 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200688 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
689 "onHeadToStagePose() called with no head tracking support!");
690
Eric Laurent2be8b292021-08-23 09:44:33 -0700691 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200692 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
693 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200694 sp<AMessage> msg =
695 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
696 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
697 msg->setFloat(sHeadPoseKeys[i], vec[i]);
698 }
699 msg->post();
700}
701
702void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
703 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200704 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700705 {
706 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200707 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700708 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200709 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Shunkai Yao7de40382022-08-25 00:44:04 +0000710 mPoseRecorder.record(headToStage);
711 mPoseDurableRecorder.record(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700712 }
713 }
714
715 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200716 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700717 }
718}
719
720void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000721 std::string modeStr = SpatializerPoseController::toString(mode);
722 ALOGV("%s(%s)", __func__, modeStr.c_str());
723 mLocalLog.log("%s with %s", __func__, modeStr.c_str());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200724 sp<AMessage> msg =
725 new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
726 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
727 msg->post();
728}
729
730void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
731 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200732 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700733 SpatializerHeadTrackingMode spatializerMode;
734 {
735 std::lock_guard lock(mLock);
736 if (!mSupportsHeadTracking) {
737 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
738 } else {
739 switch (mode) {
740 case HeadTrackingMode::STATIC:
741 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
742 break;
743 case HeadTrackingMode::WORLD_RELATIVE:
744 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
745 break;
746 case HeadTrackingMode::SCREEN_RELATIVE:
747 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
748 break;
749 default:
750 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
751 }
752 }
753 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200754 if (mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200755 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
756 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
757 }
Eric Laurent67816e32021-09-16 15:18:40 +0200758 callback = mHeadTrackingCallback;
Shunkai Yao5a251df2022-07-22 18:42:27 +0000759 mLocalLog.log("%s: %s, spatializerMode %s", __func__,
760 SpatializerPoseController::toString(mode).c_str(),
761 media::toString(spatializerMode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700762 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200763 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700764 callback->onHeadTrackingModeChanged(spatializerMode);
765 }
766}
767
Eric Laurent15903592022-02-24 20:44:36 +0100768status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200769 bool outputChanged = false;
770 sp<media::INativeSpatializerCallback> callback;
771
Eric Laurent2be8b292021-08-23 09:44:33 -0700772 {
773 std::lock_guard lock(mLock);
774 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000775 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
776 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700777 if (mOutput != AUDIO_IO_HANDLE_NONE) {
778 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
779 // remove FX instance
780 mEngine->setEnabled(false);
781 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100782 mPoseController.reset();
Eric Laurentb387fb42022-05-03 18:19:35 +0200783 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700784 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200785
Eric Laurent2be8b292021-08-23 09:44:33 -0700786 // create FX instance on output
787 AttributionSourceState attributionSource = AttributionSourceState();
788 mEngine = new AudioEffect(attributionSource);
789 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
790 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
791 false /* probe */, true /* notifyFramesProcessed */);
792 status_t status = mEngine->initCheck();
793 ALOGV("%s mEngine create status %d", __func__, (int)status);
794 if (status != NO_ERROR) {
795 return status;
796 }
797
Eric Laurent4a872862021-10-11 17:06:47 +0200798 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700799 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200800 mNumActiveTracks = numActiveTracks;
Eric Laurentb387fb42022-05-03 18:19:35 +0200801 AudioSystem::addSupportedLatencyModesCallback(this);
802
803 std::vector<audio_latency_mode_t> latencyModes;
804 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
805 if (status == OK) {
806 mSupportedLatencyModes = latencyModes;
807 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700808
Eric Laurent11094172022-04-05 18:27:42 +0200809 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200810 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200811 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100812 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200813 }
Eric Laurent4a872862021-10-11 17:06:47 +0200814 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200815 }
Eric Laurent4a872862021-10-11 17:06:47 +0200816
817 if (outputChanged && callback != nullptr) {
818 callback->onOutputChanged(output);
819 }
820
Eric Laurent6d607012021-07-05 11:54:40 +0200821 return NO_ERROR;
822}
823
824audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700825 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200826 sp<media::INativeSpatializerCallback> callback;
827
828 {
829 std::lock_guard lock(mLock);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000830 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +0200831 ALOGV("%s mOutput %d", __func__, (int)mOutput);
832 if (mOutput == AUDIO_IO_HANDLE_NONE) {
833 return output;
834 }
835 // remove FX instance
836 mEngine->setEnabled(false);
837 mEngine.clear();
Eric Laurentb387fb42022-05-03 18:19:35 +0200838 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200839 output = mOutput;
840 mOutput = AUDIO_IO_HANDLE_NONE;
841 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200842 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200843 }
Eric Laurent4a872862021-10-11 17:06:47 +0200844
845 if (callback != nullptr) {
846 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
847 }
Eric Laurent6d607012021-07-05 11:54:40 +0200848 return output;
849}
850
Eric Laurentb387fb42022-05-03 18:19:35 +0200851void Spatializer::onSupportedLatencyModesChanged(
852 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
853 std::lock_guard lock(mLock);
854 if (output == mOutput) {
855 mSupportedLatencyModes = modes;
856 checkSensorsState_l();
857 }
858}
859
Eric Laurent15903592022-02-24 20:44:36 +0100860void Spatializer::updateActiveTracks(size_t numActiveTracks) {
861 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200862 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000863 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200864 mNumActiveTracks = numActiveTracks;
865 checkEngineState_l();
866 checkSensorsState_l();
867 }
Eric Laurent15903592022-02-24 20:44:36 +0100868}
869
Eric Laurent9249d342022-03-18 11:55:56 +0100870void Spatializer::checkSensorsState_l() {
Eric Laurentb387fb42022-05-03 18:19:35 +0200871 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
872 bool lowLatencySupported = mSupportedLatencyModes.empty()
873 || (std::find(mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
874 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end());
875 if (mSupportsHeadTracking && mPoseController != nullptr && lowLatencySupported) {
Eric Laurent9249d342022-03-18 11:55:56 +0100876 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent15903592022-02-24 20:44:36 +0100877 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
878 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
879 mPoseController->setHeadSensor(mHeadSensor);
Eric Laurent9249d342022-03-18 11:55:56 +0100880 mPoseController->setScreenSensor(mScreenSensor);
Eric Laurentb387fb42022-05-03 18:19:35 +0200881 requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent15903592022-02-24 20:44:36 +0100882 } else {
883 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent9249d342022-03-18 11:55:56 +0100884 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent15903592022-02-24 20:44:36 +0100885 }
886 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200887 if (mOutput != AUDIO_IO_HANDLE_NONE) {
888 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
889 }
Eric Laurent15903592022-02-24 20:44:36 +0100890}
891
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200892void Spatializer::checkEngineState_l() {
893 if (mEngine != nullptr) {
894 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
895 mEngine->setEnabled(true);
896 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
897 std::vector<SpatializationLevel>{mLevel});
898 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
899 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
900 } else {
901 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
902 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
903 mEngine->setEnabled(false);
904 }
905 }
906}
907
Eric Laurent11094172022-04-05 18:27:42 +0200908void Spatializer::checkPoseController_l() {
909 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
910 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
911
912 if (isControllerNeeded && mPoseController == nullptr) {
913 mPoseController = std::make_shared<SpatializerPoseController>(
914 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +0200915 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +0200916 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
917 "%s could not allocate pose controller", __func__);
918 mPoseController->setDisplayOrientation(mDisplayOrientation);
919 } else if (!isControllerNeeded && mPoseController != nullptr) {
920 mPoseController.reset();
921 }
922 if (mPoseController != nullptr) {
923 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
924 }
925}
926
Eric Laurent2be8b292021-08-23 09:44:33 -0700927void Spatializer::calculateHeadPose() {
928 ALOGV("%s", __func__);
929 std::lock_guard lock(mLock);
930 if (mPoseController != nullptr) {
931 mPoseController->calculateAsync();
932 }
933}
Eric Laurent6d607012021-07-05 11:54:40 +0200934
Eric Laurent2be8b292021-08-23 09:44:33 -0700935void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +0200936 if (user == nullptr) {
937 return;
938 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700939 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +0200940 switch (event) {
941 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -0700942 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +0100943 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200944 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -0700945 } break;
Eric Laurent6d607012021-07-05 11:54:40 +0200946 default:
Eric Laurent9249d342022-03-18 11:55:56 +0100947 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +0200948 break;
949 }
950}
951
Eric Laurent8a4259f2021-09-14 16:04:00 +0200952void Spatializer::postFramesProcessedMsg(int frames) {
953 sp<AMessage> msg =
954 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
955 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
956 msg->post();
957}
958
Shunkai Yao5a251df2022-07-22 18:42:27 +0000959std::string Spatializer::toString(unsigned level) const {
960 std::string prefixSpace;
961 prefixSpace.append(level, ' ');
962 std::string ss = prefixSpace + "Spatializer:\n";
963 bool needUnlock = false;
964
965 prefixSpace += ' ';
966 if (!mLock.try_lock()) {
967 // dumpsys even try_lock failed, information dump can be useful although may not accurate
968 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
969 } else {
970 needUnlock = true;
971 }
972
973 // Spatializer class information.
974 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
975 ss.append(prefixSpace).append("Supported levels: [");
976 for (auto& level : mLevels) {
977 base::StringAppendF(&ss, " %s", media::toString(level).c_str());
978 }
979 base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
980
981 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
982 for (auto& mode : mHeadTrackingModes) {
983 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
984 }
985 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
986 SpatializerPoseController::toString(mDesiredHeadTrackingMode).c_str(),
987 media::toString(mActualHeadTrackingMode).c_str());
988
989 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
990 for (auto& mode : mSpatializationModes) {
991 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
992 }
993 ss += "]\n";
994
995 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
996 for (auto& mask : mChannelMasks) {
997 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
998 }
999 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1000 mSupportsHeadTracking ? "true" : "false");
1001 // 2. Settings (Output, tracks)
1002 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1003 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1004
1005 // 3. Sensors, Effect information.
1006 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1007 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1008 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1009 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1010 mDisplayOrientation);
1011
1012 ss.append(prefixSpace + "CommandLog:\n");
1013 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001014
1015 // PostController dump.
1016 if (mPoseController != nullptr) {
1017 ss += mPoseController->toString(level + 1);
Shunkai Yao7de40382022-08-25 00:44:04 +00001018 ss.append(prefixSpace +
1019 "Sensor data format - [rx, ry, rz, vx, vy, vz] (units-degree, "
1020 "r-transform, v-angular velocity, x-pitch, y-roll, z-yaw):\n");
1021 ss.append(prefixSpace + "PerMinuteHistory:\n");
1022 ss += mPoseDurableRecorder.toString(level + 1);
1023 ss.append(prefixSpace + "PerSecondHistory:\n");
1024 ss += mPoseRecorder.toString(level + 1);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001025 } else {
1026 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1027 }
1028
1029 if (needUnlock) {
1030 mLock.unlock();
1031 }
1032 return ss;
1033}
1034
Eric Laurent6d607012021-07-05 11:54:40 +02001035} // namespace android