blob: f0d5274cb923e6680adb11bd54ed1da3ae12e5bf [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 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
Andy Hungcd6c1062023-03-09 20:45:36 -080097template<typename T>
98static constexpr const T& safe_clamp(const T& value, const T& low, const T& high) {
99 if constexpr (std::is_floating_point_v<T>) {
100 return value != value /* constexpr isnan */
101 ? low : std::clamp(value, low, high);
102 } else /* constexpr */ {
103 return std::clamp(value, low, high);
104 }
105}
106
Eric Laurent6d607012021-07-05 11:54:40 +0200107// ---------------------------------------------------------------------------
108
Eric Laurent8a4259f2021-09-14 16:04:00 +0200109class Spatializer::EngineCallbackHandler : public AHandler {
110public:
111 EngineCallbackHandler(wp<Spatializer> spatializer)
112 : mSpatializer(spatializer) {
113 }
114
115 enum {
116 // Device state callbacks
117 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
118 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
119 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
Eric Laurentdf2ece42022-07-20 13:49:47 +0200120 kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
Eric Laurent8a4259f2021-09-14 16:04:00 +0200121 };
122 static constexpr const char *kNumFramesKey = "numFrames";
123 static constexpr const char *kModeKey = "mode";
124 static constexpr const char *kTranslation0Key = "translation0";
125 static constexpr const char *kTranslation1Key = "translation1";
126 static constexpr const char *kTranslation2Key = "translation2";
127 static constexpr const char *kRotation0Key = "rotation0";
128 static constexpr const char *kRotation1Key = "rotation1";
129 static constexpr const char *kRotation2Key = "rotation2";
Eric Laurentdf2ece42022-07-20 13:49:47 +0200130 static constexpr const char *kLatencyModesKey = "latencyModes";
131
132 class LatencyModes : public RefBase {
133 public:
134 LatencyModes(audio_io_handle_t output,
135 const std::vector<audio_latency_mode_t>& latencyModes)
136 : mOutput(output), mLatencyModes(latencyModes) {}
137 ~LatencyModes() = default;
138
139 audio_io_handle_t mOutput;
140 std::vector<audio_latency_mode_t> mLatencyModes;
141 };
Eric Laurent8a4259f2021-09-14 16:04:00 +0200142
143 void onMessageReceived(const sp<AMessage> &msg) override {
Andy Hungb725c692022-12-14 14:25:49 -0800144 // No ALooper method to get the tid so update
145 // Spatializer priority on the first message received.
146 std::call_once(mPrioritySetFlag, [](){
147 const pid_t pid = getpid();
148 const pid_t tid = gettid();
149 (void)requestSpatializerPriority(pid, tid);
150 });
151
Eric Laurentdf2ece42022-07-20 13:49:47 +0200152 sp<Spatializer> spatializer = mSpatializer.promote();
153 if (spatializer == nullptr) {
154 ALOGW("%s: Cannot promote spatializer", __func__);
155 return;
156 }
Eric Laurent8a4259f2021-09-14 16:04:00 +0200157 switch (msg->what()) {
158 case kWhatOnFramesProcessed: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200159 int numFrames;
160 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
161 ALOGE("%s: Cannot find num frames!", __func__);
162 return;
163 }
164 if (numFrames > 0) {
165 spatializer->calculateHeadPose();
166 }
167 } break;
168 case kWhatOnHeadToStagePose: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200169 std::vector<float> headToStage(sHeadPoseKeys.size());
170 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
171 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
172 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
173 return;
174 }
175 }
176 spatializer->onHeadToStagePoseMsg(headToStage);
177 } break;
178 case kWhatOnActualModeChange: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200179 int mode;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200180 if (!msg->findInt32(kModeKey, &mode)) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200181 ALOGE("%s: Cannot find actualMode!", __func__);
182 return;
183 }
184 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
185 } break;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200186
187 case kWhatOnLatencyModesChanged: {
188 sp<RefBase> object;
189 if (!msg->findObject(kLatencyModesKey, &object)) {
190 ALOGE("%s: Cannot find latency modes!", __func__);
191 return;
192 }
193 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
194 spatializer->onSupportedLatencyModesChangedMsg(
195 latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
196 } break;
197
Eric Laurent8a4259f2021-09-14 16:04:00 +0200198 default:
199 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
200 }
201 }
202private:
203 wp<Spatializer> mSpatializer;
Andy Hungb725c692022-12-14 14:25:49 -0800204 std::once_flag mPrioritySetFlag;
Eric Laurent8a4259f2021-09-14 16:04:00 +0200205};
206
207const std::vector<const char *> Spatializer::sHeadPoseKeys = {
208 Spatializer::EngineCallbackHandler::kTranslation0Key,
209 Spatializer::EngineCallbackHandler::kTranslation1Key,
210 Spatializer::EngineCallbackHandler::kTranslation2Key,
211 Spatializer::EngineCallbackHandler::kRotation0Key,
212 Spatializer::EngineCallbackHandler::kRotation1Key,
213 Spatializer::EngineCallbackHandler::kRotation2Key,
214};
215
216// ---------------------------------------------------------------------------
Shunkai Yaoe3e403d2023-04-18 23:14:25 +0000217sp<Spatializer> Spatializer::create(SpatializerPolicyCallback* callback,
218 const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
Eric Laurent6d607012021-07-05 11:54:40 +0200219 sp<Spatializer> spatializer;
220
Eric Laurent6d607012021-07-05 11:54:40 +0200221 if (effectsFactoryHal == nullptr) {
222 ALOGW("%s failed to create effect factory interface", __func__);
223 return spatializer;
224 }
225
226 std::vector<effect_descriptor_t> descriptors;
Shunkai Yaoe3e403d2023-04-18 23:14:25 +0000227 status_t status = effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200228 if (status != NO_ERROR) {
229 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
230 return spatializer;
231 }
232 ALOG_ASSERT(!descriptors.empty(),
233 "%s getDescriptors() returned no error but empty list", __func__);
234
Shunkai Yao5a251df2022-07-22 18:42:27 +0000235 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200236 sp<EffectHalInterface> effect;
237 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
238 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000239 ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
240 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200241
242 if (status == NO_ERROR && effect != nullptr) {
243 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700244 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
245 spatializer.clear();
Andy Hung0e3205d2022-08-29 14:14:58 -0700246 ALOGW("%s loadEngine error: %d effect Id %" PRId64,
247 __func__, status, effect ? effect->effectId() : 0);
248 } else {
249 spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
250 effect ? effect->effectId() : 0);
Eric Laurent2be8b292021-08-23 09:44:33 -0700251 }
Eric Laurent6d607012021-07-05 11:54:40 +0200252 }
253
254 return spatializer;
255}
256
Eric Laurent2be8b292021-08-23 09:44:33 -0700257Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
258 : mEngineDescriptor(engineDescriptor),
259 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200260 ALOGV("%s", __func__);
Andy Hung393de3a2022-12-06 16:33:20 -0800261 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent6d607012021-07-05 11:54:40 +0200262}
263
Eric Laurent8a4259f2021-09-14 16:04:00 +0200264void Spatializer::onFirstRef() {
265 mLooper = new ALooper;
266 mLooper->setName("Spatializer-looper");
267 mLooper->start(
268 /*runOnCallingThread*/false,
269 /*canCallJava*/ false,
Andy Hung898a39f2022-11-07 20:09:20 -0800270 PRIORITY_URGENT_AUDIO);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200271
272 mHandler = new EngineCallbackHandler(this);
273 mLooper->registerHandler(mHandler);
274}
275
Eric Laurent6d607012021-07-05 11:54:40 +0200276Spatializer::~Spatializer() {
277 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200278 if (mLooper != nullptr) {
279 mLooper->stop();
280 mLooper->unregisterHandler(mHandler->id());
281 }
282 mLooper.clear();
283 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200284}
285
Andy Hung4442d042022-08-17 17:27:32 -0700286static std::string channelMaskVectorToString(
287 const std::vector<audio_channel_mask_t>& masks) {
288 std::stringstream ss;
289 for (const auto &mask : masks) {
290 if (ss.tellp() != 0) ss << "|";
291 ss << mask;
292 }
293 return ss.str();
294}
295
Eric Laurent2be8b292021-08-23 09:44:33 -0700296status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
297 ALOGV("%s", __func__);
298
299 std::vector<bool> supportsHeadTracking;
300 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
301 &supportsHeadTracking);
302 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700303 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700304 return status;
305 }
306 mSupportsHeadTracking = supportsHeadTracking[0];
307
Andy Hung119dbdb2022-05-11 19:20:13 -0700308 std::vector<media::SpatializationLevel> spatializationLevels;
309 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
310 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700311 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700312 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700313 return status;
314 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700315 bool noneLevelFound = false;
316 bool activeLevelFound = false;
317 for (const auto spatializationLevel : spatializationLevels) {
318 if (!aidl_utils::isValidEnum(spatializationLevel)) {
319 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
320 continue;
321 }
322 if (spatializationLevel == media::SpatializationLevel::NONE) {
323 noneLevelFound = true;
324 } else {
325 activeLevelFound = true;
326 }
327 // we don't detect duplicates.
328 mLevels.emplace_back(spatializationLevel);
329 }
330 if (!noneLevelFound || !activeLevelFound) {
331 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
332 " and another valid level", __func__);
333 return BAD_VALUE;
334 }
335
336 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700337 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700338 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700339 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700340 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700341 return status;
342 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000343
Andy Hung119dbdb2022-05-11 19:20:13 -0700344 for (const auto spatializationMode : spatializationModes) {
345 if (!aidl_utils::isValidEnum(spatializationMode)) {
346 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
347 continue;
348 }
349 // we don't detect duplicates.
350 mSpatializationModes.emplace_back(spatializationMode);
351 }
352 if (mSpatializationModes.empty()) {
353 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
354 return BAD_VALUE;
355 }
356
357 std::vector<audio_channel_mask_t> channelMasks;
358 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
359 &channelMasks);
360 if (status != NO_ERROR) {
361 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
362 return status;
363 }
364 for (const auto channelMask : channelMasks) {
365 if (!audio_is_channel_mask_spatialized(channelMask)) {
366 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
367 continue;
368 }
369 // we don't detect duplicates.
370 mChannelMasks.emplace_back(channelMask);
371 }
372 if (mChannelMasks.empty()) {
373 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
374 return BAD_VALUE;
375 }
Andy Hunga461a002022-05-17 10:36:02 -0700376
377 // Currently we expose only RELATIVE_WORLD.
378 // This is a limitation of the head tracking library based on a UX choice.
379 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
380 if (mSupportsHeadTracking) {
381 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
382 }
383 mediametrics::LogItem(mMetricsId)
384 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
Andy Hung4442d042022-08-17 17:27:32 -0700385 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
Andy Hunga461a002022-05-17 10:36:02 -0700386 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
387 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
388 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
389 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
390 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700391 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700392}
393
Andy Hung757bc812022-09-13 18:53:06 -0700394/* static */
395void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
396 mediametrics::LogItem(kDefaultMetricsId)
397 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
398 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
399 .set(AMEDIAMETRICS_PROP_LEVELS, "")
400 .set(AMEDIAMETRICS_PROP_MODES, "")
401 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
402 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
403 .record();
404}
405
Eric Laurent2be8b292021-08-23 09:44:33 -0700406/** Gets the channel mask, sampling rate and format set for the spatializer input. */
407audio_config_base_t Spatializer::getAudioInConfig() const {
408 std::lock_guard lock(mLock);
409 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
410 // For now use highest supported channel count
Andy Hung0e3205d2022-08-29 14:14:58 -0700411 config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
Eric Laurent2be8b292021-08-23 09:44:33 -0700412 return config;
413}
414
Eric Laurent6d607012021-07-05 11:54:40 +0200415status_t Spatializer::registerCallback(
416 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700417 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200418 if (callback == nullptr) {
419 return BAD_VALUE;
420 }
421
Eric Laurentb57604f2022-08-31 16:07:50 +0200422 if (mSpatializerCallback != nullptr) {
423 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
424 ALOGW("%s: Registering callback %p again",
425 __func__, mSpatializerCallback.get());
426 return NO_ERROR;
427 }
428 ALOGE("%s: Already one client registered with callback %p",
429 __func__, mSpatializerCallback.get());
430 return INVALID_OPERATION;
431 }
432
Eric Laurent6d607012021-07-05 11:54:40 +0200433 sp<IBinder> binder = IInterface::asBinder(callback);
434 status_t status = binder->linkToDeath(this);
435 if (status == NO_ERROR) {
436 mSpatializerCallback = callback;
437 }
438 ALOGV("%s status %d", __func__, status);
439 return status;
440}
441
442// IBinder::DeathRecipient
443void Spatializer::binderDied(__unused const wp<IBinder> &who) {
444 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700445 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200446 mLevel = SpatializationLevel::NONE;
447 mSpatializerCallback.clear();
448 }
449 ALOGV("%s", __func__);
450 mPolicyCallback->onCheckSpatializer();
451}
452
453// ISpatializer
454Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
455 ALOGV("%s", __func__);
456 if (levels == nullptr) {
457 return binderStatusFromStatusT(BAD_VALUE);
458 }
Andy Hunga461a002022-05-17 10:36:02 -0700459 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700460 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200461 return Status::ok();
462}
463
Eric Laurent2be8b292021-08-23 09:44:33 -0700464Status Spatializer::setLevel(SpatializationLevel level) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000465 ALOGV("%s level %s", __func__, media::toString(level).c_str());
466 mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
Eric Laurent6d607012021-07-05 11:54:40 +0200467 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700468 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200469 return binderStatusFromStatusT(BAD_VALUE);
470 }
471 sp<media::INativeSpatializerCallback> callback;
472 bool levelChanged = false;
473 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700474 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200475 levelChanged = mLevel != level;
476 mLevel = level;
477 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700478
479 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200480 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700481 }
Eric Laurent9249d342022-03-18 11:55:56 +0100482 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200483 }
484
485 if (levelChanged) {
486 mPolicyCallback->onCheckSpatializer();
487 if (callback != nullptr) {
488 callback->onLevelChanged(level);
489 }
490 }
491 return Status::ok();
492}
493
Eric Laurent2be8b292021-08-23 09:44:33 -0700494Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200495 if (level == nullptr) {
496 return binderStatusFromStatusT(BAD_VALUE);
497 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700498 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200499 *level = mLevel;
500 ALOGV("%s level %d", __func__, (int)*level);
501 return Status::ok();
502}
503
Eric Laurentc87402b2021-09-17 16:49:42 +0200504Status Spatializer::isHeadTrackingSupported(bool *supports) {
505 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
506 if (supports == nullptr) {
507 return binderStatusFromStatusT(BAD_VALUE);
508 }
509 std::lock_guard lock(mLock);
510 *supports = mSupportsHeadTracking;
511 return Status::ok();
512}
513
Eric Laurent6d607012021-07-05 11:54:40 +0200514Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700515 std::vector<SpatializerHeadTrackingMode>* modes) {
516 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200517 ALOGV("%s", __func__);
518 if (modes == nullptr) {
519 return binderStatusFromStatusT(BAD_VALUE);
520 }
Andy Hunga461a002022-05-17 10:36:02 -0700521 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200522 return Status::ok();
523}
524
Eric Laurent2be8b292021-08-23 09:44:33 -0700525Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000526 ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700527
528 if (!mSupportsHeadTracking) {
529 return binderStatusFromStatusT(INVALID_OPERATION);
530 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000531 mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700532 std::lock_guard lock(mLock);
533 switch (mode) {
534 case SpatializerHeadTrackingMode::OTHER:
535 return binderStatusFromStatusT(BAD_VALUE);
536 case SpatializerHeadTrackingMode::DISABLED:
537 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
538 break;
539 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
540 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
541 break;
542 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
543 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
544 break;
545 }
546
Eric Laurent11094172022-04-05 18:27:42 +0200547 checkPoseController_l();
548 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700549
550 return Status::ok();
551}
552
553Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200554 if (mode == nullptr) {
555 return binderStatusFromStatusT(BAD_VALUE);
556 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700557 std::lock_guard lock(mLock);
558 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200559 ALOGV("%s mode %d", __func__, (int)*mode);
560 return Status::ok();
561}
562
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700563Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200564 if (!mSupportsHeadTracking) {
565 return binderStatusFromStatusT(INVALID_OPERATION);
566 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700567 std::lock_guard lock(mLock);
568 if (mPoseController != nullptr) {
569 mPoseController->recenter();
570 }
Eric Laurent6d607012021-07-05 11:54:40 +0200571 return Status::ok();
572}
573
574Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200575 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200576 if (!mSupportsHeadTracking) {
577 return binderStatusFromStatusT(INVALID_OPERATION);
578 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700579 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
580 if (!maybePose.has_value()) {
581 ALOGW("Invalid screenToStage vector.");
582 return binderStatusFromStatusT(BAD_VALUE);
583 }
584 std::lock_guard lock(mLock);
585 if (mPoseController != nullptr) {
Andy Hung82a4eab2023-01-30 11:58:44 -0800586 mLocalLog.log("%s with screenToStage %s", __func__,
587 media::VectorRecorder::toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700588 mPoseController->setScreenToStagePose(maybePose.value());
589 }
Eric Laurent6d607012021-07-05 11:54:40 +0200590 return Status::ok();
591}
592
593Status Spatializer::release() {
594 ALOGV("%s", __func__);
595 bool levelChanged = false;
596 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700597 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200598 if (mSpatializerCallback == nullptr) {
599 return binderStatusFromStatusT(INVALID_OPERATION);
600 }
601
602 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
603 binder->unlinkToDeath(this);
604 mSpatializerCallback.clear();
605
606 levelChanged = mLevel != SpatializationLevel::NONE;
607 mLevel = SpatializationLevel::NONE;
608 }
609
610 if (levelChanged) {
611 mPolicyCallback->onCheckSpatializer();
612 }
613 return Status::ok();
614}
615
Eric Laurent2be8b292021-08-23 09:44:33 -0700616Status Spatializer::setHeadSensor(int sensorHandle) {
617 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200618 if (!mSupportsHeadTracking) {
619 return binderStatusFromStatusT(INVALID_OPERATION);
620 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700621 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700622 if (mHeadSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000623 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700624 mHeadSensor = sensorHandle;
625 checkPoseController_l();
626 checkSensorsState_l();
627 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700628 return Status::ok();
629}
630
631Status Spatializer::setScreenSensor(int sensorHandle) {
632 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200633 if (!mSupportsHeadTracking) {
634 return binderStatusFromStatusT(INVALID_OPERATION);
635 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700636 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700637 if (mScreenSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000638 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700639 mScreenSensor = sensorHandle;
640 // TODO: consider a new method setHeadAndScreenSensor()
641 // because we generally set both at the same time.
642 // This will avoid duplicated work and recentering.
643 checkSensorsState_l();
644 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700645 return Status::ok();
646}
647
648Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
649 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000650 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Andy Hungcd6c1062023-03-09 20:45:36 -0800651 const float angle = safe_clamp(physicalToLogicalAngle, 0.f, (float)(2. * M_PI));
652 // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
653 ALOGI_IF(angle != physicalToLogicalAngle,
654 "%s: clamping %f to %f", __func__, physicalToLogicalAngle, angle);
655 std::lock_guard lock(mLock);
656 mDisplayOrientation = angle;
Eric Laurent2be8b292021-08-23 09:44:33 -0700657 if (mPoseController != nullptr) {
Andy Hungcd6c1062023-03-09 20:45:36 -0800658 // This turns on the rate-limiter.
659 mPoseController->setDisplayOrientation(angle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700660 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200661 if (mEngine != nullptr) {
662 setEffectParameter_l(
Andy Hungcd6c1062023-03-09 20:45:36 -0800663 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{angle});
Eric Laurent16ddaf42021-09-17 15:00:35 +0200664 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700665 return Status::ok();
666}
667
668Status Spatializer::setHingeAngle(float hingeAngle) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700669 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
Andy Hungcd6c1062023-03-09 20:45:36 -0800670 mLocalLog.log("%s with %f", __func__, hingeAngle);
671 const float angle = safe_clamp(hingeAngle, 0.f, (float)(2. * M_PI));
672 // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
673 ALOGI_IF(angle != hingeAngle,
674 "%s: clamping %f to %f", __func__, hingeAngle, angle);
675 std::lock_guard lock(mLock);
676 mHingeAngle = angle;
Eric Laurent2be8b292021-08-23 09:44:33 -0700677 if (mEngine != nullptr) {
Andy Hungcd6c1062023-03-09 20:45:36 -0800678 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{angle});
679 }
680 return Status::ok();
681}
682
683Status Spatializer::setFoldState(bool folded) {
684 ALOGV("%s foldState %d", __func__, (int)folded);
685 mLocalLog.log("%s with %d", __func__, (int)folded);
686 std::lock_guard lock(mLock);
687 mFoldedState = folded;
688 if (mEngine != nullptr) {
689 // we don't suppress multiple calls with the same folded state - that's
690 // done at the caller.
691 setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE, std::vector<uint8_t>{mFoldedState});
Eric Laurent2be8b292021-08-23 09:44:33 -0700692 }
693 return Status::ok();
694}
695
696Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
697 ALOGV("%s", __func__);
698 if (modes == nullptr) {
699 return binderStatusFromStatusT(BAD_VALUE);
700 }
701 *modes = mSpatializationModes;
702 return Status::ok();
703}
704
Eric Laurent67816e32021-09-16 15:18:40 +0200705Status Spatializer::registerHeadTrackingCallback(
706 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
707 ALOGV("%s callback %p", __func__, callback.get());
708 std::lock_guard lock(mLock);
709 if (!mSupportsHeadTracking) {
710 return binderStatusFromStatusT(INVALID_OPERATION);
711 }
712 mHeadTrackingCallback = callback;
713 return Status::ok();
714}
715
Eric Laurentc87402b2021-09-17 16:49:42 +0200716Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
717 ALOGV("%s key %d", __func__, key);
718 std::lock_guard lock(mLock);
719 status_t status = INVALID_OPERATION;
720 if (mEngine != nullptr) {
721 status = setEffectParameter_l(key, value);
722 }
723 return binderStatusFromStatusT(status);
724}
725
726Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700727 ALOGV("%s key %d value size %d", __func__, key,
728 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200729 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700730 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200731 }
732 std::lock_guard lock(mLock);
733 status_t status = INVALID_OPERATION;
734 if (mEngine != nullptr) {
735 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
736 status = getEffectParameter_l(key, value);
737 }
738 return binderStatusFromStatusT(status);
739}
740
741Status Spatializer::getOutput(int *output) {
742 ALOGV("%s", __func__);
743 if (output == nullptr) {
744 binderStatusFromStatusT(BAD_VALUE);
745 }
746 std::lock_guard lock(mLock);
747 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
748 ALOGV("%s got output %d", __func__, *output);
749 return Status::ok();
750}
751
Eric Laurent2be8b292021-08-23 09:44:33 -0700752// SpatializerPoseController::Listener
753void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
754 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200755 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
756 "onHeadToStagePose() called with no head tracking support!");
757
Eric Laurent2be8b292021-08-23 09:44:33 -0700758 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200759 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
760 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200761 sp<AMessage> msg =
762 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
763 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
764 msg->setFloat(sHeadPoseKeys[i], vec[i]);
765 }
766 msg->post();
767}
768
Eric Laurent3c48ad92022-10-21 11:28:32 +0200769void Spatializer::resetEngineHeadPose_l() {
770 ALOGV("%s mEngine %p", __func__, mEngine.get());
771 if (mEngine == nullptr) {
772 return;
773 }
774 const std::vector<float> headToStage(6, 0.0);
775 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
776 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
777 std::vector<SpatializerHeadTrackingMode>{SpatializerHeadTrackingMode::DISABLED});
778}
779
Eric Laurent8a4259f2021-09-14 16:04:00 +0200780void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
781 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200782 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700783 {
784 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200785 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700786 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200787 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Andy Hung2a390db2023-01-30 11:58:44 -0800788 const auto record = recordFromTranslationRotationVector(headToStage);
789 mPoseRecorder.record(record);
790 mPoseDurableRecorder.record(record);
Eric Laurent2be8b292021-08-23 09:44:33 -0700791 }
792 }
793
794 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200795 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700796 }
797}
798
799void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao51379452022-08-30 03:14:50 +0000800 std::string modeStr = media::toString(mode);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000801 ALOGV("%s(%s)", __func__, modeStr.c_str());
Shunkai Yao51379452022-08-30 03:14:50 +0000802 sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200803 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
804 msg->post();
805}
806
807void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
808 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200809 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700810 SpatializerHeadTrackingMode spatializerMode;
811 {
812 std::lock_guard lock(mLock);
813 if (!mSupportsHeadTracking) {
814 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
815 } else {
816 switch (mode) {
817 case HeadTrackingMode::STATIC:
818 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
819 break;
820 case HeadTrackingMode::WORLD_RELATIVE:
821 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
822 break;
823 case HeadTrackingMode::SCREEN_RELATIVE:
824 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
825 break;
826 default:
827 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
828 }
829 }
830 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200831 if (mEngine != nullptr) {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200832 if (spatializerMode == SpatializerHeadTrackingMode::DISABLED) {
833 resetEngineHeadPose_l();
834 } else {
835 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
836 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
837 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200838 }
Eric Laurent67816e32021-09-16 15:18:40 +0200839 callback = mHeadTrackingCallback;
Andy Hung79ccfda2023-01-30 11:58:44 -0800840 mLocalLog.log("%s: updating mode to %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700841 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200842 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700843 callback->onHeadTrackingModeChanged(spatializerMode);
844 }
845}
846
Eric Laurent15903592022-02-24 20:44:36 +0100847status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200848 bool outputChanged = false;
849 sp<media::INativeSpatializerCallback> callback;
850
Eric Laurent2be8b292021-08-23 09:44:33 -0700851 {
852 std::lock_guard lock(mLock);
853 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000854 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
855 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700856 if (mOutput != AUDIO_IO_HANDLE_NONE) {
857 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
858 // remove FX instance
859 mEngine->setEnabled(false);
860 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100861 mPoseController.reset();
Eric Laurentb387fb42022-05-03 18:19:35 +0200862 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700863 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200864
Eric Laurent2be8b292021-08-23 09:44:33 -0700865 // create FX instance on output
866 AttributionSourceState attributionSource = AttributionSourceState();
867 mEngine = new AudioEffect(attributionSource);
868 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
869 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
870 false /* probe */, true /* notifyFramesProcessed */);
871 status_t status = mEngine->initCheck();
872 ALOGV("%s mEngine create status %d", __func__, (int)status);
873 if (status != NO_ERROR) {
874 return status;
875 }
876
Eric Laurent4a872862021-10-11 17:06:47 +0200877 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700878 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200879 mNumActiveTracks = numActiveTracks;
Eric Laurentb387fb42022-05-03 18:19:35 +0200880 AudioSystem::addSupportedLatencyModesCallback(this);
881
882 std::vector<audio_latency_mode_t> latencyModes;
883 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
884 if (status == OK) {
885 mSupportedLatencyModes = latencyModes;
886 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700887
Eric Laurent11094172022-04-05 18:27:42 +0200888 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200889 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200890 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100891 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200892 }
Eric Laurent4a872862021-10-11 17:06:47 +0200893 callback = mSpatializerCallback;
Andy Hungcd6c1062023-03-09 20:45:36 -0800894
895 // Restore common effect state.
896 setEffectParameter_l(SPATIALIZER_PARAM_DISPLAY_ORIENTATION,
897 std::vector<float>{mDisplayOrientation});
898 setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE,
899 std::vector<uint8_t>{mFoldedState});
900 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE,
901 std::vector<float>{mHingeAngle});
Eric Laurent6d607012021-07-05 11:54:40 +0200902 }
Eric Laurent4a872862021-10-11 17:06:47 +0200903
904 if (outputChanged && callback != nullptr) {
905 callback->onOutputChanged(output);
906 }
907
Eric Laurent6d607012021-07-05 11:54:40 +0200908 return NO_ERROR;
909}
910
911audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700912 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200913 sp<media::INativeSpatializerCallback> callback;
914
915 {
916 std::lock_guard lock(mLock);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000917 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +0200918 ALOGV("%s mOutput %d", __func__, (int)mOutput);
919 if (mOutput == AUDIO_IO_HANDLE_NONE) {
920 return output;
921 }
922 // remove FX instance
923 mEngine->setEnabled(false);
924 mEngine.clear();
Eric Laurentb387fb42022-05-03 18:19:35 +0200925 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200926 output = mOutput;
927 mOutput = AUDIO_IO_HANDLE_NONE;
928 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200929 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200930 }
Eric Laurent4a872862021-10-11 17:06:47 +0200931
932 if (callback != nullptr) {
933 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
934 }
Eric Laurent6d607012021-07-05 11:54:40 +0200935 return output;
936}
937
Eric Laurentb387fb42022-05-03 18:19:35 +0200938void Spatializer::onSupportedLatencyModesChanged(
939 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200940 ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
941 sp<AMessage> msg =
942 new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
943 msg->setObject(EngineCallbackHandler::kLatencyModesKey,
944 sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
945 msg->post();
946}
947
948void Spatializer::onSupportedLatencyModesChangedMsg(
949 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
Eric Laurentb387fb42022-05-03 18:19:35 +0200950 std::lock_guard lock(mLock);
Eric Laurentdf2ece42022-07-20 13:49:47 +0200951 ALOGV("%s output %d mOutput %d num modes %zu",
952 __func__, (int)output, (int)mOutput, modes.size());
Eric Laurentb387fb42022-05-03 18:19:35 +0200953 if (output == mOutput) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200954 mSupportedLatencyModes = std::move(modes);
Eric Laurentb387fb42022-05-03 18:19:35 +0200955 checkSensorsState_l();
956 }
957}
958
Eric Laurent15903592022-02-24 20:44:36 +0100959void Spatializer::updateActiveTracks(size_t numActiveTracks) {
960 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200961 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000962 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200963 mNumActiveTracks = numActiveTracks;
964 checkEngineState_l();
965 checkSensorsState_l();
966 }
Eric Laurent15903592022-02-24 20:44:36 +0100967}
968
Eric Laurent9249d342022-03-18 11:55:56 +0100969void Spatializer::checkSensorsState_l() {
Eric Laurentb387fb42022-05-03 18:19:35 +0200970 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
Andy Hungc0896c72022-10-21 17:30:30 -0700971 const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
972 const bool supportsLowLatencyMode = supportsSetLatencyMode && std::find(
973 mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
974 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
Eric Laurent3c48ad92022-10-21 11:28:32 +0200975 if (mSupportsHeadTracking) {
976 if (mPoseController != nullptr) {
Andy Hungc0896c72022-10-21 17:30:30 -0700977 // TODO(b/253297301, b/255433067) reenable low latency condition check
978 // for Head Tracking after Bluetooth HAL supports it correctly.
979 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent3c48ad92022-10-21 11:28:32 +0200980 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
981 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
982 if (mEngine != nullptr) {
983 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
984 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
985 }
986 mPoseController->setHeadSensor(mHeadSensor);
987 mPoseController->setScreenSensor(mScreenSensor);
Andy Hungc0896c72022-10-21 17:30:30 -0700988 if (supportsLowLatencyMode) requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent3c48ad92022-10-21 11:28:32 +0200989 } else {
990 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
991 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
992 resetEngineHeadPose_l();
993 }
Eric Laurent15903592022-02-24 20:44:36 +0100994 } else {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200995 resetEngineHeadPose_l();
Eric Laurent15903592022-02-24 20:44:36 +0100996 }
997 }
Andy Hungc0896c72022-10-21 17:30:30 -0700998 if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
Andy Hung5d8618d2022-11-17 17:21:45 -0800999 const status_t status =
1000 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
1001 ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
1002 __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
Eric Laurentb387fb42022-05-03 18:19:35 +02001003 }
Eric Laurent15903592022-02-24 20:44:36 +01001004}
1005
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001006void Spatializer::checkEngineState_l() {
1007 if (mEngine != nullptr) {
1008 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
1009 mEngine->setEnabled(true);
1010 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
1011 std::vector<SpatializationLevel>{mLevel});
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001012 } else {
1013 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
1014 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
1015 mEngine->setEnabled(false);
1016 }
1017 }
1018}
1019
Eric Laurent11094172022-04-05 18:27:42 +02001020void Spatializer::checkPoseController_l() {
1021 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
1022 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
1023
1024 if (isControllerNeeded && mPoseController == nullptr) {
1025 mPoseController = std::make_shared<SpatializerPoseController>(
1026 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +02001027 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +02001028 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
1029 "%s could not allocate pose controller", __func__);
1030 mPoseController->setDisplayOrientation(mDisplayOrientation);
1031 } else if (!isControllerNeeded && mPoseController != nullptr) {
1032 mPoseController.reset();
Eric Laurent3c48ad92022-10-21 11:28:32 +02001033 resetEngineHeadPose_l();
Eric Laurent11094172022-04-05 18:27:42 +02001034 }
1035 if (mPoseController != nullptr) {
1036 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
1037 }
1038}
1039
Eric Laurent2be8b292021-08-23 09:44:33 -07001040void Spatializer::calculateHeadPose() {
1041 ALOGV("%s", __func__);
1042 std::lock_guard lock(mLock);
1043 if (mPoseController != nullptr) {
1044 mPoseController->calculateAsync();
1045 }
1046}
Eric Laurent6d607012021-07-05 11:54:40 +02001047
Eric Laurent2be8b292021-08-23 09:44:33 -07001048void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +02001049 if (user == nullptr) {
1050 return;
1051 }
Eric Laurent2be8b292021-08-23 09:44:33 -07001052 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +02001053 switch (event) {
1054 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -07001055 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +01001056 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +02001057 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -07001058 } break;
Eric Laurent6d607012021-07-05 11:54:40 +02001059 default:
Eric Laurent9249d342022-03-18 11:55:56 +01001060 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +02001061 break;
1062 }
1063}
1064
Eric Laurent8a4259f2021-09-14 16:04:00 +02001065void Spatializer::postFramesProcessedMsg(int frames) {
1066 sp<AMessage> msg =
1067 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
1068 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
1069 msg->post();
1070}
1071
Shunkai Yao5a251df2022-07-22 18:42:27 +00001072std::string Spatializer::toString(unsigned level) const {
Andy Hung2a390db2023-01-30 11:58:44 -08001073 std::string prefixSpace(level, ' ');
Shunkai Yao5a251df2022-07-22 18:42:27 +00001074 std::string ss = prefixSpace + "Spatializer:\n";
1075 bool needUnlock = false;
1076
1077 prefixSpace += ' ';
1078 if (!mLock.try_lock()) {
1079 // dumpsys even try_lock failed, information dump can be useful although may not accurate
1080 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1081 } else {
1082 needUnlock = true;
1083 }
1084
1085 // Spatializer class information.
1086 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1087 ss.append(prefixSpace).append("Supported levels: [");
1088 for (auto& level : mLevels) {
1089 base::StringAppendF(&ss, " %s", media::toString(level).c_str());
1090 }
1091 base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
1092
1093 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1094 for (auto& mode : mHeadTrackingModes) {
1095 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1096 }
1097 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
Shunkai Yao51379452022-08-30 03:14:50 +00001098 media::toString(mDesiredHeadTrackingMode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +00001099 media::toString(mActualHeadTrackingMode).c_str());
1100
1101 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1102 for (auto& mode : mSpatializationModes) {
1103 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1104 }
1105 ss += "]\n";
1106
1107 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1108 for (auto& mask : mChannelMasks) {
1109 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1110 }
1111 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1112 mSupportsHeadTracking ? "true" : "false");
1113 // 2. Settings (Output, tracks)
1114 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1115 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1116
1117 // 3. Sensors, Effect information.
1118 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1119 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1120 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1121 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1122 mDisplayOrientation);
1123
1124 ss.append(prefixSpace + "CommandLog:\n");
1125 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001126
1127 // PostController dump.
1128 if (mPoseController != nullptr) {
Andy Hung2a390db2023-01-30 11:58:44 -08001129 ss.append(mPoseController->toString(level + 1))
1130 .append(prefixSpace)
Andy Hung9bcf4252023-02-27 13:36:23 -08001131 .append("Pose (active stage-to-head) [tx, ty, tz : pitch, roll, yaw]:\n")
Andy Hung2a390db2023-01-30 11:58:44 -08001132 .append(prefixSpace)
1133 .append(" PerMinuteHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -08001134 .append(mPoseDurableRecorder.toString(level + 3))
Andy Hung2a390db2023-01-30 11:58:44 -08001135 .append(prefixSpace)
1136 .append(" PerSecondHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -08001137 .append(mPoseRecorder.toString(level + 3));
Shunkai Yao5a251df2022-07-22 18:42:27 +00001138 } else {
1139 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1140 }
1141
1142 if (needUnlock) {
1143 mLock.unlock();
1144 }
1145 return ss;
1146}
1147
Eric Laurent6d607012021-07-05 11:54:40 +02001148} // namespace android