blob: f765934f2e505b355a45cb79c4e32f827c3bb3ea [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
Eric Laurentdf2ece42022-07-20 13:49:47 +020088 kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
Eric Laurent8a4259f2021-09-14 16:04:00 +020089 };
90 static constexpr const char *kNumFramesKey = "numFrames";
91 static constexpr const char *kModeKey = "mode";
92 static constexpr const char *kTranslation0Key = "translation0";
93 static constexpr const char *kTranslation1Key = "translation1";
94 static constexpr const char *kTranslation2Key = "translation2";
95 static constexpr const char *kRotation0Key = "rotation0";
96 static constexpr const char *kRotation1Key = "rotation1";
97 static constexpr const char *kRotation2Key = "rotation2";
Eric Laurentdf2ece42022-07-20 13:49:47 +020098 static constexpr const char *kLatencyModesKey = "latencyModes";
99
100 class LatencyModes : public RefBase {
101 public:
102 LatencyModes(audio_io_handle_t output,
103 const std::vector<audio_latency_mode_t>& latencyModes)
104 : mOutput(output), mLatencyModes(latencyModes) {}
105 ~LatencyModes() = default;
106
107 audio_io_handle_t mOutput;
108 std::vector<audio_latency_mode_t> mLatencyModes;
109 };
Eric Laurent8a4259f2021-09-14 16:04:00 +0200110
111 void onMessageReceived(const sp<AMessage> &msg) override {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200112 sp<Spatializer> spatializer = mSpatializer.promote();
113 if (spatializer == nullptr) {
114 ALOGW("%s: Cannot promote spatializer", __func__);
115 return;
116 }
Eric Laurent8a4259f2021-09-14 16:04:00 +0200117 switch (msg->what()) {
118 case kWhatOnFramesProcessed: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200119 int numFrames;
120 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
121 ALOGE("%s: Cannot find num frames!", __func__);
122 return;
123 }
124 if (numFrames > 0) {
125 spatializer->calculateHeadPose();
126 }
127 } break;
128 case kWhatOnHeadToStagePose: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200129 std::vector<float> headToStage(sHeadPoseKeys.size());
130 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
131 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
132 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
133 return;
134 }
135 }
136 spatializer->onHeadToStagePoseMsg(headToStage);
137 } break;
138 case kWhatOnActualModeChange: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200139 int mode;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200140 if (!msg->findInt32(kModeKey, &mode)) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200141 ALOGE("%s: Cannot find actualMode!", __func__);
142 return;
143 }
144 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
145 } break;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200146
147 case kWhatOnLatencyModesChanged: {
148 sp<RefBase> object;
149 if (!msg->findObject(kLatencyModesKey, &object)) {
150 ALOGE("%s: Cannot find latency modes!", __func__);
151 return;
152 }
153 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
154 spatializer->onSupportedLatencyModesChangedMsg(
155 latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
156 } break;
157
Eric Laurent8a4259f2021-09-14 16:04:00 +0200158 default:
159 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
160 }
161 }
162private:
163 wp<Spatializer> mSpatializer;
164};
165
166const std::vector<const char *> Spatializer::sHeadPoseKeys = {
167 Spatializer::EngineCallbackHandler::kTranslation0Key,
168 Spatializer::EngineCallbackHandler::kTranslation1Key,
169 Spatializer::EngineCallbackHandler::kTranslation2Key,
170 Spatializer::EngineCallbackHandler::kRotation0Key,
171 Spatializer::EngineCallbackHandler::kRotation1Key,
172 Spatializer::EngineCallbackHandler::kRotation2Key,
173};
174
175// ---------------------------------------------------------------------------
Shunkai Yao5a251df2022-07-22 18:42:27 +0000176
177// Convert recorded sensor data to string with level indentation.
Shunkai Yao7de40382022-08-25 00:44:04 +0000178std::string Spatializer::HeadToStagePoseRecorder::toString(unsigned level) const {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000179 std::string prefixSpace(level, ' ');
180 return mPoseRecordLog.dumpToString((prefixSpace + " ").c_str(), Spatializer::mMaxLocalLogLine);
181}
182
183// Compute sensor data, record into local log when it is time.
Shunkai Yao7de40382022-08-25 00:44:04 +0000184void Spatializer::HeadToStagePoseRecorder::record(const std::vector<float>& headToStage) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000185 if (headToStage.size() != mPoseVectorSize) return;
186
187 if (mNumOfSampleSinceLastRecord++ == 0) {
188 mFirstSampleTimestamp = std::chrono::steady_clock::now();
189 }
190 // if it's time, do record and reset.
191 if (shouldRecordLog()) {
192 poseSumToAverage();
193 mPoseRecordLog.log(
Shunkai Yao7de40382022-08-25 00:44:04 +0000194 "mean: %s, min: %s, max %s, calculated %d samples in %0.4f second(s)",
Shunkai Yao5a251df2022-07-22 18:42:27 +0000195 Spatializer::toString<double>(mPoseRadianSum, true /* radianToDegree */).c_str(),
196 Spatializer::toString<float>(mMinPoseAngle, true /* radianToDegree */).c_str(),
197 Spatializer::toString<float>(mMaxPoseAngle, true /* radianToDegree */).c_str(),
Shunkai Yao7de40382022-08-25 00:44:04 +0000198 mNumOfSampleSinceLastRecord, mNumOfSecondsSinceLastRecord.count());
199 resetRecord();
Shunkai Yao5a251df2022-07-22 18:42:27 +0000200 }
201 // update stream average.
202 for (int i = 0; i < mPoseVectorSize; i++) {
203 mPoseRadianSum[i] += headToStage[i];
204 mMaxPoseAngle[i] = std::max(mMaxPoseAngle[i], headToStage[i]);
205 mMinPoseAngle[i] = std::min(mMinPoseAngle[i], headToStage[i]);
206 }
207 return;
208}
209
210// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200211sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
212 sp<Spatializer> spatializer;
213
214 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
215 if (effectsFactoryHal == nullptr) {
216 ALOGW("%s failed to create effect factory interface", __func__);
217 return spatializer;
218 }
219
220 std::vector<effect_descriptor_t> descriptors;
221 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200222 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200223 if (status != NO_ERROR) {
224 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
225 return spatializer;
226 }
227 ALOG_ASSERT(!descriptors.empty(),
228 "%s getDescriptors() returned no error but empty list", __func__);
229
Shunkai Yao5a251df2022-07-22 18:42:27 +0000230 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200231 sp<EffectHalInterface> effect;
232 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
233 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000234 ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
235 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200236
237 if (status == NO_ERROR && effect != nullptr) {
238 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700239 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
240 spatializer.clear();
241 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000242 spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
243 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200244 }
245
246 return spatializer;
247}
248
Eric Laurent2be8b292021-08-23 09:44:33 -0700249Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
250 : mEngineDescriptor(engineDescriptor),
251 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200252 ALOGV("%s", __func__);
253}
254
Eric Laurent8a4259f2021-09-14 16:04:00 +0200255void Spatializer::onFirstRef() {
256 mLooper = new ALooper;
257 mLooper->setName("Spatializer-looper");
258 mLooper->start(
259 /*runOnCallingThread*/false,
260 /*canCallJava*/ false,
261 PRIORITY_AUDIO);
262
263 mHandler = new EngineCallbackHandler(this);
264 mLooper->registerHandler(mHandler);
265}
266
Eric Laurent6d607012021-07-05 11:54:40 +0200267Spatializer::~Spatializer() {
268 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200269 if (mLooper != nullptr) {
270 mLooper->stop();
271 mLooper->unregisterHandler(mHandler->id());
272 }
273 mLooper.clear();
274 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200275}
276
Eric Laurent2be8b292021-08-23 09:44:33 -0700277status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
278 ALOGV("%s", __func__);
279
280 std::vector<bool> supportsHeadTracking;
281 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
282 &supportsHeadTracking);
283 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700284 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700285 return status;
286 }
287 mSupportsHeadTracking = supportsHeadTracking[0];
288
Andy Hung119dbdb2022-05-11 19:20:13 -0700289 std::vector<media::SpatializationLevel> spatializationLevels;
290 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
291 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700292 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700293 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700294 return status;
295 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700296 bool noneLevelFound = false;
297 bool activeLevelFound = false;
298 for (const auto spatializationLevel : spatializationLevels) {
299 if (!aidl_utils::isValidEnum(spatializationLevel)) {
300 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
301 continue;
302 }
303 if (spatializationLevel == media::SpatializationLevel::NONE) {
304 noneLevelFound = true;
305 } else {
306 activeLevelFound = true;
307 }
308 // we don't detect duplicates.
309 mLevels.emplace_back(spatializationLevel);
310 }
311 if (!noneLevelFound || !activeLevelFound) {
312 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
313 " and another valid level", __func__);
314 return BAD_VALUE;
315 }
316
317 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700318 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700319 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700320 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700321 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700322 return status;
323 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000324
Andy Hung119dbdb2022-05-11 19:20:13 -0700325 for (const auto spatializationMode : spatializationModes) {
326 if (!aidl_utils::isValidEnum(spatializationMode)) {
327 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
328 continue;
329 }
330 // we don't detect duplicates.
331 mSpatializationModes.emplace_back(spatializationMode);
332 }
333 if (mSpatializationModes.empty()) {
334 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
335 return BAD_VALUE;
336 }
337
338 std::vector<audio_channel_mask_t> channelMasks;
339 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
340 &channelMasks);
341 if (status != NO_ERROR) {
342 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
343 return status;
344 }
345 for (const auto channelMask : channelMasks) {
346 if (!audio_is_channel_mask_spatialized(channelMask)) {
347 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
348 continue;
349 }
350 // we don't detect duplicates.
351 mChannelMasks.emplace_back(channelMask);
352 }
353 if (mChannelMasks.empty()) {
354 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
355 return BAD_VALUE;
356 }
Andy Hunga461a002022-05-17 10:36:02 -0700357
358 // Currently we expose only RELATIVE_WORLD.
359 // This is a limitation of the head tracking library based on a UX choice.
360 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
361 if (mSupportsHeadTracking) {
362 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
363 }
364 mediametrics::LogItem(mMetricsId)
365 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
366 .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)getMaxChannelMask(mChannelMasks))
367 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
368 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
369 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
370 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
371 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700372 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700373}
374
375/** Gets the channel mask, sampling rate and format set for the spatializer input. */
376audio_config_base_t Spatializer::getAudioInConfig() const {
377 std::lock_guard lock(mLock);
378 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
379 // For now use highest supported channel count
Andy Hunga461a002022-05-17 10:36:02 -0700380 config.channel_mask = getMaxChannelMask(mChannelMasks);
Eric Laurent2be8b292021-08-23 09:44:33 -0700381 return config;
382}
383
Eric Laurent6d607012021-07-05 11:54:40 +0200384status_t Spatializer::registerCallback(
385 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700386 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200387 if (callback == nullptr) {
388 return BAD_VALUE;
389 }
390
Eric Laurentb57604f2022-08-31 16:07:50 +0200391 if (mSpatializerCallback != nullptr) {
392 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
393 ALOGW("%s: Registering callback %p again",
394 __func__, mSpatializerCallback.get());
395 return NO_ERROR;
396 }
397 ALOGE("%s: Already one client registered with callback %p",
398 __func__, mSpatializerCallback.get());
399 return INVALID_OPERATION;
400 }
401
Eric Laurent6d607012021-07-05 11:54:40 +0200402 sp<IBinder> binder = IInterface::asBinder(callback);
403 status_t status = binder->linkToDeath(this);
404 if (status == NO_ERROR) {
405 mSpatializerCallback = callback;
406 }
407 ALOGV("%s status %d", __func__, status);
408 return status;
409}
410
411// IBinder::DeathRecipient
412void Spatializer::binderDied(__unused const wp<IBinder> &who) {
413 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700414 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200415 mLevel = SpatializationLevel::NONE;
416 mSpatializerCallback.clear();
417 }
418 ALOGV("%s", __func__);
419 mPolicyCallback->onCheckSpatializer();
420}
421
422// ISpatializer
423Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
424 ALOGV("%s", __func__);
425 if (levels == nullptr) {
426 return binderStatusFromStatusT(BAD_VALUE);
427 }
Andy Hunga461a002022-05-17 10:36:02 -0700428 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700429 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200430 return Status::ok();
431}
432
Eric Laurent2be8b292021-08-23 09:44:33 -0700433Status Spatializer::setLevel(SpatializationLevel level) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000434 ALOGV("%s level %s", __func__, media::toString(level).c_str());
435 mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
Eric Laurent6d607012021-07-05 11:54:40 +0200436 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700437 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200438 return binderStatusFromStatusT(BAD_VALUE);
439 }
440 sp<media::INativeSpatializerCallback> callback;
441 bool levelChanged = false;
442 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700443 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200444 levelChanged = mLevel != level;
445 mLevel = level;
446 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700447
448 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200449 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700450 }
Eric Laurent9249d342022-03-18 11:55:56 +0100451 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200452 }
453
454 if (levelChanged) {
455 mPolicyCallback->onCheckSpatializer();
456 if (callback != nullptr) {
457 callback->onLevelChanged(level);
458 }
459 }
460 return Status::ok();
461}
462
Eric Laurent2be8b292021-08-23 09:44:33 -0700463Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200464 if (level == nullptr) {
465 return binderStatusFromStatusT(BAD_VALUE);
466 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700467 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200468 *level = mLevel;
469 ALOGV("%s level %d", __func__, (int)*level);
470 return Status::ok();
471}
472
Eric Laurentc87402b2021-09-17 16:49:42 +0200473Status Spatializer::isHeadTrackingSupported(bool *supports) {
474 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
475 if (supports == nullptr) {
476 return binderStatusFromStatusT(BAD_VALUE);
477 }
478 std::lock_guard lock(mLock);
479 *supports = mSupportsHeadTracking;
480 return Status::ok();
481}
482
Eric Laurent6d607012021-07-05 11:54:40 +0200483Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700484 std::vector<SpatializerHeadTrackingMode>* modes) {
485 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200486 ALOGV("%s", __func__);
487 if (modes == nullptr) {
488 return binderStatusFromStatusT(BAD_VALUE);
489 }
Andy Hunga461a002022-05-17 10:36:02 -0700490 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200491 return Status::ok();
492}
493
Eric Laurent2be8b292021-08-23 09:44:33 -0700494Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000495 ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700496
497 if (!mSupportsHeadTracking) {
498 return binderStatusFromStatusT(INVALID_OPERATION);
499 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000500 mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700501 std::lock_guard lock(mLock);
502 switch (mode) {
503 case SpatializerHeadTrackingMode::OTHER:
504 return binderStatusFromStatusT(BAD_VALUE);
505 case SpatializerHeadTrackingMode::DISABLED:
506 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
507 break;
508 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
509 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
510 break;
511 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
512 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
513 break;
514 }
515
Eric Laurent11094172022-04-05 18:27:42 +0200516 checkPoseController_l();
517 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700518
519 return Status::ok();
520}
521
522Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200523 if (mode == nullptr) {
524 return binderStatusFromStatusT(BAD_VALUE);
525 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700526 std::lock_guard lock(mLock);
527 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200528 ALOGV("%s mode %d", __func__, (int)*mode);
529 return Status::ok();
530}
531
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700532Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200533 if (!mSupportsHeadTracking) {
534 return binderStatusFromStatusT(INVALID_OPERATION);
535 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700536 std::lock_guard lock(mLock);
537 if (mPoseController != nullptr) {
538 mPoseController->recenter();
539 }
Eric Laurent6d607012021-07-05 11:54:40 +0200540 return Status::ok();
541}
542
543Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200544 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200545 if (!mSupportsHeadTracking) {
546 return binderStatusFromStatusT(INVALID_OPERATION);
547 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700548 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
549 if (!maybePose.has_value()) {
550 ALOGW("Invalid screenToStage vector.");
551 return binderStatusFromStatusT(BAD_VALUE);
552 }
553 std::lock_guard lock(mLock);
554 if (mPoseController != nullptr) {
Shunkai Yao7de40382022-08-25 00:44:04 +0000555 mLocalLog.log("%s with screenToStage %s", __func__, toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700556 mPoseController->setScreenToStagePose(maybePose.value());
557 }
Eric Laurent6d607012021-07-05 11:54:40 +0200558 return Status::ok();
559}
560
561Status Spatializer::release() {
562 ALOGV("%s", __func__);
563 bool levelChanged = false;
564 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700565 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200566 if (mSpatializerCallback == nullptr) {
567 return binderStatusFromStatusT(INVALID_OPERATION);
568 }
569
570 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
571 binder->unlinkToDeath(this);
572 mSpatializerCallback.clear();
573
574 levelChanged = mLevel != SpatializationLevel::NONE;
575 mLevel = SpatializationLevel::NONE;
576 }
577
578 if (levelChanged) {
579 mPolicyCallback->onCheckSpatializer();
580 }
581 return Status::ok();
582}
583
Eric Laurent2be8b292021-08-23 09:44:33 -0700584Status Spatializer::setHeadSensor(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 (mHeadSensor != 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 mHeadSensor = sensorHandle;
593 checkPoseController_l();
594 checkSensorsState_l();
595 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700596 return Status::ok();
597}
598
599Status Spatializer::setScreenSensor(int sensorHandle) {
600 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200601 if (!mSupportsHeadTracking) {
602 return binderStatusFromStatusT(INVALID_OPERATION);
603 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700604 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700605 if (mScreenSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000606 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700607 mScreenSensor = sensorHandle;
608 // TODO: consider a new method setHeadAndScreenSensor()
609 // because we generally set both at the same time.
610 // This will avoid duplicated work and recentering.
611 checkSensorsState_l();
612 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700613 return Status::ok();
614}
615
616Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
617 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200618 if (!mSupportsHeadTracking) {
619 return binderStatusFromStatusT(INVALID_OPERATION);
620 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700621 std::lock_guard lock(mLock);
622 mDisplayOrientation = physicalToLogicalAngle;
Shunkai Yao5a251df2022-07-22 18:42:27 +0000623 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700624 if (mPoseController != nullptr) {
625 mPoseController->setDisplayOrientation(mDisplayOrientation);
626 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200627 if (mEngine != nullptr) {
628 setEffectParameter_l(
629 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
630 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700631 return Status::ok();
632}
633
634Status Spatializer::setHingeAngle(float hingeAngle) {
635 std::lock_guard lock(mLock);
636 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
637 if (mEngine != nullptr) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000638 mLocalLog.log("%s with %f", __func__, hingeAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700639 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
640 }
641 return Status::ok();
642}
643
644Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
645 ALOGV("%s", __func__);
646 if (modes == nullptr) {
647 return binderStatusFromStatusT(BAD_VALUE);
648 }
649 *modes = mSpatializationModes;
650 return Status::ok();
651}
652
Eric Laurent67816e32021-09-16 15:18:40 +0200653Status Spatializer::registerHeadTrackingCallback(
654 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
655 ALOGV("%s callback %p", __func__, callback.get());
656 std::lock_guard lock(mLock);
657 if (!mSupportsHeadTracking) {
658 return binderStatusFromStatusT(INVALID_OPERATION);
659 }
660 mHeadTrackingCallback = callback;
661 return Status::ok();
662}
663
Eric Laurentc87402b2021-09-17 16:49:42 +0200664Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
665 ALOGV("%s key %d", __func__, key);
666 std::lock_guard lock(mLock);
667 status_t status = INVALID_OPERATION;
668 if (mEngine != nullptr) {
669 status = setEffectParameter_l(key, value);
670 }
671 return binderStatusFromStatusT(status);
672}
673
674Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700675 ALOGV("%s key %d value size %d", __func__, key,
676 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200677 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700678 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200679 }
680 std::lock_guard lock(mLock);
681 status_t status = INVALID_OPERATION;
682 if (mEngine != nullptr) {
683 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
684 status = getEffectParameter_l(key, value);
685 }
686 return binderStatusFromStatusT(status);
687}
688
689Status Spatializer::getOutput(int *output) {
690 ALOGV("%s", __func__);
691 if (output == nullptr) {
692 binderStatusFromStatusT(BAD_VALUE);
693 }
694 std::lock_guard lock(mLock);
695 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
696 ALOGV("%s got output %d", __func__, *output);
697 return Status::ok();
698}
699
Eric Laurent2be8b292021-08-23 09:44:33 -0700700// SpatializerPoseController::Listener
701void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
702 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200703 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
704 "onHeadToStagePose() called with no head tracking support!");
705
Eric Laurent2be8b292021-08-23 09:44:33 -0700706 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200707 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
708 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200709 sp<AMessage> msg =
710 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
711 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
712 msg->setFloat(sHeadPoseKeys[i], vec[i]);
713 }
714 msg->post();
715}
716
717void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
718 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200719 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700720 {
721 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200722 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700723 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200724 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Shunkai Yao7de40382022-08-25 00:44:04 +0000725 mPoseRecorder.record(headToStage);
726 mPoseDurableRecorder.record(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700727 }
728 }
729
730 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200731 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700732 }
733}
734
735void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao51379452022-08-30 03:14:50 +0000736 std::string modeStr = media::toString(mode);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000737 ALOGV("%s(%s)", __func__, modeStr.c_str());
Shunkai Yao51379452022-08-30 03:14:50 +0000738 sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200739 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
740 msg->post();
741}
742
743void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
744 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200745 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700746 SpatializerHeadTrackingMode spatializerMode;
747 {
748 std::lock_guard lock(mLock);
749 if (!mSupportsHeadTracking) {
750 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
751 } else {
752 switch (mode) {
753 case HeadTrackingMode::STATIC:
754 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
755 break;
756 case HeadTrackingMode::WORLD_RELATIVE:
757 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
758 break;
759 case HeadTrackingMode::SCREEN_RELATIVE:
760 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
761 break;
762 default:
763 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
764 }
765 }
766 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200767 if (mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200768 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
769 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
770 }
Eric Laurent67816e32021-09-16 15:18:40 +0200771 callback = mHeadTrackingCallback;
Shunkai Yao51379452022-08-30 03:14:50 +0000772 mLocalLog.log("%s: %s, spatializerMode %s", __func__, media::toString(mode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +0000773 media::toString(spatializerMode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700774 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200775 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700776 callback->onHeadTrackingModeChanged(spatializerMode);
777 }
778}
779
Eric Laurent15903592022-02-24 20:44:36 +0100780status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200781 bool outputChanged = false;
782 sp<media::INativeSpatializerCallback> callback;
783
Eric Laurent2be8b292021-08-23 09:44:33 -0700784 {
785 std::lock_guard lock(mLock);
786 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000787 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
788 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700789 if (mOutput != AUDIO_IO_HANDLE_NONE) {
790 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
791 // remove FX instance
792 mEngine->setEnabled(false);
793 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100794 mPoseController.reset();
Eric Laurentb387fb42022-05-03 18:19:35 +0200795 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700796 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200797
Eric Laurent2be8b292021-08-23 09:44:33 -0700798 // create FX instance on output
799 AttributionSourceState attributionSource = AttributionSourceState();
800 mEngine = new AudioEffect(attributionSource);
801 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
802 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
803 false /* probe */, true /* notifyFramesProcessed */);
804 status_t status = mEngine->initCheck();
805 ALOGV("%s mEngine create status %d", __func__, (int)status);
806 if (status != NO_ERROR) {
807 return status;
808 }
809
Eric Laurent4a872862021-10-11 17:06:47 +0200810 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700811 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200812 mNumActiveTracks = numActiveTracks;
Eric Laurentb387fb42022-05-03 18:19:35 +0200813 AudioSystem::addSupportedLatencyModesCallback(this);
814
815 std::vector<audio_latency_mode_t> latencyModes;
816 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
817 if (status == OK) {
818 mSupportedLatencyModes = latencyModes;
819 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700820
Eric Laurent11094172022-04-05 18:27:42 +0200821 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200822 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200823 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100824 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200825 }
Eric Laurent4a872862021-10-11 17:06:47 +0200826 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200827 }
Eric Laurent4a872862021-10-11 17:06:47 +0200828
829 if (outputChanged && callback != nullptr) {
830 callback->onOutputChanged(output);
831 }
832
Eric Laurent6d607012021-07-05 11:54:40 +0200833 return NO_ERROR;
834}
835
836audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700837 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200838 sp<media::INativeSpatializerCallback> callback;
839
840 {
841 std::lock_guard lock(mLock);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000842 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +0200843 ALOGV("%s mOutput %d", __func__, (int)mOutput);
844 if (mOutput == AUDIO_IO_HANDLE_NONE) {
845 return output;
846 }
847 // remove FX instance
848 mEngine->setEnabled(false);
849 mEngine.clear();
Eric Laurentb387fb42022-05-03 18:19:35 +0200850 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200851 output = mOutput;
852 mOutput = AUDIO_IO_HANDLE_NONE;
853 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200854 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200855 }
Eric Laurent4a872862021-10-11 17:06:47 +0200856
857 if (callback != nullptr) {
858 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
859 }
Eric Laurent6d607012021-07-05 11:54:40 +0200860 return output;
861}
862
Eric Laurentb387fb42022-05-03 18:19:35 +0200863void Spatializer::onSupportedLatencyModesChanged(
864 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200865 ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
866 sp<AMessage> msg =
867 new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
868 msg->setObject(EngineCallbackHandler::kLatencyModesKey,
869 sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
870 msg->post();
871}
872
873void Spatializer::onSupportedLatencyModesChangedMsg(
874 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
Eric Laurentb387fb42022-05-03 18:19:35 +0200875 std::lock_guard lock(mLock);
Eric Laurentdf2ece42022-07-20 13:49:47 +0200876 ALOGV("%s output %d mOutput %d num modes %zu",
877 __func__, (int)output, (int)mOutput, modes.size());
Eric Laurentb387fb42022-05-03 18:19:35 +0200878 if (output == mOutput) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200879 mSupportedLatencyModes = std::move(modes);
Eric Laurentb387fb42022-05-03 18:19:35 +0200880 checkSensorsState_l();
881 }
882}
883
Eric Laurent15903592022-02-24 20:44:36 +0100884void Spatializer::updateActiveTracks(size_t numActiveTracks) {
885 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200886 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000887 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200888 mNumActiveTracks = numActiveTracks;
889 checkEngineState_l();
890 checkSensorsState_l();
891 }
Eric Laurent15903592022-02-24 20:44:36 +0100892}
893
Eric Laurent9249d342022-03-18 11:55:56 +0100894void Spatializer::checkSensorsState_l() {
Eric Laurentb387fb42022-05-03 18:19:35 +0200895 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
896 bool lowLatencySupported = mSupportedLatencyModes.empty()
897 || (std::find(mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
898 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end());
Eric Laurentd8913a42022-07-08 13:35:46 +0200899 if (mSupportsHeadTracking && mPoseController != nullptr) {
900 if (lowLatencySupported && mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent15903592022-02-24 20:44:36 +0100901 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
902 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
903 mPoseController->setHeadSensor(mHeadSensor);
Eric Laurent9249d342022-03-18 11:55:56 +0100904 mPoseController->setScreenSensor(mScreenSensor);
Eric Laurentb387fb42022-05-03 18:19:35 +0200905 requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent15903592022-02-24 20:44:36 +0100906 } else {
907 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent9249d342022-03-18 11:55:56 +0100908 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
Eric Laurent15903592022-02-24 20:44:36 +0100909 }
910 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200911 if (mOutput != AUDIO_IO_HANDLE_NONE) {
912 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
913 }
Eric Laurent15903592022-02-24 20:44:36 +0100914}
915
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200916void Spatializer::checkEngineState_l() {
917 if (mEngine != nullptr) {
918 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
919 mEngine->setEnabled(true);
920 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
921 std::vector<SpatializationLevel>{mLevel});
922 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
923 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
924 } else {
925 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
926 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
927 mEngine->setEnabled(false);
928 }
929 }
930}
931
Eric Laurent11094172022-04-05 18:27:42 +0200932void Spatializer::checkPoseController_l() {
933 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
934 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
935
936 if (isControllerNeeded && mPoseController == nullptr) {
937 mPoseController = std::make_shared<SpatializerPoseController>(
938 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +0200939 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +0200940 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
941 "%s could not allocate pose controller", __func__);
942 mPoseController->setDisplayOrientation(mDisplayOrientation);
943 } else if (!isControllerNeeded && mPoseController != nullptr) {
944 mPoseController.reset();
945 }
946 if (mPoseController != nullptr) {
947 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
948 }
949}
950
Eric Laurent2be8b292021-08-23 09:44:33 -0700951void Spatializer::calculateHeadPose() {
952 ALOGV("%s", __func__);
953 std::lock_guard lock(mLock);
954 if (mPoseController != nullptr) {
955 mPoseController->calculateAsync();
956 }
957}
Eric Laurent6d607012021-07-05 11:54:40 +0200958
Eric Laurent2be8b292021-08-23 09:44:33 -0700959void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +0200960 if (user == nullptr) {
961 return;
962 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700963 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +0200964 switch (event) {
965 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -0700966 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +0100967 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200968 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -0700969 } break;
Eric Laurent6d607012021-07-05 11:54:40 +0200970 default:
Eric Laurent9249d342022-03-18 11:55:56 +0100971 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +0200972 break;
973 }
974}
975
Eric Laurent8a4259f2021-09-14 16:04:00 +0200976void Spatializer::postFramesProcessedMsg(int frames) {
977 sp<AMessage> msg =
978 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
979 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
980 msg->post();
981}
982
Shunkai Yao5a251df2022-07-22 18:42:27 +0000983std::string Spatializer::toString(unsigned level) const {
984 std::string prefixSpace;
985 prefixSpace.append(level, ' ');
986 std::string ss = prefixSpace + "Spatializer:\n";
987 bool needUnlock = false;
988
989 prefixSpace += ' ';
990 if (!mLock.try_lock()) {
991 // dumpsys even try_lock failed, information dump can be useful although may not accurate
992 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
993 } else {
994 needUnlock = true;
995 }
996
997 // Spatializer class information.
998 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
999 ss.append(prefixSpace).append("Supported levels: [");
1000 for (auto& level : mLevels) {
1001 base::StringAppendF(&ss, " %s", media::toString(level).c_str());
1002 }
1003 base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
1004
1005 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1006 for (auto& mode : mHeadTrackingModes) {
1007 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1008 }
1009 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
Shunkai Yao51379452022-08-30 03:14:50 +00001010 media::toString(mDesiredHeadTrackingMode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +00001011 media::toString(mActualHeadTrackingMode).c_str());
1012
1013 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1014 for (auto& mode : mSpatializationModes) {
1015 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1016 }
1017 ss += "]\n";
1018
1019 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1020 for (auto& mask : mChannelMasks) {
1021 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1022 }
1023 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1024 mSupportsHeadTracking ? "true" : "false");
1025 // 2. Settings (Output, tracks)
1026 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1027 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1028
1029 // 3. Sensors, Effect information.
1030 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1031 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1032 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1033 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1034 mDisplayOrientation);
1035
1036 ss.append(prefixSpace + "CommandLog:\n");
1037 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001038
1039 // PostController dump.
1040 if (mPoseController != nullptr) {
1041 ss += mPoseController->toString(level + 1);
Shunkai Yao7de40382022-08-25 00:44:04 +00001042 ss.append(prefixSpace +
1043 "Sensor data format - [rx, ry, rz, vx, vy, vz] (units-degree, "
1044 "r-transform, v-angular velocity, x-pitch, y-roll, z-yaw):\n");
Shunkai Yao51379452022-08-30 03:14:50 +00001045 ss.append(prefixSpace + " PerMinuteHistory:\n");
Shunkai Yao7de40382022-08-25 00:44:04 +00001046 ss += mPoseDurableRecorder.toString(level + 1);
Shunkai Yao51379452022-08-30 03:14:50 +00001047 ss.append(prefixSpace + " PerSecondHistory:\n");
Shunkai Yao7de40382022-08-25 00:44:04 +00001048 ss += mPoseRecorder.toString(level + 1);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001049 } else {
1050 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1051 }
1052
1053 if (needUnlock) {
1054 mLock.unlock();
1055 }
1056 return ss;
1057}
1058
Eric Laurent6d607012021-07-05 11:54:40 +02001059} // namespace android