blob: 5db82f7acb0429ce0adcfda4363a68ba4a93f2b3 [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
Andy Hungcd6c1062023-03-09 20:45:36 -080023#include <algorithm>
Shunkai Yao5a251df2022-07-22 18:42:27 +000024#include <inttypes.h>
Eric Laurent6d607012021-07-05 11:54:40 +020025#include <limits.h>
26#include <stdint.h>
27#include <sys/types.h>
28
29#include <android/content/AttributionSourceState.h>
30#include <audio_utils/fixedfft.h>
31#include <cutils/bitops.h>
Eric Laurent2be8b292021-08-23 09:44:33 -070032#include <hardware/sensors.h>
Eric Laurent6d607012021-07-05 11:54:40 +020033#include <media/audiohal/EffectsFactoryHalInterface.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020034#include <media/stagefright/foundation/AHandler.h>
35#include <media/stagefright/foundation/AMessage.h>
Andy Hunga461a002022-05-17 10:36:02 -070036#include <media/MediaMetricsItem.h>
Andy Hung2a390db2023-01-30 11:58:44 -080037#include <media/QuaternionUtil.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020038#include <media/ShmemCompat.h>
Andy Hungb725c692022-12-14 14:25:49 -080039#include <mediautils/SchedulingPolicyService.h>
Eric Laurent6d607012021-07-05 11:54:40 +020040#include <mediautils/ServiceUtilities.h>
41#include <utils/Thread.h>
42
43#include "Spatializer.h"
44
45namespace android {
46
47using aidl_utils::statusTFromBinderStatus;
48using aidl_utils::binderStatusFromStatusT;
49using android::content::AttributionSourceState;
50using binder::Status;
Eric Laurent2be8b292021-08-23 09:44:33 -070051using media::HeadTrackingMode;
52using media::Pose3f;
Eric Laurent6d607012021-07-05 11:54:40 +020053using media::SpatializationLevel;
Eric Laurent2be8b292021-08-23 09:44:33 -070054using media::SpatializationMode;
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070055using media::SpatializerHeadTrackingMode;
Eric Laurent2be8b292021-08-23 09:44:33 -070056using media::SensorPoseProvider;
57
Eric Laurent2be8b292021-08-23 09:44:33 -070058using namespace std::chrono_literals;
Eric Laurent6d607012021-07-05 11:54:40 +020059
60#define VALUE_OR_RETURN_BINDER_STATUS(x) \
61 ({ auto _tmp = (x); \
62 if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
63 std::move(_tmp.value()); })
64
Andy Hung0e3205d2022-08-29 14:14:58 -070065static audio_channel_mask_t getMaxChannelMask(
66 const std::vector<audio_channel_mask_t>& masks, size_t channelLimit = SIZE_MAX) {
Andy Hunga461a002022-05-17 10:36:02 -070067 uint32_t maxCount = 0;
68 audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
69 for (auto mask : masks) {
70 const size_t count = audio_channel_count_from_out_mask(mask);
Andy Hung0e3205d2022-08-29 14:14:58 -070071 if (count > channelLimit) continue; // ignore masks greater than channelLimit
Andy Hunga461a002022-05-17 10:36:02 -070072 if (count > maxCount) {
73 maxMask = mask;
74 maxCount = count;
75 }
76 }
77 return maxMask;
78}
79
Andy Hung2a390db2023-01-30 11:58:44 -080080static std::vector<float> recordFromTranslationRotationVector(
81 const std::vector<float>& trVector) {
82 auto headToStageOpt = Pose3f::fromVector(trVector);
83 if (!headToStageOpt) return {};
84
85 const auto stageToHead = headToStageOpt.value().inverse();
86 const auto stageToHeadTranslation = stageToHead.translation();
Andy Hung82a4eab2023-01-30 11:58:44 -080087 constexpr float RAD_TO_DEGREE = 180.f / M_PI;
88 std::vector<float> record{
Andy Hung2a390db2023-01-30 11:58:44 -080089 stageToHeadTranslation[0], stageToHeadTranslation[1], stageToHeadTranslation[2],
90 0.f, 0.f, 0.f};
91 media::quaternionToAngles(stageToHead.rotation(), &record[3], &record[4], &record[5]);
92 record[3] *= RAD_TO_DEGREE;
93 record[4] *= RAD_TO_DEGREE;
94 record[5] *= RAD_TO_DEGREE;
Andy Hung82a4eab2023-01-30 11:58:44 -080095 return record;
96}
97
Andy Hungcd6c1062023-03-09 20:45:36 -080098template<typename T>
99static constexpr const T& safe_clamp(const T& value, const T& low, const T& high) {
100 if constexpr (std::is_floating_point_v<T>) {
101 return value != value /* constexpr isnan */
102 ? low : std::clamp(value, low, high);
103 } else /* constexpr */ {
104 return std::clamp(value, low, high);
105 }
106}
107
Eric Laurent6d607012021-07-05 11:54:40 +0200108// ---------------------------------------------------------------------------
109
Eric Laurent8a4259f2021-09-14 16:04:00 +0200110class Spatializer::EngineCallbackHandler : public AHandler {
111public:
112 EngineCallbackHandler(wp<Spatializer> spatializer)
113 : mSpatializer(spatializer) {
114 }
115
116 enum {
117 // Device state callbacks
118 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
119 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
120 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
Eric Laurentdf2ece42022-07-20 13:49:47 +0200121 kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
Eric Laurent8a4259f2021-09-14 16:04:00 +0200122 };
123 static constexpr const char *kNumFramesKey = "numFrames";
124 static constexpr const char *kModeKey = "mode";
125 static constexpr const char *kTranslation0Key = "translation0";
126 static constexpr const char *kTranslation1Key = "translation1";
127 static constexpr const char *kTranslation2Key = "translation2";
128 static constexpr const char *kRotation0Key = "rotation0";
129 static constexpr const char *kRotation1Key = "rotation1";
130 static constexpr const char *kRotation2Key = "rotation2";
Eric Laurentdf2ece42022-07-20 13:49:47 +0200131 static constexpr const char *kLatencyModesKey = "latencyModes";
132
133 class LatencyModes : public RefBase {
134 public:
135 LatencyModes(audio_io_handle_t output,
136 const std::vector<audio_latency_mode_t>& latencyModes)
137 : mOutput(output), mLatencyModes(latencyModes) {}
138 ~LatencyModes() = default;
139
140 audio_io_handle_t mOutput;
141 std::vector<audio_latency_mode_t> mLatencyModes;
142 };
Eric Laurent8a4259f2021-09-14 16:04:00 +0200143
144 void onMessageReceived(const sp<AMessage> &msg) override {
Andy Hungb725c692022-12-14 14:25:49 -0800145 // No ALooper method to get the tid so update
146 // Spatializer priority on the first message received.
147 std::call_once(mPrioritySetFlag, [](){
148 const pid_t pid = getpid();
149 const pid_t tid = gettid();
150 (void)requestSpatializerPriority(pid, tid);
151 });
152
Eric Laurentdf2ece42022-07-20 13:49:47 +0200153 sp<Spatializer> spatializer = mSpatializer.promote();
154 if (spatializer == nullptr) {
155 ALOGW("%s: Cannot promote spatializer", __func__);
156 return;
157 }
Eric Laurent8a4259f2021-09-14 16:04:00 +0200158 switch (msg->what()) {
159 case kWhatOnFramesProcessed: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200160 int numFrames;
161 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
162 ALOGE("%s: Cannot find num frames!", __func__);
163 return;
164 }
165 if (numFrames > 0) {
166 spatializer->calculateHeadPose();
167 }
168 } break;
169 case kWhatOnHeadToStagePose: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200170 std::vector<float> headToStage(sHeadPoseKeys.size());
171 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
172 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
173 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
174 return;
175 }
176 }
177 spatializer->onHeadToStagePoseMsg(headToStage);
178 } break;
179 case kWhatOnActualModeChange: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200180 int mode;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200181 if (!msg->findInt32(kModeKey, &mode)) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200182 ALOGE("%s: Cannot find actualMode!", __func__);
183 return;
184 }
185 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
186 } break;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200187
188 case kWhatOnLatencyModesChanged: {
189 sp<RefBase> object;
190 if (!msg->findObject(kLatencyModesKey, &object)) {
191 ALOGE("%s: Cannot find latency modes!", __func__);
192 return;
193 }
194 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
195 spatializer->onSupportedLatencyModesChangedMsg(
196 latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
197 } break;
198
Eric Laurent8a4259f2021-09-14 16:04:00 +0200199 default:
200 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
201 }
202 }
203private:
204 wp<Spatializer> mSpatializer;
Andy Hungb725c692022-12-14 14:25:49 -0800205 std::once_flag mPrioritySetFlag;
Eric Laurent8a4259f2021-09-14 16:04:00 +0200206};
207
208const std::vector<const char *> Spatializer::sHeadPoseKeys = {
209 Spatializer::EngineCallbackHandler::kTranslation0Key,
210 Spatializer::EngineCallbackHandler::kTranslation1Key,
211 Spatializer::EngineCallbackHandler::kTranslation2Key,
212 Spatializer::EngineCallbackHandler::kRotation0Key,
213 Spatializer::EngineCallbackHandler::kRotation1Key,
214 Spatializer::EngineCallbackHandler::kRotation2Key,
215};
216
217// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200218sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
219 sp<Spatializer> spatializer;
220
221 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
222 if (effectsFactoryHal == nullptr) {
223 ALOGW("%s failed to create effect factory interface", __func__);
224 return spatializer;
225 }
226
227 std::vector<effect_descriptor_t> descriptors;
228 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200229 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200230 if (status != NO_ERROR) {
231 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
232 return spatializer;
233 }
234 ALOG_ASSERT(!descriptors.empty(),
235 "%s getDescriptors() returned no error but empty list", __func__);
236
Shunkai Yao5a251df2022-07-22 18:42:27 +0000237 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200238 sp<EffectHalInterface> effect;
239 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
240 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000241 ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
242 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200243
244 if (status == NO_ERROR && effect != nullptr) {
245 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700246 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
247 spatializer.clear();
Andy Hung0e3205d2022-08-29 14:14:58 -0700248 ALOGW("%s loadEngine error: %d effect Id %" PRId64,
249 __func__, status, effect ? effect->effectId() : 0);
250 } else {
251 spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
252 effect ? effect->effectId() : 0);
Eric Laurent2be8b292021-08-23 09:44:33 -0700253 }
Eric Laurent6d607012021-07-05 11:54:40 +0200254 }
255
256 return spatializer;
257}
258
Eric Laurent2be8b292021-08-23 09:44:33 -0700259Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
260 : mEngineDescriptor(engineDescriptor),
261 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200262 ALOGV("%s", __func__);
Andy Hung393de3a2022-12-06 16:33:20 -0800263 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent6d607012021-07-05 11:54:40 +0200264}
265
Eric Laurent8a4259f2021-09-14 16:04:00 +0200266void Spatializer::onFirstRef() {
267 mLooper = new ALooper;
268 mLooper->setName("Spatializer-looper");
269 mLooper->start(
270 /*runOnCallingThread*/false,
271 /*canCallJava*/ false,
Andy Hung898a39f2022-11-07 20:09:20 -0800272 PRIORITY_URGENT_AUDIO);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200273
274 mHandler = new EngineCallbackHandler(this);
275 mLooper->registerHandler(mHandler);
276}
277
Eric Laurent6d607012021-07-05 11:54:40 +0200278Spatializer::~Spatializer() {
279 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200280 if (mLooper != nullptr) {
281 mLooper->stop();
282 mLooper->unregisterHandler(mHandler->id());
283 }
284 mLooper.clear();
285 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200286}
287
Andy Hung4442d042022-08-17 17:27:32 -0700288static std::string channelMaskVectorToString(
289 const std::vector<audio_channel_mask_t>& masks) {
290 std::stringstream ss;
291 for (const auto &mask : masks) {
292 if (ss.tellp() != 0) ss << "|";
293 ss << mask;
294 }
295 return ss.str();
296}
297
Eric Laurent2be8b292021-08-23 09:44:33 -0700298status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
299 ALOGV("%s", __func__);
300
301 std::vector<bool> supportsHeadTracking;
302 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
303 &supportsHeadTracking);
304 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700305 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700306 return status;
307 }
308 mSupportsHeadTracking = supportsHeadTracking[0];
309
Andy Hung119dbdb2022-05-11 19:20:13 -0700310 std::vector<media::SpatializationLevel> spatializationLevels;
311 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
312 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700313 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700314 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700315 return status;
316 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700317 bool noneLevelFound = false;
318 bool activeLevelFound = false;
319 for (const auto spatializationLevel : spatializationLevels) {
320 if (!aidl_utils::isValidEnum(spatializationLevel)) {
321 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
322 continue;
323 }
324 if (spatializationLevel == media::SpatializationLevel::NONE) {
325 noneLevelFound = true;
326 } else {
327 activeLevelFound = true;
328 }
329 // we don't detect duplicates.
330 mLevels.emplace_back(spatializationLevel);
331 }
332 if (!noneLevelFound || !activeLevelFound) {
333 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
334 " and another valid level", __func__);
335 return BAD_VALUE;
336 }
337
338 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700339 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700340 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700341 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700342 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700343 return status;
344 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000345
Andy Hung119dbdb2022-05-11 19:20:13 -0700346 for (const auto spatializationMode : spatializationModes) {
347 if (!aidl_utils::isValidEnum(spatializationMode)) {
348 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
349 continue;
350 }
351 // we don't detect duplicates.
352 mSpatializationModes.emplace_back(spatializationMode);
353 }
354 if (mSpatializationModes.empty()) {
355 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
356 return BAD_VALUE;
357 }
358
359 std::vector<audio_channel_mask_t> channelMasks;
360 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
361 &channelMasks);
362 if (status != NO_ERROR) {
363 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
364 return status;
365 }
366 for (const auto channelMask : channelMasks) {
367 if (!audio_is_channel_mask_spatialized(channelMask)) {
368 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
369 continue;
370 }
371 // we don't detect duplicates.
372 mChannelMasks.emplace_back(channelMask);
373 }
374 if (mChannelMasks.empty()) {
375 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
376 return BAD_VALUE;
377 }
Andy Hunga461a002022-05-17 10:36:02 -0700378
379 // Currently we expose only RELATIVE_WORLD.
380 // This is a limitation of the head tracking library based on a UX choice.
381 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
382 if (mSupportsHeadTracking) {
383 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
384 }
385 mediametrics::LogItem(mMetricsId)
386 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
Andy Hung4442d042022-08-17 17:27:32 -0700387 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
Andy Hunga461a002022-05-17 10:36:02 -0700388 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
389 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
390 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
391 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
392 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700393 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700394}
395
Andy Hung757bc812022-09-13 18:53:06 -0700396/* static */
397void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
398 mediametrics::LogItem(kDefaultMetricsId)
399 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
400 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
401 .set(AMEDIAMETRICS_PROP_LEVELS, "")
402 .set(AMEDIAMETRICS_PROP_MODES, "")
403 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
404 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
405 .record();
406}
407
Eric Laurent2be8b292021-08-23 09:44:33 -0700408/** Gets the channel mask, sampling rate and format set for the spatializer input. */
409audio_config_base_t Spatializer::getAudioInConfig() const {
410 std::lock_guard lock(mLock);
411 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
412 // For now use highest supported channel count
Andy Hung0e3205d2022-08-29 14:14:58 -0700413 config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
Eric Laurent2be8b292021-08-23 09:44:33 -0700414 return config;
415}
416
Eric Laurent6d607012021-07-05 11:54:40 +0200417status_t Spatializer::registerCallback(
418 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700419 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200420 if (callback == nullptr) {
421 return BAD_VALUE;
422 }
423
Eric Laurentb57604f2022-08-31 16:07:50 +0200424 if (mSpatializerCallback != nullptr) {
425 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
426 ALOGW("%s: Registering callback %p again",
427 __func__, mSpatializerCallback.get());
428 return NO_ERROR;
429 }
430 ALOGE("%s: Already one client registered with callback %p",
431 __func__, mSpatializerCallback.get());
432 return INVALID_OPERATION;
433 }
434
Eric Laurent6d607012021-07-05 11:54:40 +0200435 sp<IBinder> binder = IInterface::asBinder(callback);
436 status_t status = binder->linkToDeath(this);
437 if (status == NO_ERROR) {
438 mSpatializerCallback = callback;
439 }
440 ALOGV("%s status %d", __func__, status);
441 return status;
442}
443
444// IBinder::DeathRecipient
445void Spatializer::binderDied(__unused const wp<IBinder> &who) {
446 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700447 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200448 mLevel = SpatializationLevel::NONE;
449 mSpatializerCallback.clear();
450 }
451 ALOGV("%s", __func__);
452 mPolicyCallback->onCheckSpatializer();
453}
454
455// ISpatializer
456Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
457 ALOGV("%s", __func__);
458 if (levels == nullptr) {
459 return binderStatusFromStatusT(BAD_VALUE);
460 }
Andy Hunga461a002022-05-17 10:36:02 -0700461 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700462 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200463 return Status::ok();
464}
465
Eric Laurent2be8b292021-08-23 09:44:33 -0700466Status Spatializer::setLevel(SpatializationLevel level) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000467 ALOGV("%s level %s", __func__, media::toString(level).c_str());
468 mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
Eric Laurent6d607012021-07-05 11:54:40 +0200469 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700470 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200471 return binderStatusFromStatusT(BAD_VALUE);
472 }
473 sp<media::INativeSpatializerCallback> callback;
474 bool levelChanged = false;
475 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700476 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200477 levelChanged = mLevel != level;
478 mLevel = level;
479 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700480
481 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200482 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700483 }
Eric Laurent9249d342022-03-18 11:55:56 +0100484 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200485 }
486
487 if (levelChanged) {
488 mPolicyCallback->onCheckSpatializer();
489 if (callback != nullptr) {
490 callback->onLevelChanged(level);
491 }
492 }
493 return Status::ok();
494}
495
Eric Laurent2be8b292021-08-23 09:44:33 -0700496Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200497 if (level == nullptr) {
498 return binderStatusFromStatusT(BAD_VALUE);
499 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700500 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200501 *level = mLevel;
502 ALOGV("%s level %d", __func__, (int)*level);
503 return Status::ok();
504}
505
Eric Laurentc87402b2021-09-17 16:49:42 +0200506Status Spatializer::isHeadTrackingSupported(bool *supports) {
507 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
508 if (supports == nullptr) {
509 return binderStatusFromStatusT(BAD_VALUE);
510 }
511 std::lock_guard lock(mLock);
512 *supports = mSupportsHeadTracking;
513 return Status::ok();
514}
515
Eric Laurent6d607012021-07-05 11:54:40 +0200516Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700517 std::vector<SpatializerHeadTrackingMode>* modes) {
518 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200519 ALOGV("%s", __func__);
520 if (modes == nullptr) {
521 return binderStatusFromStatusT(BAD_VALUE);
522 }
Andy Hunga461a002022-05-17 10:36:02 -0700523 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200524 return Status::ok();
525}
526
Eric Laurent2be8b292021-08-23 09:44:33 -0700527Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000528 ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700529
530 if (!mSupportsHeadTracking) {
531 return binderStatusFromStatusT(INVALID_OPERATION);
532 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000533 mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700534 std::lock_guard lock(mLock);
535 switch (mode) {
536 case SpatializerHeadTrackingMode::OTHER:
537 return binderStatusFromStatusT(BAD_VALUE);
538 case SpatializerHeadTrackingMode::DISABLED:
539 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
540 break;
541 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
542 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
543 break;
544 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
545 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
546 break;
547 }
548
Eric Laurent11094172022-04-05 18:27:42 +0200549 checkPoseController_l();
550 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700551
552 return Status::ok();
553}
554
555Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200556 if (mode == nullptr) {
557 return binderStatusFromStatusT(BAD_VALUE);
558 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700559 std::lock_guard lock(mLock);
560 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200561 ALOGV("%s mode %d", __func__, (int)*mode);
562 return Status::ok();
563}
564
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700565Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200566 if (!mSupportsHeadTracking) {
567 return binderStatusFromStatusT(INVALID_OPERATION);
568 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700569 std::lock_guard lock(mLock);
570 if (mPoseController != nullptr) {
571 mPoseController->recenter();
572 }
Eric Laurent6d607012021-07-05 11:54:40 +0200573 return Status::ok();
574}
575
576Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200577 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200578 if (!mSupportsHeadTracking) {
579 return binderStatusFromStatusT(INVALID_OPERATION);
580 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700581 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
582 if (!maybePose.has_value()) {
583 ALOGW("Invalid screenToStage vector.");
584 return binderStatusFromStatusT(BAD_VALUE);
585 }
586 std::lock_guard lock(mLock);
587 if (mPoseController != nullptr) {
Andy Hung82a4eab2023-01-30 11:58:44 -0800588 mLocalLog.log("%s with screenToStage %s", __func__,
589 media::VectorRecorder::toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700590 mPoseController->setScreenToStagePose(maybePose.value());
591 }
Eric Laurent6d607012021-07-05 11:54:40 +0200592 return Status::ok();
593}
594
595Status Spatializer::release() {
596 ALOGV("%s", __func__);
597 bool levelChanged = false;
598 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700599 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200600 if (mSpatializerCallback == nullptr) {
601 return binderStatusFromStatusT(INVALID_OPERATION);
602 }
603
604 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
605 binder->unlinkToDeath(this);
606 mSpatializerCallback.clear();
607
608 levelChanged = mLevel != SpatializationLevel::NONE;
609 mLevel = SpatializationLevel::NONE;
610 }
611
612 if (levelChanged) {
613 mPolicyCallback->onCheckSpatializer();
614 }
615 return Status::ok();
616}
617
Eric Laurent2be8b292021-08-23 09:44:33 -0700618Status Spatializer::setHeadSensor(int sensorHandle) {
619 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200620 if (!mSupportsHeadTracking) {
621 return binderStatusFromStatusT(INVALID_OPERATION);
622 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700623 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700624 if (mHeadSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000625 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700626 mHeadSensor = sensorHandle;
627 checkPoseController_l();
628 checkSensorsState_l();
629 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700630 return Status::ok();
631}
632
633Status Spatializer::setScreenSensor(int sensorHandle) {
634 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200635 if (!mSupportsHeadTracking) {
636 return binderStatusFromStatusT(INVALID_OPERATION);
637 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700638 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700639 if (mScreenSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000640 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700641 mScreenSensor = sensorHandle;
642 // TODO: consider a new method setHeadAndScreenSensor()
643 // because we generally set both at the same time.
644 // This will avoid duplicated work and recentering.
645 checkSensorsState_l();
646 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700647 return Status::ok();
648}
649
650Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
651 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000652 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Andy Hungcd6c1062023-03-09 20:45:36 -0800653 const float angle = safe_clamp(physicalToLogicalAngle, 0.f, (float)(2. * M_PI));
654 // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
655 ALOGI_IF(angle != physicalToLogicalAngle,
656 "%s: clamping %f to %f", __func__, physicalToLogicalAngle, angle);
657 std::lock_guard lock(mLock);
658 mDisplayOrientation = angle;
Eric Laurent2be8b292021-08-23 09:44:33 -0700659 if (mPoseController != nullptr) {
Andy Hungcd6c1062023-03-09 20:45:36 -0800660 // This turns on the rate-limiter.
661 mPoseController->setDisplayOrientation(angle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700662 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200663 if (mEngine != nullptr) {
664 setEffectParameter_l(
Andy Hungcd6c1062023-03-09 20:45:36 -0800665 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{angle});
Eric Laurent16ddaf42021-09-17 15:00:35 +0200666 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700667 return Status::ok();
668}
669
670Status Spatializer::setHingeAngle(float hingeAngle) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700671 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
Andy Hungcd6c1062023-03-09 20:45:36 -0800672 mLocalLog.log("%s with %f", __func__, hingeAngle);
673 const float angle = safe_clamp(hingeAngle, 0.f, (float)(2. * M_PI));
674 // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
675 ALOGI_IF(angle != hingeAngle,
676 "%s: clamping %f to %f", __func__, hingeAngle, angle);
677 std::lock_guard lock(mLock);
678 mHingeAngle = angle;
Eric Laurent2be8b292021-08-23 09:44:33 -0700679 if (mEngine != nullptr) {
Andy Hungcd6c1062023-03-09 20:45:36 -0800680 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{angle});
681 }
682 return Status::ok();
683}
684
685Status Spatializer::setFoldState(bool folded) {
686 ALOGV("%s foldState %d", __func__, (int)folded);
687 mLocalLog.log("%s with %d", __func__, (int)folded);
688 std::lock_guard lock(mLock);
689 mFoldedState = folded;
690 if (mEngine != nullptr) {
691 // we don't suppress multiple calls with the same folded state - that's
692 // done at the caller.
693 setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE, std::vector<uint8_t>{mFoldedState});
Eric Laurent2be8b292021-08-23 09:44:33 -0700694 }
695 return Status::ok();
696}
697
698Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
699 ALOGV("%s", __func__);
700 if (modes == nullptr) {
701 return binderStatusFromStatusT(BAD_VALUE);
702 }
703 *modes = mSpatializationModes;
704 return Status::ok();
705}
706
Eric Laurent67816e32021-09-16 15:18:40 +0200707Status Spatializer::registerHeadTrackingCallback(
708 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
709 ALOGV("%s callback %p", __func__, callback.get());
710 std::lock_guard lock(mLock);
711 if (!mSupportsHeadTracking) {
712 return binderStatusFromStatusT(INVALID_OPERATION);
713 }
714 mHeadTrackingCallback = callback;
715 return Status::ok();
716}
717
Eric Laurentc87402b2021-09-17 16:49:42 +0200718Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
719 ALOGV("%s key %d", __func__, key);
720 std::lock_guard lock(mLock);
721 status_t status = INVALID_OPERATION;
722 if (mEngine != nullptr) {
723 status = setEffectParameter_l(key, value);
724 }
725 return binderStatusFromStatusT(status);
726}
727
728Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700729 ALOGV("%s key %d value size %d", __func__, key,
730 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200731 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700732 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200733 }
734 std::lock_guard lock(mLock);
735 status_t status = INVALID_OPERATION;
736 if (mEngine != nullptr) {
737 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
738 status = getEffectParameter_l(key, value);
739 }
740 return binderStatusFromStatusT(status);
741}
742
743Status Spatializer::getOutput(int *output) {
744 ALOGV("%s", __func__);
745 if (output == nullptr) {
746 binderStatusFromStatusT(BAD_VALUE);
747 }
748 std::lock_guard lock(mLock);
749 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
750 ALOGV("%s got output %d", __func__, *output);
751 return Status::ok();
752}
753
Eric Laurent2be8b292021-08-23 09:44:33 -0700754// SpatializerPoseController::Listener
755void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
756 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200757 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
758 "onHeadToStagePose() called with no head tracking support!");
759
Eric Laurent2be8b292021-08-23 09:44:33 -0700760 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200761 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
762 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200763 sp<AMessage> msg =
764 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
765 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
766 msg->setFloat(sHeadPoseKeys[i], vec[i]);
767 }
768 msg->post();
769}
770
Eric Laurent3c48ad92022-10-21 11:28:32 +0200771void Spatializer::resetEngineHeadPose_l() {
772 ALOGV("%s mEngine %p", __func__, mEngine.get());
773 if (mEngine == nullptr) {
774 return;
775 }
776 const std::vector<float> headToStage(6, 0.0);
777 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
778 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
779 std::vector<SpatializerHeadTrackingMode>{SpatializerHeadTrackingMode::DISABLED});
780}
781
Eric Laurent8a4259f2021-09-14 16:04:00 +0200782void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
783 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200784 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700785 {
786 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200787 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700788 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200789 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Andy Hung2a390db2023-01-30 11:58:44 -0800790 const auto record = recordFromTranslationRotationVector(headToStage);
791 mPoseRecorder.record(record);
792 mPoseDurableRecorder.record(record);
Eric Laurent2be8b292021-08-23 09:44:33 -0700793 }
794 }
795
796 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200797 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700798 }
799}
800
801void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao51379452022-08-30 03:14:50 +0000802 std::string modeStr = media::toString(mode);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000803 ALOGV("%s(%s)", __func__, modeStr.c_str());
Shunkai Yao51379452022-08-30 03:14:50 +0000804 sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200805 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
806 msg->post();
807}
808
809void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
810 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200811 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700812 SpatializerHeadTrackingMode spatializerMode;
813 {
814 std::lock_guard lock(mLock);
815 if (!mSupportsHeadTracking) {
816 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
817 } else {
818 switch (mode) {
819 case HeadTrackingMode::STATIC:
820 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
821 break;
822 case HeadTrackingMode::WORLD_RELATIVE:
823 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
824 break;
825 case HeadTrackingMode::SCREEN_RELATIVE:
826 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
827 break;
828 default:
829 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
830 }
831 }
832 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200833 if (mEngine != nullptr) {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200834 if (spatializerMode == SpatializerHeadTrackingMode::DISABLED) {
835 resetEngineHeadPose_l();
836 } else {
837 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
838 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
839 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200840 }
Eric Laurent67816e32021-09-16 15:18:40 +0200841 callback = mHeadTrackingCallback;
Andy Hung79ccfda2023-01-30 11:58:44 -0800842 mLocalLog.log("%s: updating mode to %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700843 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200844 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700845 callback->onHeadTrackingModeChanged(spatializerMode);
846 }
847}
848
Eric Laurent15903592022-02-24 20:44:36 +0100849status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200850 bool outputChanged = false;
851 sp<media::INativeSpatializerCallback> callback;
852
Eric Laurent2be8b292021-08-23 09:44:33 -0700853 {
854 std::lock_guard lock(mLock);
855 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000856 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
857 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700858 if (mOutput != AUDIO_IO_HANDLE_NONE) {
859 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
860 // remove FX instance
861 mEngine->setEnabled(false);
862 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100863 mPoseController.reset();
Eric Laurentb387fb42022-05-03 18:19:35 +0200864 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700865 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200866
Eric Laurent2be8b292021-08-23 09:44:33 -0700867 // create FX instance on output
868 AttributionSourceState attributionSource = AttributionSourceState();
869 mEngine = new AudioEffect(attributionSource);
870 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
871 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
872 false /* probe */, true /* notifyFramesProcessed */);
873 status_t status = mEngine->initCheck();
874 ALOGV("%s mEngine create status %d", __func__, (int)status);
875 if (status != NO_ERROR) {
876 return status;
877 }
878
Eric Laurent4a872862021-10-11 17:06:47 +0200879 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700880 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200881 mNumActiveTracks = numActiveTracks;
Eric Laurentb387fb42022-05-03 18:19:35 +0200882 AudioSystem::addSupportedLatencyModesCallback(this);
883
884 std::vector<audio_latency_mode_t> latencyModes;
885 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
886 if (status == OK) {
887 mSupportedLatencyModes = latencyModes;
888 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700889
Eric Laurent11094172022-04-05 18:27:42 +0200890 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200891 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200892 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100893 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200894 }
Eric Laurent4a872862021-10-11 17:06:47 +0200895 callback = mSpatializerCallback;
Andy Hungcd6c1062023-03-09 20:45:36 -0800896
897 // Restore common effect state.
898 setEffectParameter_l(SPATIALIZER_PARAM_DISPLAY_ORIENTATION,
899 std::vector<float>{mDisplayOrientation});
900 setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE,
901 std::vector<uint8_t>{mFoldedState});
902 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE,
903 std::vector<float>{mHingeAngle});
Eric Laurent6d607012021-07-05 11:54:40 +0200904 }
Eric Laurent4a872862021-10-11 17:06:47 +0200905
906 if (outputChanged && callback != nullptr) {
907 callback->onOutputChanged(output);
908 }
909
Eric Laurent6d607012021-07-05 11:54:40 +0200910 return NO_ERROR;
911}
912
913audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700914 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200915 sp<media::INativeSpatializerCallback> callback;
916
917 {
918 std::lock_guard lock(mLock);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000919 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +0200920 ALOGV("%s mOutput %d", __func__, (int)mOutput);
921 if (mOutput == AUDIO_IO_HANDLE_NONE) {
922 return output;
923 }
924 // remove FX instance
925 mEngine->setEnabled(false);
926 mEngine.clear();
Eric Laurentb387fb42022-05-03 18:19:35 +0200927 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200928 output = mOutput;
929 mOutput = AUDIO_IO_HANDLE_NONE;
930 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200931 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200932 }
Eric Laurent4a872862021-10-11 17:06:47 +0200933
934 if (callback != nullptr) {
935 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
936 }
Eric Laurent6d607012021-07-05 11:54:40 +0200937 return output;
938}
939
Eric Laurentb387fb42022-05-03 18:19:35 +0200940void Spatializer::onSupportedLatencyModesChanged(
941 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200942 ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
943 sp<AMessage> msg =
944 new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
945 msg->setObject(EngineCallbackHandler::kLatencyModesKey,
946 sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
947 msg->post();
948}
949
950void Spatializer::onSupportedLatencyModesChangedMsg(
951 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
Eric Laurentb387fb42022-05-03 18:19:35 +0200952 std::lock_guard lock(mLock);
Eric Laurentdf2ece42022-07-20 13:49:47 +0200953 ALOGV("%s output %d mOutput %d num modes %zu",
954 __func__, (int)output, (int)mOutput, modes.size());
Eric Laurentb387fb42022-05-03 18:19:35 +0200955 if (output == mOutput) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200956 mSupportedLatencyModes = std::move(modes);
Eric Laurentb387fb42022-05-03 18:19:35 +0200957 checkSensorsState_l();
958 }
959}
960
Eric Laurent15903592022-02-24 20:44:36 +0100961void Spatializer::updateActiveTracks(size_t numActiveTracks) {
962 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200963 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000964 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200965 mNumActiveTracks = numActiveTracks;
966 checkEngineState_l();
967 checkSensorsState_l();
968 }
Eric Laurent15903592022-02-24 20:44:36 +0100969}
970
Eric Laurent9249d342022-03-18 11:55:56 +0100971void Spatializer::checkSensorsState_l() {
Eric Laurentb387fb42022-05-03 18:19:35 +0200972 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
Andy Hungc0896c72022-10-21 17:30:30 -0700973 const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
974 const bool supportsLowLatencyMode = supportsSetLatencyMode && std::find(
975 mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
976 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
Eric Laurent3c48ad92022-10-21 11:28:32 +0200977 if (mSupportsHeadTracking) {
978 if (mPoseController != nullptr) {
Andy Hungc0896c72022-10-21 17:30:30 -0700979 // TODO(b/253297301, b/255433067) reenable low latency condition check
980 // for Head Tracking after Bluetooth HAL supports it correctly.
981 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent3c48ad92022-10-21 11:28:32 +0200982 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
983 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
984 if (mEngine != nullptr) {
985 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
986 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
987 }
988 mPoseController->setHeadSensor(mHeadSensor);
989 mPoseController->setScreenSensor(mScreenSensor);
Andy Hungc0896c72022-10-21 17:30:30 -0700990 if (supportsLowLatencyMode) requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent3c48ad92022-10-21 11:28:32 +0200991 } else {
992 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
993 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
994 resetEngineHeadPose_l();
995 }
Eric Laurent15903592022-02-24 20:44:36 +0100996 } else {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200997 resetEngineHeadPose_l();
Eric Laurent15903592022-02-24 20:44:36 +0100998 }
999 }
Andy Hungc0896c72022-10-21 17:30:30 -07001000 if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
Andy Hung5d8618d2022-11-17 17:21:45 -08001001 const status_t status =
1002 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
1003 ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
1004 __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
Eric Laurentb387fb42022-05-03 18:19:35 +02001005 }
Eric Laurent15903592022-02-24 20:44:36 +01001006}
1007
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001008void Spatializer::checkEngineState_l() {
1009 if (mEngine != nullptr) {
1010 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
1011 mEngine->setEnabled(true);
1012 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
1013 std::vector<SpatializationLevel>{mLevel});
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001014 } else {
1015 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
1016 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
1017 mEngine->setEnabled(false);
1018 }
1019 }
1020}
1021
Eric Laurent11094172022-04-05 18:27:42 +02001022void Spatializer::checkPoseController_l() {
1023 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
1024 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
1025
1026 if (isControllerNeeded && mPoseController == nullptr) {
1027 mPoseController = std::make_shared<SpatializerPoseController>(
1028 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +02001029 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +02001030 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
1031 "%s could not allocate pose controller", __func__);
1032 mPoseController->setDisplayOrientation(mDisplayOrientation);
1033 } else if (!isControllerNeeded && mPoseController != nullptr) {
1034 mPoseController.reset();
Eric Laurent3c48ad92022-10-21 11:28:32 +02001035 resetEngineHeadPose_l();
Eric Laurent11094172022-04-05 18:27:42 +02001036 }
1037 if (mPoseController != nullptr) {
1038 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
1039 }
1040}
1041
Eric Laurent2be8b292021-08-23 09:44:33 -07001042void Spatializer::calculateHeadPose() {
1043 ALOGV("%s", __func__);
1044 std::lock_guard lock(mLock);
1045 if (mPoseController != nullptr) {
1046 mPoseController->calculateAsync();
1047 }
1048}
Eric Laurent6d607012021-07-05 11:54:40 +02001049
Eric Laurent2be8b292021-08-23 09:44:33 -07001050void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +02001051 if (user == nullptr) {
1052 return;
1053 }
Eric Laurent2be8b292021-08-23 09:44:33 -07001054 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +02001055 switch (event) {
1056 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -07001057 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +01001058 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +02001059 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -07001060 } break;
Eric Laurent6d607012021-07-05 11:54:40 +02001061 default:
Eric Laurent9249d342022-03-18 11:55:56 +01001062 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +02001063 break;
1064 }
1065}
1066
Eric Laurent8a4259f2021-09-14 16:04:00 +02001067void Spatializer::postFramesProcessedMsg(int frames) {
1068 sp<AMessage> msg =
1069 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
1070 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
1071 msg->post();
1072}
1073
Shunkai Yao5a251df2022-07-22 18:42:27 +00001074std::string Spatializer::toString(unsigned level) const {
Andy Hung2a390db2023-01-30 11:58:44 -08001075 std::string prefixSpace(level, ' ');
Shunkai Yao5a251df2022-07-22 18:42:27 +00001076 std::string ss = prefixSpace + "Spatializer:\n";
1077 bool needUnlock = false;
1078
1079 prefixSpace += ' ';
1080 if (!mLock.try_lock()) {
1081 // dumpsys even try_lock failed, information dump can be useful although may not accurate
1082 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1083 } else {
1084 needUnlock = true;
1085 }
1086
1087 // Spatializer class information.
1088 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1089 ss.append(prefixSpace).append("Supported levels: [");
1090 for (auto& level : mLevels) {
1091 base::StringAppendF(&ss, " %s", media::toString(level).c_str());
1092 }
1093 base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
1094
1095 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1096 for (auto& mode : mHeadTrackingModes) {
1097 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1098 }
1099 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
Shunkai Yao51379452022-08-30 03:14:50 +00001100 media::toString(mDesiredHeadTrackingMode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +00001101 media::toString(mActualHeadTrackingMode).c_str());
1102
1103 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1104 for (auto& mode : mSpatializationModes) {
1105 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1106 }
1107 ss += "]\n";
1108
1109 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1110 for (auto& mask : mChannelMasks) {
1111 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1112 }
1113 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1114 mSupportsHeadTracking ? "true" : "false");
1115 // 2. Settings (Output, tracks)
1116 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1117 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1118
1119 // 3. Sensors, Effect information.
1120 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1121 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1122 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1123 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1124 mDisplayOrientation);
1125
1126 ss.append(prefixSpace + "CommandLog:\n");
1127 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001128
1129 // PostController dump.
1130 if (mPoseController != nullptr) {
Andy Hung2a390db2023-01-30 11:58:44 -08001131 ss.append(mPoseController->toString(level + 1))
1132 .append(prefixSpace)
Andy Hung9bcf4252023-02-27 13:36:23 -08001133 .append("Pose (active stage-to-head) [tx, ty, tz : pitch, roll, yaw]:\n")
Andy Hung2a390db2023-01-30 11:58:44 -08001134 .append(prefixSpace)
1135 .append(" PerMinuteHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -08001136 .append(mPoseDurableRecorder.toString(level + 3))
Andy Hung2a390db2023-01-30 11:58:44 -08001137 .append(prefixSpace)
1138 .append(" PerSecondHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -08001139 .append(mPoseRecorder.toString(level + 3));
Shunkai Yao5a251df2022-07-22 18:42:27 +00001140 } else {
1141 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1142 }
1143
1144 if (needUnlock) {
1145 mLock.unlock();
1146 }
1147 return ss;
1148}
1149
Eric Laurent6d607012021-07-05 11:54:40 +02001150} // namespace android