blob: ca3e0e0aefaf76cdbac7c048e950816ccf3efd4d [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 Yaoafc0c2e2022-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 Hung2490b2d2023-03-09 20:45:36 -080023#include <algorithm>
Shunkai Yaoafc0c2e2022-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>
Eric Laurentbe21a942023-11-14 16:05:00 +010030#include <android/sysprop/BluetoothProperties.sysprop.h>
Eric Laurent6d607012021-07-05 11:54:40 +020031#include <audio_utils/fixedfft.h>
Eric Laurentbe21a942023-11-14 16:05:00 +010032#include <com_android_media_audio.h>
Eric Laurent6d607012021-07-05 11:54:40 +020033#include <cutils/bitops.h>
Eric Laurent2be8b292021-08-23 09:44:33 -070034#include <hardware/sensors.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020035#include <media/stagefright/foundation/AHandler.h>
36#include <media/stagefright/foundation/AMessage.h>
Andy Hunga461a002022-05-17 10:36:02 -070037#include <media/MediaMetricsItem.h>
Andy Hung560addd2023-01-30 11:58:44 -080038#include <media/QuaternionUtil.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020039#include <media/ShmemCompat.h>
Andy Hung41ccf7f2022-12-14 14:25:49 -080040#include <mediautils/SchedulingPolicyService.h>
Eric Laurent6d607012021-07-05 11:54:40 +020041#include <mediautils/ServiceUtilities.h>
42#include <utils/Thread.h>
43
44#include "Spatializer.h"
45
46namespace android {
47
Eric Laurent6d607012021-07-05 11:54:40 +020048using aidl_utils::binderStatusFromStatusT;
Shunkai Yao49bc61f2023-10-10 19:31:10 +000049using aidl_utils::statusTFromBinderStatus;
Eric Laurent6d607012021-07-05 11:54:40 +020050using android::content::AttributionSourceState;
51using binder::Status;
Eric Laurent2be8b292021-08-23 09:44:33 -070052using media::HeadTrackingMode;
53using media::Pose3f;
Eric Laurent2be8b292021-08-23 09:44:33 -070054using media::SensorPoseProvider;
Shunkai Yao49bc61f2023-10-10 19:31:10 +000055using media::audio::common::HeadTracking;
56using media::audio::common::Spatialization;
57using ::android::internal::ToString;
Eric Laurent2be8b292021-08-23 09:44:33 -070058
Eric Laurent2be8b292021-08-23 09:44:33 -070059using namespace std::chrono_literals;
Eric Laurent6d607012021-07-05 11:54:40 +020060
61#define VALUE_OR_RETURN_BINDER_STATUS(x) \
62 ({ auto _tmp = (x); \
63 if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
64 std::move(_tmp.value()); })
65
Andy Hung4e2547c2022-08-29 14:14:58 -070066static audio_channel_mask_t getMaxChannelMask(
67 const std::vector<audio_channel_mask_t>& masks, size_t channelLimit = SIZE_MAX) {
Andy Hunga461a002022-05-17 10:36:02 -070068 uint32_t maxCount = 0;
69 audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
70 for (auto mask : masks) {
71 const size_t count = audio_channel_count_from_out_mask(mask);
Andy Hung4e2547c2022-08-29 14:14:58 -070072 if (count > channelLimit) continue; // ignore masks greater than channelLimit
Andy Hunga461a002022-05-17 10:36:02 -070073 if (count > maxCount) {
74 maxMask = mask;
75 maxCount = count;
76 }
77 }
78 return maxMask;
79}
80
Andy Hung560addd2023-01-30 11:58:44 -080081static std::vector<float> recordFromTranslationRotationVector(
82 const std::vector<float>& trVector) {
83 auto headToStageOpt = Pose3f::fromVector(trVector);
84 if (!headToStageOpt) return {};
85
86 const auto stageToHead = headToStageOpt.value().inverse();
87 const auto stageToHeadTranslation = stageToHead.translation();
Andy Hunga367cb22023-01-30 11:58:44 -080088 constexpr float RAD_TO_DEGREE = 180.f / M_PI;
89 std::vector<float> record{
Andy Hung560addd2023-01-30 11:58:44 -080090 stageToHeadTranslation[0], stageToHeadTranslation[1], stageToHeadTranslation[2],
91 0.f, 0.f, 0.f};
92 media::quaternionToAngles(stageToHead.rotation(), &record[3], &record[4], &record[5]);
93 record[3] *= RAD_TO_DEGREE;
94 record[4] *= RAD_TO_DEGREE;
95 record[5] *= RAD_TO_DEGREE;
Andy Hunga367cb22023-01-30 11:58:44 -080096 return record;
97}
98
Andy Hung2490b2d2023-03-09 20:45:36 -080099template<typename T>
100static constexpr const T& safe_clamp(const T& value, const T& low, const T& high) {
101 if constexpr (std::is_floating_point_v<T>) {
102 return value != value /* constexpr isnan */
103 ? low : std::clamp(value, low, high);
104 } else /* constexpr */ {
105 return std::clamp(value, low, high);
106 }
107}
108
Eric Laurent6d607012021-07-05 11:54:40 +0200109// ---------------------------------------------------------------------------
110
Eric Laurent8a4259f2021-09-14 16:04:00 +0200111class Spatializer::EngineCallbackHandler : public AHandler {
112public:
113 EngineCallbackHandler(wp<Spatializer> spatializer)
114 : mSpatializer(spatializer) {
115 }
116
117 enum {
118 // Device state callbacks
119 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
120 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
121 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
Eric Laurent9c04de92022-07-20 13:49:47 +0200122 kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
Eric Laurent8a4259f2021-09-14 16:04:00 +0200123 };
124 static constexpr const char *kNumFramesKey = "numFrames";
125 static constexpr const char *kModeKey = "mode";
126 static constexpr const char *kTranslation0Key = "translation0";
127 static constexpr const char *kTranslation1Key = "translation1";
128 static constexpr const char *kTranslation2Key = "translation2";
129 static constexpr const char *kRotation0Key = "rotation0";
130 static constexpr const char *kRotation1Key = "rotation1";
131 static constexpr const char *kRotation2Key = "rotation2";
Eric Laurent9c04de92022-07-20 13:49:47 +0200132 static constexpr const char *kLatencyModesKey = "latencyModes";
133
134 class LatencyModes : public RefBase {
135 public:
136 LatencyModes(audio_io_handle_t output,
137 const std::vector<audio_latency_mode_t>& latencyModes)
138 : mOutput(output), mLatencyModes(latencyModes) {}
139 ~LatencyModes() = default;
140
141 audio_io_handle_t mOutput;
142 std::vector<audio_latency_mode_t> mLatencyModes;
143 };
Eric Laurent8a4259f2021-09-14 16:04:00 +0200144
145 void onMessageReceived(const sp<AMessage> &msg) override {
Andy Hung41ccf7f2022-12-14 14:25:49 -0800146 // No ALooper method to get the tid so update
147 // Spatializer priority on the first message received.
148 std::call_once(mPrioritySetFlag, [](){
149 const pid_t pid = getpid();
150 const pid_t tid = gettid();
151 (void)requestSpatializerPriority(pid, tid);
152 });
153
Eric Laurent9c04de92022-07-20 13:49:47 +0200154 sp<Spatializer> spatializer = mSpatializer.promote();
155 if (spatializer == nullptr) {
156 ALOGW("%s: Cannot promote spatializer", __func__);
157 return;
158 }
Eric Laurent8a4259f2021-09-14 16:04:00 +0200159 switch (msg->what()) {
160 case kWhatOnFramesProcessed: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200161 int numFrames;
162 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
163 ALOGE("%s: Cannot find num frames!", __func__);
164 return;
165 }
166 if (numFrames > 0) {
167 spatializer->calculateHeadPose();
168 }
169 } break;
170 case kWhatOnHeadToStagePose: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200171 std::vector<float> headToStage(sHeadPoseKeys.size());
172 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
173 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
174 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
175 return;
176 }
177 }
178 spatializer->onHeadToStagePoseMsg(headToStage);
179 } break;
180 case kWhatOnActualModeChange: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200181 int mode;
Eric Laurent9c04de92022-07-20 13:49:47 +0200182 if (!msg->findInt32(kModeKey, &mode)) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200183 ALOGE("%s: Cannot find actualMode!", __func__);
184 return;
185 }
186 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
187 } break;
Eric Laurent9c04de92022-07-20 13:49:47 +0200188
189 case kWhatOnLatencyModesChanged: {
190 sp<RefBase> object;
191 if (!msg->findObject(kLatencyModesKey, &object)) {
192 ALOGE("%s: Cannot find latency modes!", __func__);
193 return;
194 }
195 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
196 spatializer->onSupportedLatencyModesChangedMsg(
197 latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
198 } break;
199
Eric Laurent8a4259f2021-09-14 16:04:00 +0200200 default:
201 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
202 }
203 }
204private:
205 wp<Spatializer> mSpatializer;
Andy Hung41ccf7f2022-12-14 14:25:49 -0800206 std::once_flag mPrioritySetFlag;
Eric Laurent8a4259f2021-09-14 16:04:00 +0200207};
208
209const std::vector<const char *> Spatializer::sHeadPoseKeys = {
210 Spatializer::EngineCallbackHandler::kTranslation0Key,
211 Spatializer::EngineCallbackHandler::kTranslation1Key,
212 Spatializer::EngineCallbackHandler::kTranslation2Key,
213 Spatializer::EngineCallbackHandler::kRotation0Key,
214 Spatializer::EngineCallbackHandler::kRotation1Key,
215 Spatializer::EngineCallbackHandler::kRotation2Key,
216};
217
Eric Laurentbe21a942023-11-14 16:05:00 +0100218// Mapping table between strings read form property bluetooth.core.le.dsa_transport_preference
219// and low latency modes emums.
220//TODO b/273373363: use AIDL enum when available
221const std::map<std::string, audio_latency_mode_t> Spatializer::sStringToLatencyModeMap = {
222 {"le-acl", AUDIO_LATENCY_MODE_LOW},
223 {"iso-sw", AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE},
224 {"iso-hw", AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE},
225};
226
227void Spatializer::loadOrderedLowLatencyModes() {
228 if (!com::android::media::audio::dsa_over_bt_le_audio()) {
229 return;
230 }
231 auto latencyModesStrs = android::sysprop::BluetoothProperties::dsa_transport_preference();
Andy Hung79eacdb2023-11-30 19:34:24 -0800232 audio_utils::lock_guard lock(mMutex);
Eric Laurentbe21a942023-11-14 16:05:00 +0100233 // First load preferred low latency modes ordered from the property
234 for (auto str : latencyModesStrs) {
235 if (!str.has_value()) continue;
236 if (auto it = sStringToLatencyModeMap.find(str.value());
237 it != sStringToLatencyModeMap.end()) {
238 mOrderedLowLatencyModes.push_back(it->second);
239 }
240 }
241 // Then add unlisted latency modes at the end of the ordered list
242 for (auto it : sStringToLatencyModeMap) {
243 if (std::find(mOrderedLowLatencyModes.begin(), mOrderedLowLatencyModes.end(), it.second)
244 == mOrderedLowLatencyModes.end()) {
245 mOrderedLowLatencyModes.push_back(it.second);
246 }
247 }
248}
249
Eric Laurent8a4259f2021-09-14 16:04:00 +0200250// ---------------------------------------------------------------------------
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000251sp<Spatializer> Spatializer::create(SpatializerPolicyCallback* callback,
252 const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
Eric Laurent6d607012021-07-05 11:54:40 +0200253 sp<Spatializer> spatializer;
254
Eric Laurent6d607012021-07-05 11:54:40 +0200255 if (effectsFactoryHal == nullptr) {
256 ALOGW("%s failed to create effect factory interface", __func__);
257 return spatializer;
258 }
259
260 std::vector<effect_descriptor_t> descriptors;
Shunkai Yao8d6489a2023-04-18 23:14:25 +0000261 status_t status = effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200262 if (status != NO_ERROR) {
263 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
264 return spatializer;
265 }
266 ALOG_ASSERT(!descriptors.empty(),
267 "%s getDescriptors() returned no error but empty list", __func__);
268
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +0000269 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200270 sp<EffectHalInterface> effect;
271 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
272 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Mikhail Naganov89c22e42023-06-14 15:49:59 -0700273 ALOGI("%s FX create status %d effect %p", __func__, status, effect.get());
Eric Laurent6d607012021-07-05 11:54:40 +0200274
275 if (status == NO_ERROR && effect != nullptr) {
276 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700277 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
278 spatializer.clear();
Mikhail Naganov89c22e42023-06-14 15:49:59 -0700279 ALOGW("%s loadEngine error: %d effect %p", __func__, status, effect.get());
Andy Hung4e2547c2022-08-29 14:14:58 -0700280 } else {
Eric Laurentbe21a942023-11-14 16:05:00 +0100281 spatializer->loadOrderedLowLatencyModes();
Mikhail Naganov89c22e42023-06-14 15:49:59 -0700282 spatializer->mLocalLog.log("%s with effect Id %p", __func__, effect.get());
Eric Laurent2be8b292021-08-23 09:44:33 -0700283 }
Eric Laurent6d607012021-07-05 11:54:40 +0200284 }
285
286 return spatializer;
287}
288
Eric Laurent2be8b292021-08-23 09:44:33 -0700289Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
290 : mEngineDescriptor(engineDescriptor),
291 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200292 ALOGV("%s", __func__);
Andy Hung225aef62022-12-06 16:33:20 -0800293 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent6d607012021-07-05 11:54:40 +0200294}
295
Eric Laurent8a4259f2021-09-14 16:04:00 +0200296void Spatializer::onFirstRef() {
297 mLooper = new ALooper;
298 mLooper->setName("Spatializer-looper");
299 mLooper->start(
300 /*runOnCallingThread*/false,
301 /*canCallJava*/ false,
Andy Hungbf1777b2022-11-07 20:09:20 -0800302 PRIORITY_URGENT_AUDIO);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200303
304 mHandler = new EngineCallbackHandler(this);
305 mLooper->registerHandler(mHandler);
306}
307
Eric Laurent6d607012021-07-05 11:54:40 +0200308Spatializer::~Spatializer() {
309 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200310 if (mLooper != nullptr) {
311 mLooper->stop();
312 mLooper->unregisterHandler(mHandler->id());
313 }
314 mLooper.clear();
315 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200316}
317
Andy Hung8a7ecff2022-08-17 17:27:32 -0700318static std::string channelMaskVectorToString(
319 const std::vector<audio_channel_mask_t>& masks) {
320 std::stringstream ss;
321 for (const auto &mask : masks) {
322 if (ss.tellp() != 0) ss << "|";
323 ss << mask;
324 }
325 return ss.str();
326}
327
Eric Laurent2be8b292021-08-23 09:44:33 -0700328status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
329 ALOGV("%s", __func__);
330
331 std::vector<bool> supportsHeadTracking;
332 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
333 &supportsHeadTracking);
334 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700335 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700336 return status;
337 }
338 mSupportsHeadTracking = supportsHeadTracking[0];
339
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000340 std::vector<Spatialization::Level> spatializationLevels;
Andy Hung119dbdb2022-05-11 19:20:13 -0700341 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
342 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700343 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700344 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700345 return status;
346 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700347 bool noneLevelFound = false;
348 bool activeLevelFound = false;
349 for (const auto spatializationLevel : spatializationLevels) {
350 if (!aidl_utils::isValidEnum(spatializationLevel)) {
351 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
352 continue;
353 }
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000354 if (spatializationLevel == Spatialization::Level::NONE) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700355 noneLevelFound = true;
356 } else {
357 activeLevelFound = true;
358 }
359 // we don't detect duplicates.
360 mLevels.emplace_back(spatializationLevel);
361 }
362 if (!noneLevelFound || !activeLevelFound) {
363 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
364 " and another valid level", __func__);
365 return BAD_VALUE;
366 }
367
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000368 std::vector<Spatialization::Mode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700369 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700370 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700371 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700372 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700373 return status;
374 }
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +0000375
Andy Hung119dbdb2022-05-11 19:20:13 -0700376 for (const auto spatializationMode : spatializationModes) {
377 if (!aidl_utils::isValidEnum(spatializationMode)) {
378 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
379 continue;
380 }
381 // we don't detect duplicates.
382 mSpatializationModes.emplace_back(spatializationMode);
383 }
384 if (mSpatializationModes.empty()) {
385 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
386 return BAD_VALUE;
387 }
388
389 std::vector<audio_channel_mask_t> channelMasks;
390 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
391 &channelMasks);
392 if (status != NO_ERROR) {
393 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
394 return status;
395 }
396 for (const auto channelMask : channelMasks) {
Andy Hung481bfe32023-12-18 14:00:29 -0800397 const bool channel_mask_spatialized =
398 com_android_media_audio_stereo_spatialization()
399 ? audio_channel_mask_contains_stereo(channelMask)
400 : audio_is_channel_mask_spatialized(channelMask);
401 if (!channel_mask_spatialized) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700402 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
403 continue;
404 }
405 // we don't detect duplicates.
406 mChannelMasks.emplace_back(channelMask);
407 }
408 if (mChannelMasks.empty()) {
409 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
410 return BAD_VALUE;
411 }
Andy Hunga461a002022-05-17 10:36:02 -0700412
Eric Laurentbe21a942023-11-14 16:05:00 +0100413 //TODO b/273373363: use AIDL enum when available
414 if (com::android::media::audio::dsa_over_bt_le_audio()
415 && mSupportsHeadTracking) {
416 mHeadtrackingConnectionMode = HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED;
417 std::vector<uint8_t> headtrackingConnectionModes;
418 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_HEADTRACKING_CONNECTION,
419 &headtrackingConnectionModes);
420 if (status == NO_ERROR) {
421 for (const auto htConnectionMode : headtrackingConnectionModes) {
422 if (htConnectionMode < HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED ||
423 htConnectionMode > HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_TUNNEL) {
424 ALOGW("%s: ignoring HT connection mode:%d", __func__, (int)htConnectionMode);
425 continue;
426 }
427 mSupportedHeadtrackingConnectionModes.insert(
428 static_cast<headtracking_connection_t> (htConnectionMode));
429 }
430 ALOGW_IF(mSupportedHeadtrackingConnectionModes.find(
431 HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED)
432 == mSupportedHeadtrackingConnectionModes.end(),
433 "%s: HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED not reported", __func__);
434 }
435 }
436
Andy Hunga461a002022-05-17 10:36:02 -0700437 // Currently we expose only RELATIVE_WORLD.
438 // This is a limitation of the head tracking library based on a UX choice.
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000439 mHeadTrackingModes.push_back(HeadTracking::Mode::DISABLED);
Andy Hunga461a002022-05-17 10:36:02 -0700440 if (mSupportsHeadTracking) {
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000441 mHeadTrackingModes.push_back(HeadTracking::Mode::RELATIVE_WORLD);
Andy Hunga461a002022-05-17 10:36:02 -0700442 }
443 mediametrics::LogItem(mMetricsId)
444 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
Andy Hung8a7ecff2022-08-17 17:27:32 -0700445 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
Andy Hunga461a002022-05-17 10:36:02 -0700446 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
447 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
448 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
449 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
450 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700451 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700452}
453
Andy Hung8aa43c02022-09-13 18:53:06 -0700454/* static */
455void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
456 mediametrics::LogItem(kDefaultMetricsId)
457 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
458 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
459 .set(AMEDIAMETRICS_PROP_LEVELS, "")
460 .set(AMEDIAMETRICS_PROP_MODES, "")
461 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
462 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
463 .record();
464}
465
Eric Laurent2be8b292021-08-23 09:44:33 -0700466/** Gets the channel mask, sampling rate and format set for the spatializer input. */
467audio_config_base_t Spatializer::getAudioInConfig() const {
Andy Hung79eacdb2023-11-30 19:34:24 -0800468 audio_utils::lock_guard lock(mMutex);
Eric Laurent2be8b292021-08-23 09:44:33 -0700469 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
470 // For now use highest supported channel count
Andy Hung4e2547c2022-08-29 14:14:58 -0700471 config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
Eric Laurent2be8b292021-08-23 09:44:33 -0700472 return config;
473}
474
Eric Laurent6d607012021-07-05 11:54:40 +0200475status_t Spatializer::registerCallback(
476 const sp<media::INativeSpatializerCallback>& callback) {
Andy Hung79eacdb2023-11-30 19:34:24 -0800477 audio_utils::lock_guard lock(mMutex);
Eric Laurent6d607012021-07-05 11:54:40 +0200478 if (callback == nullptr) {
479 return BAD_VALUE;
480 }
481
Eric Laurentd6bee3a2022-08-31 16:07:50 +0200482 if (mSpatializerCallback != nullptr) {
483 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
484 ALOGW("%s: Registering callback %p again",
485 __func__, mSpatializerCallback.get());
486 return NO_ERROR;
487 }
488 ALOGE("%s: Already one client registered with callback %p",
489 __func__, mSpatializerCallback.get());
490 return INVALID_OPERATION;
491 }
492
Eric Laurent6d607012021-07-05 11:54:40 +0200493 sp<IBinder> binder = IInterface::asBinder(callback);
494 status_t status = binder->linkToDeath(this);
495 if (status == NO_ERROR) {
496 mSpatializerCallback = callback;
497 }
498 ALOGV("%s status %d", __func__, status);
499 return status;
500}
501
502// IBinder::DeathRecipient
503void Spatializer::binderDied(__unused const wp<IBinder> &who) {
504 {
Andy Hung79eacdb2023-11-30 19:34:24 -0800505 audio_utils::lock_guard lock(mMutex);
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000506 mLevel = Spatialization::Level::NONE;
Eric Laurent6d607012021-07-05 11:54:40 +0200507 mSpatializerCallback.clear();
508 }
509 ALOGV("%s", __func__);
510 mPolicyCallback->onCheckSpatializer();
511}
512
513// ISpatializer
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000514Status Spatializer::getSupportedLevels(std::vector<Spatialization::Level> *levels) {
Eric Laurent6d607012021-07-05 11:54:40 +0200515 ALOGV("%s", __func__);
516 if (levels == nullptr) {
517 return binderStatusFromStatusT(BAD_VALUE);
518 }
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000519 // Spatialization::Level::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700520 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200521 return Status::ok();
522}
523
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000524Status Spatializer::setLevel(Spatialization::Level level) {
525 ALOGV("%s level %s", __func__, ToString(level).c_str());
526 mLocalLog.log("%s with %s", __func__, ToString(level).c_str());
527 if (level != Spatialization::Level::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700528 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200529 return binderStatusFromStatusT(BAD_VALUE);
530 }
531 sp<media::INativeSpatializerCallback> callback;
532 bool levelChanged = false;
533 {
Andy Hung79eacdb2023-11-30 19:34:24 -0800534 audio_utils::lock_guard lock(mMutex);
Eric Laurent6d607012021-07-05 11:54:40 +0200535 levelChanged = mLevel != level;
536 mLevel = level;
537 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700538
539 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200540 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700541 }
Eric Laurent9249d342022-03-18 11:55:56 +0100542 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200543 }
544
545 if (levelChanged) {
546 mPolicyCallback->onCheckSpatializer();
547 if (callback != nullptr) {
548 callback->onLevelChanged(level);
549 }
550 }
551 return Status::ok();
552}
553
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000554Status Spatializer::getLevel(Spatialization::Level *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200555 if (level == nullptr) {
556 return binderStatusFromStatusT(BAD_VALUE);
557 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800558 audio_utils::lock_guard lock(mMutex);
Eric Laurent6d607012021-07-05 11:54:40 +0200559 *level = mLevel;
560 ALOGV("%s level %d", __func__, (int)*level);
561 return Status::ok();
562}
563
Eric Laurentc87402b2021-09-17 16:49:42 +0200564Status Spatializer::isHeadTrackingSupported(bool *supports) {
565 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
566 if (supports == nullptr) {
567 return binderStatusFromStatusT(BAD_VALUE);
568 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800569 audio_utils::lock_guard lock(mMutex);
Eric Laurentc87402b2021-09-17 16:49:42 +0200570 *supports = mSupportsHeadTracking;
571 return Status::ok();
572}
573
Eric Laurent6d607012021-07-05 11:54:40 +0200574Status Spatializer::getSupportedHeadTrackingModes(
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000575 std::vector<HeadTracking::Mode>* modes) {
Andy Hung79eacdb2023-11-30 19:34:24 -0800576 audio_utils::lock_guard lock(mMutex);
Eric Laurent6d607012021-07-05 11:54:40 +0200577 ALOGV("%s", __func__);
578 if (modes == nullptr) {
579 return binderStatusFromStatusT(BAD_VALUE);
580 }
Andy Hunga461a002022-05-17 10:36:02 -0700581 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200582 return Status::ok();
583}
584
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000585Status Spatializer::setDesiredHeadTrackingMode(HeadTracking::Mode mode) {
586 ALOGV("%s mode %s", __func__, ToString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700587
588 if (!mSupportsHeadTracking) {
589 return binderStatusFromStatusT(INVALID_OPERATION);
590 }
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000591 mLocalLog.log("%s with %s", __func__, ToString(mode).c_str());
Andy Hung79eacdb2023-11-30 19:34:24 -0800592 audio_utils::lock_guard lock(mMutex);
Eric Laurent2be8b292021-08-23 09:44:33 -0700593 switch (mode) {
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000594 case HeadTracking::Mode::OTHER:
Eric Laurent2be8b292021-08-23 09:44:33 -0700595 return binderStatusFromStatusT(BAD_VALUE);
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000596 case HeadTracking::Mode::DISABLED:
Eric Laurent2be8b292021-08-23 09:44:33 -0700597 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
598 break;
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000599 case HeadTracking::Mode::RELATIVE_WORLD:
Eric Laurent2be8b292021-08-23 09:44:33 -0700600 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
601 break;
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000602 case HeadTracking::Mode::RELATIVE_SCREEN:
Eric Laurent2be8b292021-08-23 09:44:33 -0700603 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
604 break;
605 }
606
Eric Laurent11094172022-04-05 18:27:42 +0200607 checkPoseController_l();
608 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700609
610 return Status::ok();
611}
612
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000613Status Spatializer::getActualHeadTrackingMode(HeadTracking::Mode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200614 if (mode == nullptr) {
615 return binderStatusFromStatusT(BAD_VALUE);
616 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800617 audio_utils::lock_guard lock(mMutex);
Eric Laurent2be8b292021-08-23 09:44:33 -0700618 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200619 ALOGV("%s mode %d", __func__, (int)*mode);
620 return Status::ok();
621}
622
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700623Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200624 if (!mSupportsHeadTracking) {
625 return binderStatusFromStatusT(INVALID_OPERATION);
626 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800627 audio_utils::lock_guard lock(mMutex);
Eric Laurent2be8b292021-08-23 09:44:33 -0700628 if (mPoseController != nullptr) {
629 mPoseController->recenter();
630 }
Eric Laurent6d607012021-07-05 11:54:40 +0200631 return Status::ok();
632}
633
634Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200635 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200636 if (!mSupportsHeadTracking) {
637 return binderStatusFromStatusT(INVALID_OPERATION);
638 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700639 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
640 if (!maybePose.has_value()) {
641 ALOGW("Invalid screenToStage vector.");
642 return binderStatusFromStatusT(BAD_VALUE);
643 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800644 audio_utils::lock_guard lock(mMutex);
Eric Laurent2be8b292021-08-23 09:44:33 -0700645 if (mPoseController != nullptr) {
Andy Hunga367cb22023-01-30 11:58:44 -0800646 mLocalLog.log("%s with screenToStage %s", __func__,
647 media::VectorRecorder::toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700648 mPoseController->setScreenToStagePose(maybePose.value());
649 }
Eric Laurent6d607012021-07-05 11:54:40 +0200650 return Status::ok();
651}
652
653Status Spatializer::release() {
654 ALOGV("%s", __func__);
655 bool levelChanged = false;
656 {
Andy Hung79eacdb2023-11-30 19:34:24 -0800657 audio_utils::lock_guard lock(mMutex);
Eric Laurent6d607012021-07-05 11:54:40 +0200658 if (mSpatializerCallback == nullptr) {
659 return binderStatusFromStatusT(INVALID_OPERATION);
660 }
661
662 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
663 binder->unlinkToDeath(this);
664 mSpatializerCallback.clear();
665
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000666 levelChanged = mLevel != Spatialization::Level::NONE;
667 mLevel = Spatialization::Level::NONE;
Eric Laurent6d607012021-07-05 11:54:40 +0200668 }
669
670 if (levelChanged) {
671 mPolicyCallback->onCheckSpatializer();
672 }
673 return Status::ok();
674}
675
Eric Laurent2be8b292021-08-23 09:44:33 -0700676Status Spatializer::setHeadSensor(int sensorHandle) {
677 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200678 if (!mSupportsHeadTracking) {
679 return binderStatusFromStatusT(INVALID_OPERATION);
680 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800681 audio_utils::lock_guard lock(mMutex);
Andy Hungba2a61a2022-05-20 12:00:28 -0700682 if (mHeadSensor != sensorHandle) {
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +0000683 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700684 mHeadSensor = sensorHandle;
685 checkPoseController_l();
686 checkSensorsState_l();
687 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700688 return Status::ok();
689}
690
691Status Spatializer::setScreenSensor(int sensorHandle) {
692 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200693 if (!mSupportsHeadTracking) {
694 return binderStatusFromStatusT(INVALID_OPERATION);
695 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800696 audio_utils::lock_guard lock(mMutex);
Andy Hungba2a61a2022-05-20 12:00:28 -0700697 if (mScreenSensor != sensorHandle) {
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +0000698 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700699 mScreenSensor = sensorHandle;
700 // TODO: consider a new method setHeadAndScreenSensor()
701 // because we generally set both at the same time.
702 // This will avoid duplicated work and recentering.
703 checkSensorsState_l();
704 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700705 return Status::ok();
706}
707
708Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
709 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +0000710 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Andy Hung2490b2d2023-03-09 20:45:36 -0800711 const float angle = safe_clamp(physicalToLogicalAngle, 0.f, (float)(2. * M_PI));
712 // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
713 ALOGI_IF(angle != physicalToLogicalAngle,
714 "%s: clamping %f to %f", __func__, physicalToLogicalAngle, angle);
Andy Hung79eacdb2023-11-30 19:34:24 -0800715 audio_utils::lock_guard lock(mMutex);
Andy Hung2490b2d2023-03-09 20:45:36 -0800716 mDisplayOrientation = angle;
Eric Laurent2be8b292021-08-23 09:44:33 -0700717 if (mPoseController != nullptr) {
Andy Hung2490b2d2023-03-09 20:45:36 -0800718 // This turns on the rate-limiter.
719 mPoseController->setDisplayOrientation(angle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700720 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200721 if (mEngine != nullptr) {
722 setEffectParameter_l(
Andy Hung2490b2d2023-03-09 20:45:36 -0800723 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{angle});
Eric Laurent16ddaf42021-09-17 15:00:35 +0200724 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700725 return Status::ok();
726}
727
728Status Spatializer::setHingeAngle(float hingeAngle) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700729 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
Andy Hung2490b2d2023-03-09 20:45:36 -0800730 mLocalLog.log("%s with %f", __func__, hingeAngle);
731 const float angle = safe_clamp(hingeAngle, 0.f, (float)(2. * M_PI));
732 // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
733 ALOGI_IF(angle != hingeAngle,
734 "%s: clamping %f to %f", __func__, hingeAngle, angle);
Andy Hung79eacdb2023-11-30 19:34:24 -0800735 audio_utils::lock_guard lock(mMutex);
Andy Hung2490b2d2023-03-09 20:45:36 -0800736 mHingeAngle = angle;
Eric Laurent2be8b292021-08-23 09:44:33 -0700737 if (mEngine != nullptr) {
Andy Hung2490b2d2023-03-09 20:45:36 -0800738 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{angle});
739 }
740 return Status::ok();
741}
742
743Status Spatializer::setFoldState(bool folded) {
744 ALOGV("%s foldState %d", __func__, (int)folded);
745 mLocalLog.log("%s with %d", __func__, (int)folded);
Andy Hung79eacdb2023-11-30 19:34:24 -0800746 audio_utils::lock_guard lock(mMutex);
Andy Hung2490b2d2023-03-09 20:45:36 -0800747 mFoldedState = folded;
748 if (mEngine != nullptr) {
749 // we don't suppress multiple calls with the same folded state - that's
750 // done at the caller.
751 setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE, std::vector<uint8_t>{mFoldedState});
Eric Laurent2be8b292021-08-23 09:44:33 -0700752 }
753 return Status::ok();
754}
755
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000756Status Spatializer::getSupportedModes(std::vector<Spatialization::Mode> *modes) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700757 ALOGV("%s", __func__);
758 if (modes == nullptr) {
759 return binderStatusFromStatusT(BAD_VALUE);
760 }
761 *modes = mSpatializationModes;
762 return Status::ok();
763}
764
Eric Laurent67816e32021-09-16 15:18:40 +0200765Status Spatializer::registerHeadTrackingCallback(
766 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
767 ALOGV("%s callback %p", __func__, callback.get());
Andy Hung79eacdb2023-11-30 19:34:24 -0800768 audio_utils::lock_guard lock(mMutex);
Eric Laurent67816e32021-09-16 15:18:40 +0200769 if (!mSupportsHeadTracking) {
770 return binderStatusFromStatusT(INVALID_OPERATION);
771 }
772 mHeadTrackingCallback = callback;
773 return Status::ok();
774}
775
Eric Laurentc87402b2021-09-17 16:49:42 +0200776Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
777 ALOGV("%s key %d", __func__, key);
Andy Hung79eacdb2023-11-30 19:34:24 -0800778 audio_utils::lock_guard lock(mMutex);
Eric Laurentc87402b2021-09-17 16:49:42 +0200779 status_t status = INVALID_OPERATION;
780 if (mEngine != nullptr) {
781 status = setEffectParameter_l(key, value);
782 }
783 return binderStatusFromStatusT(status);
784}
785
786Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700787 ALOGV("%s key %d value size %d", __func__, key,
788 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200789 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700790 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200791 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800792 audio_utils::lock_guard lock(mMutex);
Eric Laurentc87402b2021-09-17 16:49:42 +0200793 status_t status = INVALID_OPERATION;
794 if (mEngine != nullptr) {
795 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
796 status = getEffectParameter_l(key, value);
797 }
798 return binderStatusFromStatusT(status);
799}
800
801Status Spatializer::getOutput(int *output) {
802 ALOGV("%s", __func__);
803 if (output == nullptr) {
804 binderStatusFromStatusT(BAD_VALUE);
805 }
Andy Hung79eacdb2023-11-30 19:34:24 -0800806 audio_utils::lock_guard lock(mMutex);
Eric Laurentc87402b2021-09-17 16:49:42 +0200807 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
808 ALOGV("%s got output %d", __func__, *output);
809 return Status::ok();
810}
811
Eric Laurent2be8b292021-08-23 09:44:33 -0700812// SpatializerPoseController::Listener
813void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
814 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200815 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
816 "onHeadToStagePose() called with no head tracking support!");
817
Eric Laurent2be8b292021-08-23 09:44:33 -0700818 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200819 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
820 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200821 sp<AMessage> msg =
822 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
823 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
824 msg->setFloat(sHeadPoseKeys[i], vec[i]);
825 }
826 msg->post();
827}
828
Eric Laurentbdecc052022-10-21 11:28:32 +0200829void Spatializer::resetEngineHeadPose_l() {
830 ALOGV("%s mEngine %p", __func__, mEngine.get());
831 if (mEngine == nullptr) {
832 return;
833 }
834 const std::vector<float> headToStage(6, 0.0);
835 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
836 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000837 std::vector<HeadTracking::Mode>{HeadTracking::Mode::DISABLED});
Eric Laurentbdecc052022-10-21 11:28:32 +0200838}
839
Eric Laurent8a4259f2021-09-14 16:04:00 +0200840void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
841 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200842 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700843 {
Andy Hung79eacdb2023-11-30 19:34:24 -0800844 audio_utils::lock_guard lock(mMutex);
Eric Laurent67816e32021-09-16 15:18:40 +0200845 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700846 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200847 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Andy Hung560addd2023-01-30 11:58:44 -0800848 const auto record = recordFromTranslationRotationVector(headToStage);
849 mPoseRecorder.record(record);
850 mPoseDurableRecorder.record(record);
Eric Laurent2be8b292021-08-23 09:44:33 -0700851 }
852 }
853
854 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200855 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700856 }
857}
858
859void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao56e43f02022-08-30 03:14:50 +0000860 std::string modeStr = media::toString(mode);
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +0000861 ALOGV("%s(%s)", __func__, modeStr.c_str());
Shunkai Yao56e43f02022-08-30 03:14:50 +0000862 sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200863 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
864 msg->post();
865}
866
867void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
868 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200869 sp<media::ISpatializerHeadTrackingCallback> callback;
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000870 HeadTracking::Mode spatializerMode;
Eric Laurent2be8b292021-08-23 09:44:33 -0700871 {
Andy Hung79eacdb2023-11-30 19:34:24 -0800872 audio_utils::lock_guard lock(mMutex);
Eric Laurent2be8b292021-08-23 09:44:33 -0700873 if (!mSupportsHeadTracking) {
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000874 spatializerMode = HeadTracking::Mode::DISABLED;
Eric Laurent2be8b292021-08-23 09:44:33 -0700875 } else {
876 switch (mode) {
877 case HeadTrackingMode::STATIC:
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000878 spatializerMode = HeadTracking::Mode::DISABLED;
Eric Laurent2be8b292021-08-23 09:44:33 -0700879 break;
880 case HeadTrackingMode::WORLD_RELATIVE:
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000881 spatializerMode = HeadTracking::Mode::RELATIVE_WORLD;
Eric Laurent2be8b292021-08-23 09:44:33 -0700882 break;
883 case HeadTrackingMode::SCREEN_RELATIVE:
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000884 spatializerMode = HeadTracking::Mode::RELATIVE_SCREEN;
Eric Laurent2be8b292021-08-23 09:44:33 -0700885 break;
886 default:
887 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
888 }
889 }
890 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200891 if (mEngine != nullptr) {
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000892 if (spatializerMode == HeadTracking::Mode::DISABLED) {
Eric Laurentbdecc052022-10-21 11:28:32 +0200893 resetEngineHeadPose_l();
894 } else {
895 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
Shunkai Yao49bc61f2023-10-10 19:31:10 +0000896 std::vector<HeadTracking::Mode>{spatializerMode});
Eric Laurentbe21a942023-11-14 16:05:00 +0100897 setEngineHeadtrackingConnectionMode_l();
Eric Laurentbdecc052022-10-21 11:28:32 +0200898 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200899 }
Eric Laurent67816e32021-09-16 15:18:40 +0200900 callback = mHeadTrackingCallback;
Andy Hung8702c312023-01-30 11:58:44 -0800901 mLocalLog.log("%s: updating mode to %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700902 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200903 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700904 callback->onHeadTrackingModeChanged(spatializerMode);
905 }
906}
907
Eric Laurentbe21a942023-11-14 16:05:00 +0100908void Spatializer::setEngineHeadtrackingConnectionMode_l() {
909 if (!com::android::media::audio::dsa_over_bt_le_audio()) {
910 return;
911 }
912 if (mActualHeadTrackingMode != HeadTracking::Mode::DISABLED
913 && !mSupportedHeadtrackingConnectionModes.empty()) {
914 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_CONNECTION,
915 static_cast<uint8_t>(mHeadtrackingConnectionMode),
916 static_cast<uint32_t>(mHeadSensor));
917 }
918}
919
920void Spatializer::sortSupportedLatencyModes_l() {
921 if (!com::android::media::audio::dsa_over_bt_le_audio()) {
922 return;
923 }
924 std::sort(mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
925 [this](audio_latency_mode_t x, audio_latency_mode_t y) {
926 auto itX = std::find(mOrderedLowLatencyModes.begin(),
927 mOrderedLowLatencyModes.end(), x);
928 auto itY = std::find(mOrderedLowLatencyModes.begin(),
929 mOrderedLowLatencyModes.end(), y);
930 return itX < itY;
931 });
932}
933
Eric Laurent15903592022-02-24 20:44:36 +0100934status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200935 bool outputChanged = false;
936 sp<media::INativeSpatializerCallback> callback;
937
Eric Laurent2be8b292021-08-23 09:44:33 -0700938 {
Andy Hung79eacdb2023-11-30 19:34:24 -0800939 audio_utils::lock_guard lock(mMutex);
Eric Laurent2be8b292021-08-23 09:44:33 -0700940 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +0000941 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
942 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700943 if (mOutput != AUDIO_IO_HANDLE_NONE) {
944 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
945 // remove FX instance
946 mEngine->setEnabled(false);
947 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100948 mPoseController.reset();
Eric Laurentee398ad2022-05-03 18:19:35 +0200949 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700950 }
Eric Laurentee398ad2022-05-03 18:19:35 +0200951
Eric Laurent2be8b292021-08-23 09:44:33 -0700952 // create FX instance on output
953 AttributionSourceState attributionSource = AttributionSourceState();
954 mEngine = new AudioEffect(attributionSource);
Atneya Nair20e6cc82022-05-17 20:12:37 -0400955 mEngine->set(nullptr /* type */, &mEngineDescriptor.uuid, 0 /* priority */,
956 wp<AudioEffect::IAudioEffectCallback>::fromExisting(this),
957 AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */, false /* probe */,
958 true /* notifyFramesProcessed */);
Eric Laurent2be8b292021-08-23 09:44:33 -0700959 status_t status = mEngine->initCheck();
960 ALOGV("%s mEngine create status %d", __func__, (int)status);
961 if (status != NO_ERROR) {
962 return status;
963 }
964
Eric Laurent4a872862021-10-11 17:06:47 +0200965 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700966 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200967 mNumActiveTracks = numActiveTracks;
Eric Laurentee398ad2022-05-03 18:19:35 +0200968 AudioSystem::addSupportedLatencyModesCallback(this);
969
970 std::vector<audio_latency_mode_t> latencyModes;
971 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
972 if (status == OK) {
973 mSupportedLatencyModes = latencyModes;
Eric Laurentbe21a942023-11-14 16:05:00 +0100974 sortSupportedLatencyModes_l();
Eric Laurentee398ad2022-05-03 18:19:35 +0200975 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700976
Eric Laurent11094172022-04-05 18:27:42 +0200977 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200978 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200979 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100980 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200981 }
Eric Laurent4a872862021-10-11 17:06:47 +0200982 callback = mSpatializerCallback;
Andy Hung2490b2d2023-03-09 20:45:36 -0800983
984 // Restore common effect state.
985 setEffectParameter_l(SPATIALIZER_PARAM_DISPLAY_ORIENTATION,
986 std::vector<float>{mDisplayOrientation});
987 setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE,
988 std::vector<uint8_t>{mFoldedState});
989 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE,
990 std::vector<float>{mHingeAngle});
Eric Laurent6d607012021-07-05 11:54:40 +0200991 }
Eric Laurent4a872862021-10-11 17:06:47 +0200992
993 if (outputChanged && callback != nullptr) {
994 callback->onOutputChanged(output);
995 }
996
Eric Laurent6d607012021-07-05 11:54:40 +0200997 return NO_ERROR;
998}
999
1000audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -07001001 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +02001002 sp<media::INativeSpatializerCallback> callback;
1003
1004 {
Andy Hung79eacdb2023-11-30 19:34:24 -08001005 audio_utils::lock_guard lock(mMutex);
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001006 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +02001007 ALOGV("%s mOutput %d", __func__, (int)mOutput);
1008 if (mOutput == AUDIO_IO_HANDLE_NONE) {
1009 return output;
1010 }
1011 // remove FX instance
1012 mEngine->setEnabled(false);
1013 mEngine.clear();
Eric Laurentee398ad2022-05-03 18:19:35 +02001014 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +02001015 output = mOutput;
1016 mOutput = AUDIO_IO_HANDLE_NONE;
1017 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +02001018 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +02001019 }
Eric Laurent4a872862021-10-11 17:06:47 +02001020
1021 if (callback != nullptr) {
1022 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
1023 }
Eric Laurent6d607012021-07-05 11:54:40 +02001024 return output;
1025}
1026
Eric Laurentee398ad2022-05-03 18:19:35 +02001027void Spatializer::onSupportedLatencyModesChanged(
1028 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
Eric Laurent9c04de92022-07-20 13:49:47 +02001029 ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
1030 sp<AMessage> msg =
1031 new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
1032 msg->setObject(EngineCallbackHandler::kLatencyModesKey,
1033 sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
1034 msg->post();
1035}
1036
1037void Spatializer::onSupportedLatencyModesChangedMsg(
1038 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
Andy Hung79eacdb2023-11-30 19:34:24 -08001039 audio_utils::lock_guard lock(mMutex);
Eric Laurent9c04de92022-07-20 13:49:47 +02001040 ALOGV("%s output %d mOutput %d num modes %zu",
1041 __func__, (int)output, (int)mOutput, modes.size());
Eric Laurentee398ad2022-05-03 18:19:35 +02001042 if (output == mOutput) {
Eric Laurent9c04de92022-07-20 13:49:47 +02001043 mSupportedLatencyModes = std::move(modes);
Eric Laurentbe21a942023-11-14 16:05:00 +01001044 sortSupportedLatencyModes_l();
Eric Laurentee398ad2022-05-03 18:19:35 +02001045 checkSensorsState_l();
1046 }
1047}
1048
Eric Laurent15903592022-02-24 20:44:36 +01001049void Spatializer::updateActiveTracks(size_t numActiveTracks) {
Andy Hung79eacdb2023-11-30 19:34:24 -08001050 audio_utils::lock_guard lock(mMutex);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001051 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001052 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001053 mNumActiveTracks = numActiveTracks;
1054 checkEngineState_l();
1055 checkSensorsState_l();
1056 }
Eric Laurent15903592022-02-24 20:44:36 +01001057}
1058
Eric Laurentbe21a942023-11-14 16:05:00 +01001059//TODO b/273373363: use AIDL enum when available
1060audio_latency_mode_t Spatializer::selectHeadtrackingConnectionMode_l() {
1061 if (!com::android::media::audio::dsa_over_bt_le_audio()) {
1062 return AUDIO_LATENCY_MODE_LOW;
1063 }
1064 // mSupportedLatencyModes is ordered according to system preferences loaded in
1065 // mOrderedLowLatencyModes
1066 mHeadtrackingConnectionMode = HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED;
1067 audio_latency_mode_t requestedLatencyMode = mSupportedLatencyModes[0];
1068 if (requestedLatencyMode == AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
1069 if (mSupportedHeadtrackingConnectionModes.find(
1070 HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_TUNNEL)
1071 != mSupportedHeadtrackingConnectionModes.end()) {
1072 mHeadtrackingConnectionMode = HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_TUNNEL;
1073 } else if (mSupportedHeadtrackingConnectionModes.find(
1074 HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_SW)
1075 != mSupportedHeadtrackingConnectionModes.end()) {
1076 mHeadtrackingConnectionMode = HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_SW;
1077 } else {
1078 // if the engine does not support direct reading of IMU data, do not allow
1079 // DYNAMIC_SPATIAL_AUDIO_HARDWARE mode and fallback to next mode
1080 if (mSupportedLatencyModes.size() > 1) {
1081 requestedLatencyMode = mSupportedLatencyModes[1];
1082 } else {
1083 // If only DYNAMIC_SPATIAL_AUDIO_HARDWARE mode is reported by the
1084 // HAL and the engine does not support it, assert as this is a
1085 // product configuration error
1086 LOG_ALWAYS_FATAL("%s: the audio HAL reported only low latency with"
1087 "HW HID tunneling but the spatializer does not support it",
1088 __func__);
1089 }
1090 }
1091 }
1092 return requestedLatencyMode;
1093}
1094
Eric Laurent9249d342022-03-18 11:55:56 +01001095void Spatializer::checkSensorsState_l() {
Eric Laurentee398ad2022-05-03 18:19:35 +02001096 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
Andy Hungdae53212022-10-21 17:30:30 -07001097 const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
Eric Laurentbe21a942023-11-14 16:05:00 +01001098 bool supportsLowLatencyMode;
1099 if (com::android::media::audio::dsa_over_bt_le_audio()) {
1100 // mSupportedLatencyModes is ordered with MODE_FREE always at the end:
1101 // the first entry is never MODE_FREE if at least one low ltency mode is supported.
1102 supportsLowLatencyMode = supportsSetLatencyMode
1103 && mSupportedLatencyModes[0] != AUDIO_LATENCY_MODE_FREE;
1104 } else {
1105 supportsLowLatencyMode = supportsSetLatencyMode && std::find(
Andy Hungdae53212022-10-21 17:30:30 -07001106 mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
1107 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
Eric Laurentbe21a942023-11-14 16:05:00 +01001108 }
Eric Laurentbdecc052022-10-21 11:28:32 +02001109 if (mSupportsHeadTracking) {
1110 if (mPoseController != nullptr) {
Andy Hungdae53212022-10-21 17:30:30 -07001111 // TODO(b/253297301, b/255433067) reenable low latency condition check
1112 // for Head Tracking after Bluetooth HAL supports it correctly.
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001113 if (mNumActiveTracks > 0 && mLevel != Spatialization::Level::NONE
Eric Laurentbe21a942023-11-14 16:05:00 +01001114 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
1115 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
1116 if (supportsLowLatencyMode) {
1117 requestedLatencyMode = selectHeadtrackingConnectionMode_l();
1118 }
Eric Laurentbdecc052022-10-21 11:28:32 +02001119 if (mEngine != nullptr) {
1120 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001121 std::vector<HeadTracking::Mode>{mActualHeadTrackingMode});
Eric Laurentbe21a942023-11-14 16:05:00 +01001122 setEngineHeadtrackingConnectionMode_l();
Eric Laurentbdecc052022-10-21 11:28:32 +02001123 }
Eric Laurentbe21a942023-11-14 16:05:00 +01001124 // TODO: b/307588546: configure mPoseController according to selected
1125 // mHeadtrackingConnectionMode
Eric Laurentbdecc052022-10-21 11:28:32 +02001126 mPoseController->setHeadSensor(mHeadSensor);
1127 mPoseController->setScreenSensor(mScreenSensor);
Eric Laurentbdecc052022-10-21 11:28:32 +02001128 } else {
1129 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
1130 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
1131 resetEngineHeadPose_l();
1132 }
Eric Laurent15903592022-02-24 20:44:36 +01001133 } else {
Eric Laurentbdecc052022-10-21 11:28:32 +02001134 resetEngineHeadPose_l();
Eric Laurent15903592022-02-24 20:44:36 +01001135 }
1136 }
Andy Hungdae53212022-10-21 17:30:30 -07001137 if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
Andy Hung4bd53e72022-11-17 17:21:45 -08001138 const status_t status =
1139 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001140 ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d", __func__,
1141 mOutput, toString(requestedLatencyMode).c_str(), status);
Eric Laurentee398ad2022-05-03 18:19:35 +02001142 }
Eric Laurent15903592022-02-24 20:44:36 +01001143}
1144
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001145void Spatializer::checkEngineState_l() {
1146 if (mEngine != nullptr) {
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001147 if (mLevel != Spatialization::Level::NONE && mNumActiveTracks > 0) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001148 mEngine->setEnabled(true);
1149 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001150 std::vector<Spatialization::Level>{mLevel});
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001151 } else {
1152 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001153 std::vector<Spatialization::Level>{Spatialization::Level::NONE});
Eric Laurent7ea0d1b2022-04-01 14:23:44 +02001154 mEngine->setEnabled(false);
1155 }
1156 }
1157}
1158
Eric Laurent11094172022-04-05 18:27:42 +02001159void Spatializer::checkPoseController_l() {
1160 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
1161 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
1162
1163 if (isControllerNeeded && mPoseController == nullptr) {
1164 mPoseController = std::make_shared<SpatializerPoseController>(
1165 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +02001166 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +02001167 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
1168 "%s could not allocate pose controller", __func__);
1169 mPoseController->setDisplayOrientation(mDisplayOrientation);
1170 } else if (!isControllerNeeded && mPoseController != nullptr) {
1171 mPoseController.reset();
Eric Laurentbdecc052022-10-21 11:28:32 +02001172 resetEngineHeadPose_l();
Eric Laurent11094172022-04-05 18:27:42 +02001173 }
1174 if (mPoseController != nullptr) {
1175 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
1176 }
1177}
1178
Eric Laurent2be8b292021-08-23 09:44:33 -07001179void Spatializer::calculateHeadPose() {
1180 ALOGV("%s", __func__);
Andy Hung79eacdb2023-11-30 19:34:24 -08001181 audio_utils::lock_guard lock(mMutex);
Eric Laurent2be8b292021-08-23 09:44:33 -07001182 if (mPoseController != nullptr) {
1183 mPoseController->calculateAsync();
1184 }
1185}
Eric Laurent6d607012021-07-05 11:54:40 +02001186
Atneya Nair20e6cc82022-05-17 20:12:37 -04001187void Spatializer::onFramesProcessed(int32_t framesProcessed) {
Eric Laurent8a4259f2021-09-14 16:04:00 +02001188 sp<AMessage> msg =
1189 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
Atneya Nair20e6cc82022-05-17 20:12:37 -04001190 msg->setInt32(EngineCallbackHandler::kNumFramesKey, framesProcessed);
Eric Laurent8a4259f2021-09-14 16:04:00 +02001191 msg->post();
1192}
1193
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001194std::string Spatializer::toString(unsigned level) const {
Andy Hung560addd2023-01-30 11:58:44 -08001195 std::string prefixSpace(level, ' ');
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001196 std::string ss = prefixSpace + "Spatializer:\n";
1197 bool needUnlock = false;
1198
1199 prefixSpace += ' ';
Andy Hung79eacdb2023-11-30 19:34:24 -08001200 if (!mMutex.try_lock()) {
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001201 // dumpsys even try_lock failed, information dump can be useful although may not accurate
1202 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1203 } else {
1204 needUnlock = true;
1205 }
1206
1207 // Spatializer class information.
1208 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1209 ss.append(prefixSpace).append("Supported levels: [");
1210 for (auto& level : mLevels) {
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001211 base::StringAppendF(&ss, " %s", ToString(level).c_str());
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001212 }
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001213 base::StringAppendF(&ss, "], mLevel: %s", ToString(mLevel).c_str());
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001214
1215 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1216 for (auto& mode : mHeadTrackingModes) {
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001217 base::StringAppendF(&ss, " %s", ToString(mode).c_str());
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001218 }
1219 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
Shunkai Yao56e43f02022-08-30 03:14:50 +00001220 media::toString(mDesiredHeadTrackingMode).c_str(),
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001221 ToString(mActualHeadTrackingMode).c_str());
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001222
1223 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1224 for (auto& mode : mSpatializationModes) {
Shunkai Yao49bc61f2023-10-10 19:31:10 +00001225 base::StringAppendF(&ss, " %s", ToString(mode).c_str());
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001226 }
1227 ss += "]\n";
1228
1229 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1230 for (auto& mask : mChannelMasks) {
1231 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1232 }
1233 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1234 mSupportsHeadTracking ? "true" : "false");
1235 // 2. Settings (Output, tracks)
1236 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1237 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1238
1239 // 3. Sensors, Effect information.
1240 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1241 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1242 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1243 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1244 mDisplayOrientation);
1245
Andy Hung481bfe32023-12-18 14:00:29 -08001246 // 4. Show flag or property state.
1247 base::StringAppendF(&ss, "%sStereo Spatialization: %s\n", prefixSpace.c_str(),
1248 com_android_media_audio_stereo_spatialization() ? "true" : "false");
1249
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001250 ss.append(prefixSpace + "CommandLog:\n");
1251 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001252
1253 // PostController dump.
1254 if (mPoseController != nullptr) {
Andy Hung560addd2023-01-30 11:58:44 -08001255 ss.append(mPoseController->toString(level + 1))
1256 .append(prefixSpace)
Andy Hunga69459c2023-02-27 13:36:23 -08001257 .append("Pose (active stage-to-head) [tx, ty, tz : pitch, roll, yaw]:\n")
Andy Hung560addd2023-01-30 11:58:44 -08001258 .append(prefixSpace)
1259 .append(" PerMinuteHistory:\n")
Andy Hunga69459c2023-02-27 13:36:23 -08001260 .append(mPoseDurableRecorder.toString(level + 3))
Andy Hung560addd2023-01-30 11:58:44 -08001261 .append(prefixSpace)
1262 .append(" PerSecondHistory:\n")
Andy Hunga69459c2023-02-27 13:36:23 -08001263 .append(mPoseRecorder.toString(level + 3));
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001264 } else {
1265 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1266 }
1267
1268 if (needUnlock) {
Andy Hung79eacdb2023-11-30 19:34:24 -08001269 mMutex.unlock();
Shunkai Yaoafc0c2e2022-07-22 18:42:27 +00001270 }
1271 return ss;
1272}
1273
Eric Laurent6d607012021-07-05 11:54:40 +02001274} // namespace android