blob: 9ee9037e2fb94282e6b03921aa19638bdf5980e3 [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>
Andy Hung2a390db2023-01-30 11:58:44 -080036#include <media/QuaternionUtil.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020037#include <media/ShmemCompat.h>
Andy Hungb725c692022-12-14 14:25:49 -080038#include <mediautils/SchedulingPolicyService.h>
Eric Laurent6d607012021-07-05 11:54:40 +020039#include <mediautils/ServiceUtilities.h>
40#include <utils/Thread.h>
41
42#include "Spatializer.h"
43
44namespace android {
45
46using aidl_utils::statusTFromBinderStatus;
47using aidl_utils::binderStatusFromStatusT;
48using android::content::AttributionSourceState;
49using binder::Status;
Eric Laurent2be8b292021-08-23 09:44:33 -070050using media::HeadTrackingMode;
51using media::Pose3f;
Eric Laurent6d607012021-07-05 11:54:40 +020052using media::SpatializationLevel;
Eric Laurent2be8b292021-08-23 09:44:33 -070053using media::SpatializationMode;
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070054using media::SpatializerHeadTrackingMode;
Eric Laurent2be8b292021-08-23 09:44:33 -070055using media::SensorPoseProvider;
56
Eric Laurent2be8b292021-08-23 09:44:33 -070057using namespace std::chrono_literals;
Eric Laurent6d607012021-07-05 11:54:40 +020058
59#define VALUE_OR_RETURN_BINDER_STATUS(x) \
60 ({ auto _tmp = (x); \
61 if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
62 std::move(_tmp.value()); })
63
Andy Hung0e3205d2022-08-29 14:14:58 -070064static audio_channel_mask_t getMaxChannelMask(
65 const std::vector<audio_channel_mask_t>& masks, size_t channelLimit = SIZE_MAX) {
Andy Hunga461a002022-05-17 10:36:02 -070066 uint32_t maxCount = 0;
67 audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
68 for (auto mask : masks) {
69 const size_t count = audio_channel_count_from_out_mask(mask);
Andy Hung0e3205d2022-08-29 14:14:58 -070070 if (count > channelLimit) continue; // ignore masks greater than channelLimit
Andy Hunga461a002022-05-17 10:36:02 -070071 if (count > maxCount) {
72 maxMask = mask;
73 maxCount = count;
74 }
75 }
76 return maxMask;
77}
78
Andy Hung2a390db2023-01-30 11:58:44 -080079static std::vector<float> recordFromTranslationRotationVector(
80 const std::vector<float>& trVector) {
81 auto headToStageOpt = Pose3f::fromVector(trVector);
82 if (!headToStageOpt) return {};
83
84 const auto stageToHead = headToStageOpt.value().inverse();
85 const auto stageToHeadTranslation = stageToHead.translation();
Andy Hung82a4eab2023-01-30 11:58:44 -080086 constexpr float RAD_TO_DEGREE = 180.f / M_PI;
87 std::vector<float> record{
Andy Hung2a390db2023-01-30 11:58:44 -080088 stageToHeadTranslation[0], stageToHeadTranslation[1], stageToHeadTranslation[2],
89 0.f, 0.f, 0.f};
90 media::quaternionToAngles(stageToHead.rotation(), &record[3], &record[4], &record[5]);
91 record[3] *= RAD_TO_DEGREE;
92 record[4] *= RAD_TO_DEGREE;
93 record[5] *= RAD_TO_DEGREE;
Andy Hung82a4eab2023-01-30 11:58:44 -080094 return record;
95}
96
Eric Laurent6d607012021-07-05 11:54:40 +020097// ---------------------------------------------------------------------------
98
Eric Laurent8a4259f2021-09-14 16:04:00 +020099class Spatializer::EngineCallbackHandler : public AHandler {
100public:
101 EngineCallbackHandler(wp<Spatializer> spatializer)
102 : mSpatializer(spatializer) {
103 }
104
105 enum {
106 // Device state callbacks
107 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
108 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
109 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
Eric Laurentdf2ece42022-07-20 13:49:47 +0200110 kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
Eric Laurent8a4259f2021-09-14 16:04:00 +0200111 };
112 static constexpr const char *kNumFramesKey = "numFrames";
113 static constexpr const char *kModeKey = "mode";
114 static constexpr const char *kTranslation0Key = "translation0";
115 static constexpr const char *kTranslation1Key = "translation1";
116 static constexpr const char *kTranslation2Key = "translation2";
117 static constexpr const char *kRotation0Key = "rotation0";
118 static constexpr const char *kRotation1Key = "rotation1";
119 static constexpr const char *kRotation2Key = "rotation2";
Eric Laurentdf2ece42022-07-20 13:49:47 +0200120 static constexpr const char *kLatencyModesKey = "latencyModes";
121
122 class LatencyModes : public RefBase {
123 public:
124 LatencyModes(audio_io_handle_t output,
125 const std::vector<audio_latency_mode_t>& latencyModes)
126 : mOutput(output), mLatencyModes(latencyModes) {}
127 ~LatencyModes() = default;
128
129 audio_io_handle_t mOutput;
130 std::vector<audio_latency_mode_t> mLatencyModes;
131 };
Eric Laurent8a4259f2021-09-14 16:04:00 +0200132
133 void onMessageReceived(const sp<AMessage> &msg) override {
Andy Hungb725c692022-12-14 14:25:49 -0800134 // No ALooper method to get the tid so update
135 // Spatializer priority on the first message received.
136 std::call_once(mPrioritySetFlag, [](){
137 const pid_t pid = getpid();
138 const pid_t tid = gettid();
139 (void)requestSpatializerPriority(pid, tid);
140 });
141
Eric Laurentdf2ece42022-07-20 13:49:47 +0200142 sp<Spatializer> spatializer = mSpatializer.promote();
143 if (spatializer == nullptr) {
144 ALOGW("%s: Cannot promote spatializer", __func__);
145 return;
146 }
Eric Laurent8a4259f2021-09-14 16:04:00 +0200147 switch (msg->what()) {
148 case kWhatOnFramesProcessed: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200149 int numFrames;
150 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
151 ALOGE("%s: Cannot find num frames!", __func__);
152 return;
153 }
154 if (numFrames > 0) {
155 spatializer->calculateHeadPose();
156 }
157 } break;
158 case kWhatOnHeadToStagePose: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200159 std::vector<float> headToStage(sHeadPoseKeys.size());
160 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
161 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
162 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
163 return;
164 }
165 }
166 spatializer->onHeadToStagePoseMsg(headToStage);
167 } break;
168 case kWhatOnActualModeChange: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200169 int mode;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200170 if (!msg->findInt32(kModeKey, &mode)) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200171 ALOGE("%s: Cannot find actualMode!", __func__);
172 return;
173 }
174 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
175 } break;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200176
177 case kWhatOnLatencyModesChanged: {
178 sp<RefBase> object;
179 if (!msg->findObject(kLatencyModesKey, &object)) {
180 ALOGE("%s: Cannot find latency modes!", __func__);
181 return;
182 }
183 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
184 spatializer->onSupportedLatencyModesChangedMsg(
185 latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
186 } break;
187
Eric Laurent8a4259f2021-09-14 16:04:00 +0200188 default:
189 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
190 }
191 }
192private:
193 wp<Spatializer> mSpatializer;
Andy Hungb725c692022-12-14 14:25:49 -0800194 std::once_flag mPrioritySetFlag;
Eric Laurent8a4259f2021-09-14 16:04:00 +0200195};
196
197const std::vector<const char *> Spatializer::sHeadPoseKeys = {
198 Spatializer::EngineCallbackHandler::kTranslation0Key,
199 Spatializer::EngineCallbackHandler::kTranslation1Key,
200 Spatializer::EngineCallbackHandler::kTranslation2Key,
201 Spatializer::EngineCallbackHandler::kRotation0Key,
202 Spatializer::EngineCallbackHandler::kRotation1Key,
203 Spatializer::EngineCallbackHandler::kRotation2Key,
204};
205
206// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200207sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
208 sp<Spatializer> spatializer;
209
210 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
211 if (effectsFactoryHal == nullptr) {
212 ALOGW("%s failed to create effect factory interface", __func__);
213 return spatializer;
214 }
215
216 std::vector<effect_descriptor_t> descriptors;
217 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200218 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200219 if (status != NO_ERROR) {
220 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
221 return spatializer;
222 }
223 ALOG_ASSERT(!descriptors.empty(),
224 "%s getDescriptors() returned no error but empty list", __func__);
225
Shunkai Yao5a251df2022-07-22 18:42:27 +0000226 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200227 sp<EffectHalInterface> effect;
228 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
229 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000230 ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
231 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200232
233 if (status == NO_ERROR && effect != nullptr) {
234 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700235 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
236 spatializer.clear();
Andy Hung0e3205d2022-08-29 14:14:58 -0700237 ALOGW("%s loadEngine error: %d effect Id %" PRId64,
238 __func__, status, effect ? effect->effectId() : 0);
239 } else {
240 spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
241 effect ? effect->effectId() : 0);
Eric Laurent2be8b292021-08-23 09:44:33 -0700242 }
Eric Laurent6d607012021-07-05 11:54:40 +0200243 }
244
245 return spatializer;
246}
247
Eric Laurent2be8b292021-08-23 09:44:33 -0700248Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
249 : mEngineDescriptor(engineDescriptor),
250 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200251 ALOGV("%s", __func__);
Andy Hung393de3a2022-12-06 16:33:20 -0800252 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent6d607012021-07-05 11:54:40 +0200253}
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,
Andy Hung898a39f2022-11-07 20:09:20 -0800261 PRIORITY_URGENT_AUDIO);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200262
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
Andy Hung4442d042022-08-17 17:27:32 -0700277static std::string channelMaskVectorToString(
278 const std::vector<audio_channel_mask_t>& masks) {
279 std::stringstream ss;
280 for (const auto &mask : masks) {
281 if (ss.tellp() != 0) ss << "|";
282 ss << mask;
283 }
284 return ss.str();
285}
286
Eric Laurent2be8b292021-08-23 09:44:33 -0700287status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
288 ALOGV("%s", __func__);
289
290 std::vector<bool> supportsHeadTracking;
291 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
292 &supportsHeadTracking);
293 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700294 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700295 return status;
296 }
297 mSupportsHeadTracking = supportsHeadTracking[0];
298
Andy Hung119dbdb2022-05-11 19:20:13 -0700299 std::vector<media::SpatializationLevel> spatializationLevels;
300 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
301 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700302 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700303 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700304 return status;
305 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700306 bool noneLevelFound = false;
307 bool activeLevelFound = false;
308 for (const auto spatializationLevel : spatializationLevels) {
309 if (!aidl_utils::isValidEnum(spatializationLevel)) {
310 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
311 continue;
312 }
313 if (spatializationLevel == media::SpatializationLevel::NONE) {
314 noneLevelFound = true;
315 } else {
316 activeLevelFound = true;
317 }
318 // we don't detect duplicates.
319 mLevels.emplace_back(spatializationLevel);
320 }
321 if (!noneLevelFound || !activeLevelFound) {
322 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
323 " and another valid level", __func__);
324 return BAD_VALUE;
325 }
326
327 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700328 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700329 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700330 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700331 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700332 return status;
333 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000334
Andy Hung119dbdb2022-05-11 19:20:13 -0700335 for (const auto spatializationMode : spatializationModes) {
336 if (!aidl_utils::isValidEnum(spatializationMode)) {
337 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
338 continue;
339 }
340 // we don't detect duplicates.
341 mSpatializationModes.emplace_back(spatializationMode);
342 }
343 if (mSpatializationModes.empty()) {
344 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
345 return BAD_VALUE;
346 }
347
348 std::vector<audio_channel_mask_t> channelMasks;
349 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
350 &channelMasks);
351 if (status != NO_ERROR) {
352 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
353 return status;
354 }
355 for (const auto channelMask : channelMasks) {
356 if (!audio_is_channel_mask_spatialized(channelMask)) {
357 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
358 continue;
359 }
360 // we don't detect duplicates.
361 mChannelMasks.emplace_back(channelMask);
362 }
363 if (mChannelMasks.empty()) {
364 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
365 return BAD_VALUE;
366 }
Andy Hunga461a002022-05-17 10:36:02 -0700367
368 // Currently we expose only RELATIVE_WORLD.
369 // This is a limitation of the head tracking library based on a UX choice.
370 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
371 if (mSupportsHeadTracking) {
372 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
373 }
374 mediametrics::LogItem(mMetricsId)
375 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
Andy Hung4442d042022-08-17 17:27:32 -0700376 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
Andy Hunga461a002022-05-17 10:36:02 -0700377 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
378 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
379 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
380 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
381 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700382 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700383}
384
Andy Hung757bc812022-09-13 18:53:06 -0700385/* static */
386void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
387 mediametrics::LogItem(kDefaultMetricsId)
388 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
389 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
390 .set(AMEDIAMETRICS_PROP_LEVELS, "")
391 .set(AMEDIAMETRICS_PROP_MODES, "")
392 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
393 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
394 .record();
395}
396
Eric Laurent2be8b292021-08-23 09:44:33 -0700397/** Gets the channel mask, sampling rate and format set for the spatializer input. */
398audio_config_base_t Spatializer::getAudioInConfig() const {
399 std::lock_guard lock(mLock);
400 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
401 // For now use highest supported channel count
Andy Hung0e3205d2022-08-29 14:14:58 -0700402 config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
Eric Laurent2be8b292021-08-23 09:44:33 -0700403 return config;
404}
405
Eric Laurent6d607012021-07-05 11:54:40 +0200406status_t Spatializer::registerCallback(
407 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700408 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200409 if (callback == nullptr) {
410 return BAD_VALUE;
411 }
412
Eric Laurentb57604f2022-08-31 16:07:50 +0200413 if (mSpatializerCallback != nullptr) {
414 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
415 ALOGW("%s: Registering callback %p again",
416 __func__, mSpatializerCallback.get());
417 return NO_ERROR;
418 }
419 ALOGE("%s: Already one client registered with callback %p",
420 __func__, mSpatializerCallback.get());
421 return INVALID_OPERATION;
422 }
423
Eric Laurent6d607012021-07-05 11:54:40 +0200424 sp<IBinder> binder = IInterface::asBinder(callback);
425 status_t status = binder->linkToDeath(this);
426 if (status == NO_ERROR) {
427 mSpatializerCallback = callback;
428 }
429 ALOGV("%s status %d", __func__, status);
430 return status;
431}
432
433// IBinder::DeathRecipient
434void Spatializer::binderDied(__unused const wp<IBinder> &who) {
435 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700436 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200437 mLevel = SpatializationLevel::NONE;
438 mSpatializerCallback.clear();
439 }
440 ALOGV("%s", __func__);
441 mPolicyCallback->onCheckSpatializer();
442}
443
444// ISpatializer
445Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
446 ALOGV("%s", __func__);
447 if (levels == nullptr) {
448 return binderStatusFromStatusT(BAD_VALUE);
449 }
Andy Hunga461a002022-05-17 10:36:02 -0700450 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700451 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200452 return Status::ok();
453}
454
Eric Laurent2be8b292021-08-23 09:44:33 -0700455Status Spatializer::setLevel(SpatializationLevel level) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000456 ALOGV("%s level %s", __func__, media::toString(level).c_str());
457 mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
Eric Laurent6d607012021-07-05 11:54:40 +0200458 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700459 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200460 return binderStatusFromStatusT(BAD_VALUE);
461 }
462 sp<media::INativeSpatializerCallback> callback;
463 bool levelChanged = false;
464 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700465 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200466 levelChanged = mLevel != level;
467 mLevel = level;
468 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700469
470 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200471 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700472 }
Eric Laurent9249d342022-03-18 11:55:56 +0100473 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200474 }
475
476 if (levelChanged) {
477 mPolicyCallback->onCheckSpatializer();
478 if (callback != nullptr) {
479 callback->onLevelChanged(level);
480 }
481 }
482 return Status::ok();
483}
484
Eric Laurent2be8b292021-08-23 09:44:33 -0700485Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200486 if (level == nullptr) {
487 return binderStatusFromStatusT(BAD_VALUE);
488 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700489 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200490 *level = mLevel;
491 ALOGV("%s level %d", __func__, (int)*level);
492 return Status::ok();
493}
494
Eric Laurentc87402b2021-09-17 16:49:42 +0200495Status Spatializer::isHeadTrackingSupported(bool *supports) {
496 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
497 if (supports == nullptr) {
498 return binderStatusFromStatusT(BAD_VALUE);
499 }
500 std::lock_guard lock(mLock);
501 *supports = mSupportsHeadTracking;
502 return Status::ok();
503}
504
Eric Laurent6d607012021-07-05 11:54:40 +0200505Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700506 std::vector<SpatializerHeadTrackingMode>* modes) {
507 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200508 ALOGV("%s", __func__);
509 if (modes == nullptr) {
510 return binderStatusFromStatusT(BAD_VALUE);
511 }
Andy Hunga461a002022-05-17 10:36:02 -0700512 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200513 return Status::ok();
514}
515
Eric Laurent2be8b292021-08-23 09:44:33 -0700516Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000517 ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700518
519 if (!mSupportsHeadTracking) {
520 return binderStatusFromStatusT(INVALID_OPERATION);
521 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000522 mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700523 std::lock_guard lock(mLock);
524 switch (mode) {
525 case SpatializerHeadTrackingMode::OTHER:
526 return binderStatusFromStatusT(BAD_VALUE);
527 case SpatializerHeadTrackingMode::DISABLED:
528 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
529 break;
530 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
531 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
532 break;
533 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
534 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
535 break;
536 }
537
Eric Laurent11094172022-04-05 18:27:42 +0200538 checkPoseController_l();
539 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700540
541 return Status::ok();
542}
543
544Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200545 if (mode == nullptr) {
546 return binderStatusFromStatusT(BAD_VALUE);
547 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700548 std::lock_guard lock(mLock);
549 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200550 ALOGV("%s mode %d", __func__, (int)*mode);
551 return Status::ok();
552}
553
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700554Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200555 if (!mSupportsHeadTracking) {
556 return binderStatusFromStatusT(INVALID_OPERATION);
557 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700558 std::lock_guard lock(mLock);
559 if (mPoseController != nullptr) {
560 mPoseController->recenter();
561 }
Eric Laurent6d607012021-07-05 11:54:40 +0200562 return Status::ok();
563}
564
565Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200566 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200567 if (!mSupportsHeadTracking) {
568 return binderStatusFromStatusT(INVALID_OPERATION);
569 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700570 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
571 if (!maybePose.has_value()) {
572 ALOGW("Invalid screenToStage vector.");
573 return binderStatusFromStatusT(BAD_VALUE);
574 }
575 std::lock_guard lock(mLock);
576 if (mPoseController != nullptr) {
Andy Hung82a4eab2023-01-30 11:58:44 -0800577 mLocalLog.log("%s with screenToStage %s", __func__,
578 media::VectorRecorder::toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700579 mPoseController->setScreenToStagePose(maybePose.value());
580 }
Eric Laurent6d607012021-07-05 11:54:40 +0200581 return Status::ok();
582}
583
584Status Spatializer::release() {
585 ALOGV("%s", __func__);
586 bool levelChanged = false;
587 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700588 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200589 if (mSpatializerCallback == nullptr) {
590 return binderStatusFromStatusT(INVALID_OPERATION);
591 }
592
593 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
594 binder->unlinkToDeath(this);
595 mSpatializerCallback.clear();
596
597 levelChanged = mLevel != SpatializationLevel::NONE;
598 mLevel = SpatializationLevel::NONE;
599 }
600
601 if (levelChanged) {
602 mPolicyCallback->onCheckSpatializer();
603 }
604 return Status::ok();
605}
606
Eric Laurent2be8b292021-08-23 09:44:33 -0700607Status Spatializer::setHeadSensor(int sensorHandle) {
608 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200609 if (!mSupportsHeadTracking) {
610 return binderStatusFromStatusT(INVALID_OPERATION);
611 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700612 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700613 if (mHeadSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000614 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700615 mHeadSensor = sensorHandle;
616 checkPoseController_l();
617 checkSensorsState_l();
618 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700619 return Status::ok();
620}
621
622Status Spatializer::setScreenSensor(int sensorHandle) {
623 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200624 if (!mSupportsHeadTracking) {
625 return binderStatusFromStatusT(INVALID_OPERATION);
626 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700627 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700628 if (mScreenSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000629 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700630 mScreenSensor = sensorHandle;
631 // TODO: consider a new method setHeadAndScreenSensor()
632 // because we generally set both at the same time.
633 // This will avoid duplicated work and recentering.
634 checkSensorsState_l();
635 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700636 return Status::ok();
637}
638
639Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
640 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200641 if (!mSupportsHeadTracking) {
642 return binderStatusFromStatusT(INVALID_OPERATION);
643 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700644 std::lock_guard lock(mLock);
645 mDisplayOrientation = physicalToLogicalAngle;
Shunkai Yao5a251df2022-07-22 18:42:27 +0000646 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700647 if (mPoseController != nullptr) {
648 mPoseController->setDisplayOrientation(mDisplayOrientation);
649 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200650 if (mEngine != nullptr) {
651 setEffectParameter_l(
652 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
653 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700654 return Status::ok();
655}
656
657Status Spatializer::setHingeAngle(float hingeAngle) {
658 std::lock_guard lock(mLock);
659 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
660 if (mEngine != nullptr) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000661 mLocalLog.log("%s with %f", __func__, hingeAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700662 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
663 }
664 return Status::ok();
665}
666
667Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
668 ALOGV("%s", __func__);
669 if (modes == nullptr) {
670 return binderStatusFromStatusT(BAD_VALUE);
671 }
672 *modes = mSpatializationModes;
673 return Status::ok();
674}
675
Eric Laurent67816e32021-09-16 15:18:40 +0200676Status Spatializer::registerHeadTrackingCallback(
677 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
678 ALOGV("%s callback %p", __func__, callback.get());
679 std::lock_guard lock(mLock);
680 if (!mSupportsHeadTracking) {
681 return binderStatusFromStatusT(INVALID_OPERATION);
682 }
683 mHeadTrackingCallback = callback;
684 return Status::ok();
685}
686
Eric Laurentc87402b2021-09-17 16:49:42 +0200687Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
688 ALOGV("%s key %d", __func__, key);
689 std::lock_guard lock(mLock);
690 status_t status = INVALID_OPERATION;
691 if (mEngine != nullptr) {
692 status = setEffectParameter_l(key, value);
693 }
694 return binderStatusFromStatusT(status);
695}
696
697Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700698 ALOGV("%s key %d value size %d", __func__, key,
699 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200700 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700701 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200702 }
703 std::lock_guard lock(mLock);
704 status_t status = INVALID_OPERATION;
705 if (mEngine != nullptr) {
706 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
707 status = getEffectParameter_l(key, value);
708 }
709 return binderStatusFromStatusT(status);
710}
711
712Status Spatializer::getOutput(int *output) {
713 ALOGV("%s", __func__);
714 if (output == nullptr) {
715 binderStatusFromStatusT(BAD_VALUE);
716 }
717 std::lock_guard lock(mLock);
718 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
719 ALOGV("%s got output %d", __func__, *output);
720 return Status::ok();
721}
722
Eric Laurent2be8b292021-08-23 09:44:33 -0700723// SpatializerPoseController::Listener
724void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
725 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200726 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
727 "onHeadToStagePose() called with no head tracking support!");
728
Eric Laurent2be8b292021-08-23 09:44:33 -0700729 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200730 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
731 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200732 sp<AMessage> msg =
733 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
734 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
735 msg->setFloat(sHeadPoseKeys[i], vec[i]);
736 }
737 msg->post();
738}
739
Eric Laurent3c48ad92022-10-21 11:28:32 +0200740void Spatializer::resetEngineHeadPose_l() {
741 ALOGV("%s mEngine %p", __func__, mEngine.get());
742 if (mEngine == nullptr) {
743 return;
744 }
745 const std::vector<float> headToStage(6, 0.0);
746 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
747 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
748 std::vector<SpatializerHeadTrackingMode>{SpatializerHeadTrackingMode::DISABLED});
749}
750
Eric Laurent8a4259f2021-09-14 16:04:00 +0200751void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
752 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200753 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700754 {
755 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200756 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700757 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200758 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Andy Hung2a390db2023-01-30 11:58:44 -0800759 const auto record = recordFromTranslationRotationVector(headToStage);
760 mPoseRecorder.record(record);
761 mPoseDurableRecorder.record(record);
Eric Laurent2be8b292021-08-23 09:44:33 -0700762 }
763 }
764
765 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200766 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700767 }
768}
769
770void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao51379452022-08-30 03:14:50 +0000771 std::string modeStr = media::toString(mode);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000772 ALOGV("%s(%s)", __func__, modeStr.c_str());
Shunkai Yao51379452022-08-30 03:14:50 +0000773 sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200774 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
775 msg->post();
776}
777
778void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
779 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200780 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700781 SpatializerHeadTrackingMode spatializerMode;
782 {
783 std::lock_guard lock(mLock);
784 if (!mSupportsHeadTracking) {
785 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
786 } else {
787 switch (mode) {
788 case HeadTrackingMode::STATIC:
789 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
790 break;
791 case HeadTrackingMode::WORLD_RELATIVE:
792 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
793 break;
794 case HeadTrackingMode::SCREEN_RELATIVE:
795 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
796 break;
797 default:
798 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
799 }
800 }
801 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200802 if (mEngine != nullptr) {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200803 if (spatializerMode == SpatializerHeadTrackingMode::DISABLED) {
804 resetEngineHeadPose_l();
805 } else {
806 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
807 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
808 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200809 }
Eric Laurent67816e32021-09-16 15:18:40 +0200810 callback = mHeadTrackingCallback;
Andy Hung79ccfda2023-01-30 11:58:44 -0800811 mLocalLog.log("%s: updating mode to %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700812 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200813 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700814 callback->onHeadTrackingModeChanged(spatializerMode);
815 }
816}
817
Eric Laurent15903592022-02-24 20:44:36 +0100818status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200819 bool outputChanged = false;
820 sp<media::INativeSpatializerCallback> callback;
821
Eric Laurent2be8b292021-08-23 09:44:33 -0700822 {
823 std::lock_guard lock(mLock);
824 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000825 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
826 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700827 if (mOutput != AUDIO_IO_HANDLE_NONE) {
828 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
829 // remove FX instance
830 mEngine->setEnabled(false);
831 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100832 mPoseController.reset();
Eric Laurentb387fb42022-05-03 18:19:35 +0200833 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700834 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200835
Eric Laurent2be8b292021-08-23 09:44:33 -0700836 // create FX instance on output
837 AttributionSourceState attributionSource = AttributionSourceState();
838 mEngine = new AudioEffect(attributionSource);
839 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
840 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
841 false /* probe */, true /* notifyFramesProcessed */);
842 status_t status = mEngine->initCheck();
843 ALOGV("%s mEngine create status %d", __func__, (int)status);
844 if (status != NO_ERROR) {
845 return status;
846 }
847
Eric Laurent4a872862021-10-11 17:06:47 +0200848 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700849 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200850 mNumActiveTracks = numActiveTracks;
Eric Laurentb387fb42022-05-03 18:19:35 +0200851 AudioSystem::addSupportedLatencyModesCallback(this);
852
853 std::vector<audio_latency_mode_t> latencyModes;
854 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
855 if (status == OK) {
856 mSupportedLatencyModes = latencyModes;
857 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700858
Eric Laurent11094172022-04-05 18:27:42 +0200859 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200860 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200861 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100862 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200863 }
Eric Laurent4a872862021-10-11 17:06:47 +0200864 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200865 }
Eric Laurent4a872862021-10-11 17:06:47 +0200866
867 if (outputChanged && callback != nullptr) {
868 callback->onOutputChanged(output);
869 }
870
Eric Laurent6d607012021-07-05 11:54:40 +0200871 return NO_ERROR;
872}
873
874audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700875 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200876 sp<media::INativeSpatializerCallback> callback;
877
878 {
879 std::lock_guard lock(mLock);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000880 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +0200881 ALOGV("%s mOutput %d", __func__, (int)mOutput);
882 if (mOutput == AUDIO_IO_HANDLE_NONE) {
883 return output;
884 }
885 // remove FX instance
886 mEngine->setEnabled(false);
887 mEngine.clear();
Eric Laurentb387fb42022-05-03 18:19:35 +0200888 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200889 output = mOutput;
890 mOutput = AUDIO_IO_HANDLE_NONE;
891 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200892 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200893 }
Eric Laurent4a872862021-10-11 17:06:47 +0200894
895 if (callback != nullptr) {
896 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
897 }
Eric Laurent6d607012021-07-05 11:54:40 +0200898 return output;
899}
900
Eric Laurentb387fb42022-05-03 18:19:35 +0200901void Spatializer::onSupportedLatencyModesChanged(
902 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200903 ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
904 sp<AMessage> msg =
905 new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
906 msg->setObject(EngineCallbackHandler::kLatencyModesKey,
907 sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
908 msg->post();
909}
910
911void Spatializer::onSupportedLatencyModesChangedMsg(
912 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
Eric Laurentb387fb42022-05-03 18:19:35 +0200913 std::lock_guard lock(mLock);
Eric Laurentdf2ece42022-07-20 13:49:47 +0200914 ALOGV("%s output %d mOutput %d num modes %zu",
915 __func__, (int)output, (int)mOutput, modes.size());
Eric Laurentb387fb42022-05-03 18:19:35 +0200916 if (output == mOutput) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200917 mSupportedLatencyModes = std::move(modes);
Eric Laurentb387fb42022-05-03 18:19:35 +0200918 checkSensorsState_l();
919 }
920}
921
Eric Laurent15903592022-02-24 20:44:36 +0100922void Spatializer::updateActiveTracks(size_t numActiveTracks) {
923 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200924 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000925 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200926 mNumActiveTracks = numActiveTracks;
927 checkEngineState_l();
928 checkSensorsState_l();
929 }
Eric Laurent15903592022-02-24 20:44:36 +0100930}
931
Eric Laurent9249d342022-03-18 11:55:56 +0100932void Spatializer::checkSensorsState_l() {
Eric Laurentb387fb42022-05-03 18:19:35 +0200933 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
Andy Hungc0896c72022-10-21 17:30:30 -0700934 const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
935 const bool supportsLowLatencyMode = supportsSetLatencyMode && std::find(
936 mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
937 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
Eric Laurent3c48ad92022-10-21 11:28:32 +0200938 if (mSupportsHeadTracking) {
939 if (mPoseController != nullptr) {
Andy Hungc0896c72022-10-21 17:30:30 -0700940 // TODO(b/253297301, b/255433067) reenable low latency condition check
941 // for Head Tracking after Bluetooth HAL supports it correctly.
942 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent3c48ad92022-10-21 11:28:32 +0200943 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
944 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
945 if (mEngine != nullptr) {
946 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
947 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
948 }
949 mPoseController->setHeadSensor(mHeadSensor);
950 mPoseController->setScreenSensor(mScreenSensor);
Andy Hungc0896c72022-10-21 17:30:30 -0700951 if (supportsLowLatencyMode) requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent3c48ad92022-10-21 11:28:32 +0200952 } else {
953 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
954 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
955 resetEngineHeadPose_l();
956 }
Eric Laurent15903592022-02-24 20:44:36 +0100957 } else {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200958 resetEngineHeadPose_l();
Eric Laurent15903592022-02-24 20:44:36 +0100959 }
960 }
Andy Hungc0896c72022-10-21 17:30:30 -0700961 if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
Andy Hung5d8618d2022-11-17 17:21:45 -0800962 const status_t status =
963 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
964 ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
965 __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
Eric Laurentb387fb42022-05-03 18:19:35 +0200966 }
Eric Laurent15903592022-02-24 20:44:36 +0100967}
968
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200969void Spatializer::checkEngineState_l() {
970 if (mEngine != nullptr) {
971 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
972 mEngine->setEnabled(true);
973 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
974 std::vector<SpatializationLevel>{mLevel});
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200975 } else {
976 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
977 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
978 mEngine->setEnabled(false);
979 }
980 }
981}
982
Eric Laurent11094172022-04-05 18:27:42 +0200983void Spatializer::checkPoseController_l() {
984 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
985 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
986
987 if (isControllerNeeded && mPoseController == nullptr) {
988 mPoseController = std::make_shared<SpatializerPoseController>(
989 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +0200990 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +0200991 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
992 "%s could not allocate pose controller", __func__);
993 mPoseController->setDisplayOrientation(mDisplayOrientation);
994 } else if (!isControllerNeeded && mPoseController != nullptr) {
995 mPoseController.reset();
Eric Laurent3c48ad92022-10-21 11:28:32 +0200996 resetEngineHeadPose_l();
Eric Laurent11094172022-04-05 18:27:42 +0200997 }
998 if (mPoseController != nullptr) {
999 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
1000 }
1001}
1002
Eric Laurent2be8b292021-08-23 09:44:33 -07001003void Spatializer::calculateHeadPose() {
1004 ALOGV("%s", __func__);
1005 std::lock_guard lock(mLock);
1006 if (mPoseController != nullptr) {
1007 mPoseController->calculateAsync();
1008 }
1009}
Eric Laurent6d607012021-07-05 11:54:40 +02001010
Eric Laurent2be8b292021-08-23 09:44:33 -07001011void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +02001012 if (user == nullptr) {
1013 return;
1014 }
Eric Laurent2be8b292021-08-23 09:44:33 -07001015 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +02001016 switch (event) {
1017 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -07001018 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +01001019 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +02001020 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -07001021 } break;
Eric Laurent6d607012021-07-05 11:54:40 +02001022 default:
Eric Laurent9249d342022-03-18 11:55:56 +01001023 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +02001024 break;
1025 }
1026}
1027
Eric Laurent8a4259f2021-09-14 16:04:00 +02001028void Spatializer::postFramesProcessedMsg(int frames) {
1029 sp<AMessage> msg =
1030 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
1031 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
1032 msg->post();
1033}
1034
Shunkai Yao5a251df2022-07-22 18:42:27 +00001035std::string Spatializer::toString(unsigned level) const {
Andy Hung2a390db2023-01-30 11:58:44 -08001036 std::string prefixSpace(level, ' ');
Shunkai Yao5a251df2022-07-22 18:42:27 +00001037 std::string ss = prefixSpace + "Spatializer:\n";
1038 bool needUnlock = false;
1039
1040 prefixSpace += ' ';
1041 if (!mLock.try_lock()) {
1042 // dumpsys even try_lock failed, information dump can be useful although may not accurate
1043 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1044 } else {
1045 needUnlock = true;
1046 }
1047
1048 // Spatializer class information.
1049 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1050 ss.append(prefixSpace).append("Supported levels: [");
1051 for (auto& level : mLevels) {
1052 base::StringAppendF(&ss, " %s", media::toString(level).c_str());
1053 }
1054 base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
1055
1056 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1057 for (auto& mode : mHeadTrackingModes) {
1058 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1059 }
1060 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
Shunkai Yao51379452022-08-30 03:14:50 +00001061 media::toString(mDesiredHeadTrackingMode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +00001062 media::toString(mActualHeadTrackingMode).c_str());
1063
1064 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1065 for (auto& mode : mSpatializationModes) {
1066 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1067 }
1068 ss += "]\n";
1069
1070 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1071 for (auto& mask : mChannelMasks) {
1072 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1073 }
1074 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1075 mSupportsHeadTracking ? "true" : "false");
1076 // 2. Settings (Output, tracks)
1077 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1078 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1079
1080 // 3. Sensors, Effect information.
1081 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1082 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1083 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1084 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1085 mDisplayOrientation);
1086
1087 ss.append(prefixSpace + "CommandLog:\n");
1088 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001089
1090 // PostController dump.
1091 if (mPoseController != nullptr) {
Andy Hung2a390db2023-01-30 11:58:44 -08001092 ss.append(mPoseController->toString(level + 1))
1093 .append(prefixSpace)
Andy Hung9bcf4252023-02-27 13:36:23 -08001094 .append("Pose (active stage-to-head) [tx, ty, tz : pitch, roll, yaw]:\n")
Andy Hung2a390db2023-01-30 11:58:44 -08001095 .append(prefixSpace)
1096 .append(" PerMinuteHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -08001097 .append(mPoseDurableRecorder.toString(level + 3))
Andy Hung2a390db2023-01-30 11:58:44 -08001098 .append(prefixSpace)
1099 .append(" PerSecondHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -08001100 .append(mPoseRecorder.toString(level + 3));
Shunkai Yao5a251df2022-07-22 18:42:27 +00001101 } else {
1102 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1103 }
1104
1105 if (needUnlock) {
1106 mLock.unlock();
1107 }
1108 return ss;
1109}
1110
Eric Laurent6d607012021-07-05 11:54:40 +02001111} // namespace android