blob: cf9543c40e050443b7c8efd797d4b33820d9e905 [file] [log] [blame]
Eric Laurent6d607012021-07-05 11:54:40 +02001/*
2**
3** Copyright 2021, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Shunkai Yao5a251df2022-07-22 18:42:27 +000018#include <string>
Eric Laurent6d607012021-07-05 11:54:40 +020019#define LOG_TAG "Spatializer"
20//#define LOG_NDEBUG 0
21#include <utils/Log.h>
22
Shunkai Yao5a251df2022-07-22 18:42:27 +000023#include <inttypes.h>
Eric Laurent6d607012021-07-05 11:54:40 +020024#include <limits.h>
25#include <stdint.h>
26#include <sys/types.h>
27
28#include <android/content/AttributionSourceState.h>
29#include <audio_utils/fixedfft.h>
30#include <cutils/bitops.h>
Eric Laurent2be8b292021-08-23 09:44:33 -070031#include <hardware/sensors.h>
Eric Laurent6d607012021-07-05 11:54:40 +020032#include <media/audiohal/EffectsFactoryHalInterface.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020033#include <media/stagefright/foundation/AHandler.h>
34#include <media/stagefright/foundation/AMessage.h>
Andy Hunga461a002022-05-17 10:36:02 -070035#include <media/MediaMetricsItem.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020036#include <media/ShmemCompat.h>
Andy Hungb725c692022-12-14 14:25:49 -080037#include <mediautils/SchedulingPolicyService.h>
Eric Laurent6d607012021-07-05 11:54:40 +020038#include <mediautils/ServiceUtilities.h>
39#include <utils/Thread.h>
40
41#include "Spatializer.h"
42
43namespace android {
44
45using aidl_utils::statusTFromBinderStatus;
46using aidl_utils::binderStatusFromStatusT;
47using android::content::AttributionSourceState;
48using binder::Status;
Eric Laurent2be8b292021-08-23 09:44:33 -070049using media::HeadTrackingMode;
50using media::Pose3f;
Eric Laurent6d607012021-07-05 11:54:40 +020051using media::SpatializationLevel;
Eric Laurent2be8b292021-08-23 09:44:33 -070052using media::SpatializationMode;
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070053using media::SpatializerHeadTrackingMode;
Eric Laurent2be8b292021-08-23 09:44:33 -070054using media::SensorPoseProvider;
55
Eric Laurent2be8b292021-08-23 09:44:33 -070056using namespace std::chrono_literals;
Eric Laurent6d607012021-07-05 11:54:40 +020057
58#define VALUE_OR_RETURN_BINDER_STATUS(x) \
59 ({ auto _tmp = (x); \
60 if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
61 std::move(_tmp.value()); })
62
Andy Hung0e3205d2022-08-29 14:14:58 -070063static audio_channel_mask_t getMaxChannelMask(
64 const std::vector<audio_channel_mask_t>& masks, size_t channelLimit = SIZE_MAX) {
Andy Hunga461a002022-05-17 10:36:02 -070065 uint32_t maxCount = 0;
66 audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
67 for (auto mask : masks) {
68 const size_t count = audio_channel_count_from_out_mask(mask);
Andy Hung0e3205d2022-08-29 14:14:58 -070069 if (count > channelLimit) continue; // ignore masks greater than channelLimit
Andy Hunga461a002022-05-17 10:36:02 -070070 if (count > maxCount) {
71 maxMask = mask;
72 maxCount = count;
73 }
74 }
75 return maxMask;
76}
77
Andy Hung82a4eab2023-01-30 11:58:44 -080078std::vector<float> recordFromRotationVector(const std::vector<float>& rotationVector) {
79 constexpr float RAD_TO_DEGREE = 180.f / M_PI;
80 std::vector<float> record{
81 rotationVector[0], rotationVector[1], rotationVector[2],
82 rotationVector[3] * RAD_TO_DEGREE,
83 rotationVector[4] * RAD_TO_DEGREE,
84 rotationVector[5] * RAD_TO_DEGREE};
85 return record;
86}
87
Eric Laurent6d607012021-07-05 11:54:40 +020088// ---------------------------------------------------------------------------
89
Eric Laurent8a4259f2021-09-14 16:04:00 +020090class Spatializer::EngineCallbackHandler : public AHandler {
91public:
92 EngineCallbackHandler(wp<Spatializer> spatializer)
93 : mSpatializer(spatializer) {
94 }
95
96 enum {
97 // Device state callbacks
98 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
99 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
100 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
Eric Laurentdf2ece42022-07-20 13:49:47 +0200101 kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
Eric Laurent8a4259f2021-09-14 16:04:00 +0200102 };
103 static constexpr const char *kNumFramesKey = "numFrames";
104 static constexpr const char *kModeKey = "mode";
105 static constexpr const char *kTranslation0Key = "translation0";
106 static constexpr const char *kTranslation1Key = "translation1";
107 static constexpr const char *kTranslation2Key = "translation2";
108 static constexpr const char *kRotation0Key = "rotation0";
109 static constexpr const char *kRotation1Key = "rotation1";
110 static constexpr const char *kRotation2Key = "rotation2";
Eric Laurentdf2ece42022-07-20 13:49:47 +0200111 static constexpr const char *kLatencyModesKey = "latencyModes";
112
113 class LatencyModes : public RefBase {
114 public:
115 LatencyModes(audio_io_handle_t output,
116 const std::vector<audio_latency_mode_t>& latencyModes)
117 : mOutput(output), mLatencyModes(latencyModes) {}
118 ~LatencyModes() = default;
119
120 audio_io_handle_t mOutput;
121 std::vector<audio_latency_mode_t> mLatencyModes;
122 };
Eric Laurent8a4259f2021-09-14 16:04:00 +0200123
124 void onMessageReceived(const sp<AMessage> &msg) override {
Andy Hungb725c692022-12-14 14:25:49 -0800125 // No ALooper method to get the tid so update
126 // Spatializer priority on the first message received.
127 std::call_once(mPrioritySetFlag, [](){
128 const pid_t pid = getpid();
129 const pid_t tid = gettid();
130 (void)requestSpatializerPriority(pid, tid);
131 });
132
Eric Laurentdf2ece42022-07-20 13:49:47 +0200133 sp<Spatializer> spatializer = mSpatializer.promote();
134 if (spatializer == nullptr) {
135 ALOGW("%s: Cannot promote spatializer", __func__);
136 return;
137 }
Eric Laurent8a4259f2021-09-14 16:04:00 +0200138 switch (msg->what()) {
139 case kWhatOnFramesProcessed: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200140 int numFrames;
141 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
142 ALOGE("%s: Cannot find num frames!", __func__);
143 return;
144 }
145 if (numFrames > 0) {
146 spatializer->calculateHeadPose();
147 }
148 } break;
149 case kWhatOnHeadToStagePose: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200150 std::vector<float> headToStage(sHeadPoseKeys.size());
151 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
152 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
153 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
154 return;
155 }
156 }
157 spatializer->onHeadToStagePoseMsg(headToStage);
158 } break;
159 case kWhatOnActualModeChange: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200160 int mode;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200161 if (!msg->findInt32(kModeKey, &mode)) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200162 ALOGE("%s: Cannot find actualMode!", __func__);
163 return;
164 }
165 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
166 } break;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200167
168 case kWhatOnLatencyModesChanged: {
169 sp<RefBase> object;
170 if (!msg->findObject(kLatencyModesKey, &object)) {
171 ALOGE("%s: Cannot find latency modes!", __func__);
172 return;
173 }
174 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
175 spatializer->onSupportedLatencyModesChangedMsg(
176 latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
177 } break;
178
Eric Laurent8a4259f2021-09-14 16:04:00 +0200179 default:
180 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
181 }
182 }
183private:
184 wp<Spatializer> mSpatializer;
Andy Hungb725c692022-12-14 14:25:49 -0800185 std::once_flag mPrioritySetFlag;
Eric Laurent8a4259f2021-09-14 16:04:00 +0200186};
187
188const std::vector<const char *> Spatializer::sHeadPoseKeys = {
189 Spatializer::EngineCallbackHandler::kTranslation0Key,
190 Spatializer::EngineCallbackHandler::kTranslation1Key,
191 Spatializer::EngineCallbackHandler::kTranslation2Key,
192 Spatializer::EngineCallbackHandler::kRotation0Key,
193 Spatializer::EngineCallbackHandler::kRotation1Key,
194 Spatializer::EngineCallbackHandler::kRotation2Key,
195};
196
197// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200198sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
199 sp<Spatializer> spatializer;
200
201 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
202 if (effectsFactoryHal == nullptr) {
203 ALOGW("%s failed to create effect factory interface", __func__);
204 return spatializer;
205 }
206
207 std::vector<effect_descriptor_t> descriptors;
208 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200209 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200210 if (status != NO_ERROR) {
211 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
212 return spatializer;
213 }
214 ALOG_ASSERT(!descriptors.empty(),
215 "%s getDescriptors() returned no error but empty list", __func__);
216
Shunkai Yao5a251df2022-07-22 18:42:27 +0000217 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200218 sp<EffectHalInterface> effect;
219 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
220 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000221 ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
222 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200223
224 if (status == NO_ERROR && effect != nullptr) {
225 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700226 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
227 spatializer.clear();
Andy Hung0e3205d2022-08-29 14:14:58 -0700228 ALOGW("%s loadEngine error: %d effect Id %" PRId64,
229 __func__, status, effect ? effect->effectId() : 0);
230 } else {
231 spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
232 effect ? effect->effectId() : 0);
Eric Laurent2be8b292021-08-23 09:44:33 -0700233 }
Eric Laurent6d607012021-07-05 11:54:40 +0200234 }
235
236 return spatializer;
237}
238
Eric Laurent2be8b292021-08-23 09:44:33 -0700239Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
240 : mEngineDescriptor(engineDescriptor),
241 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200242 ALOGV("%s", __func__);
Andy Hung393de3a2022-12-06 16:33:20 -0800243 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent6d607012021-07-05 11:54:40 +0200244}
245
Eric Laurent8a4259f2021-09-14 16:04:00 +0200246void Spatializer::onFirstRef() {
247 mLooper = new ALooper;
248 mLooper->setName("Spatializer-looper");
249 mLooper->start(
250 /*runOnCallingThread*/false,
251 /*canCallJava*/ false,
Andy Hung898a39f2022-11-07 20:09:20 -0800252 PRIORITY_URGENT_AUDIO);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200253
254 mHandler = new EngineCallbackHandler(this);
255 mLooper->registerHandler(mHandler);
256}
257
Eric Laurent6d607012021-07-05 11:54:40 +0200258Spatializer::~Spatializer() {
259 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200260 if (mLooper != nullptr) {
261 mLooper->stop();
262 mLooper->unregisterHandler(mHandler->id());
263 }
264 mLooper.clear();
265 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200266}
267
Andy Hung4442d042022-08-17 17:27:32 -0700268static std::string channelMaskVectorToString(
269 const std::vector<audio_channel_mask_t>& masks) {
270 std::stringstream ss;
271 for (const auto &mask : masks) {
272 if (ss.tellp() != 0) ss << "|";
273 ss << mask;
274 }
275 return ss.str();
276}
277
Eric Laurent2be8b292021-08-23 09:44:33 -0700278status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
279 ALOGV("%s", __func__);
280
281 std::vector<bool> supportsHeadTracking;
282 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
283 &supportsHeadTracking);
284 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700285 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700286 return status;
287 }
288 mSupportsHeadTracking = supportsHeadTracking[0];
289
Andy Hung119dbdb2022-05-11 19:20:13 -0700290 std::vector<media::SpatializationLevel> spatializationLevels;
291 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
292 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700293 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700294 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700295 return status;
296 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700297 bool noneLevelFound = false;
298 bool activeLevelFound = false;
299 for (const auto spatializationLevel : spatializationLevels) {
300 if (!aidl_utils::isValidEnum(spatializationLevel)) {
301 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
302 continue;
303 }
304 if (spatializationLevel == media::SpatializationLevel::NONE) {
305 noneLevelFound = true;
306 } else {
307 activeLevelFound = true;
308 }
309 // we don't detect duplicates.
310 mLevels.emplace_back(spatializationLevel);
311 }
312 if (!noneLevelFound || !activeLevelFound) {
313 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
314 " and another valid level", __func__);
315 return BAD_VALUE;
316 }
317
318 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700319 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700320 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700321 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700322 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700323 return status;
324 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000325
Andy Hung119dbdb2022-05-11 19:20:13 -0700326 for (const auto spatializationMode : spatializationModes) {
327 if (!aidl_utils::isValidEnum(spatializationMode)) {
328 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
329 continue;
330 }
331 // we don't detect duplicates.
332 mSpatializationModes.emplace_back(spatializationMode);
333 }
334 if (mSpatializationModes.empty()) {
335 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
336 return BAD_VALUE;
337 }
338
339 std::vector<audio_channel_mask_t> channelMasks;
340 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
341 &channelMasks);
342 if (status != NO_ERROR) {
343 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
344 return status;
345 }
346 for (const auto channelMask : channelMasks) {
347 if (!audio_is_channel_mask_spatialized(channelMask)) {
348 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
349 continue;
350 }
351 // we don't detect duplicates.
352 mChannelMasks.emplace_back(channelMask);
353 }
354 if (mChannelMasks.empty()) {
355 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
356 return BAD_VALUE;
357 }
Andy Hunga461a002022-05-17 10:36:02 -0700358
359 // Currently we expose only RELATIVE_WORLD.
360 // This is a limitation of the head tracking library based on a UX choice.
361 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
362 if (mSupportsHeadTracking) {
363 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
364 }
365 mediametrics::LogItem(mMetricsId)
366 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
Andy Hung4442d042022-08-17 17:27:32 -0700367 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
Andy Hunga461a002022-05-17 10:36:02 -0700368 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
369 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
370 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
371 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
372 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700373 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700374}
375
Andy Hung757bc812022-09-13 18:53:06 -0700376/* static */
377void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
378 mediametrics::LogItem(kDefaultMetricsId)
379 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
380 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
381 .set(AMEDIAMETRICS_PROP_LEVELS, "")
382 .set(AMEDIAMETRICS_PROP_MODES, "")
383 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
384 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
385 .record();
386}
387
Eric Laurent2be8b292021-08-23 09:44:33 -0700388/** Gets the channel mask, sampling rate and format set for the spatializer input. */
389audio_config_base_t Spatializer::getAudioInConfig() const {
390 std::lock_guard lock(mLock);
391 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
392 // For now use highest supported channel count
Andy Hung0e3205d2022-08-29 14:14:58 -0700393 config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
Eric Laurent2be8b292021-08-23 09:44:33 -0700394 return config;
395}
396
Eric Laurent6d607012021-07-05 11:54:40 +0200397status_t Spatializer::registerCallback(
398 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700399 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200400 if (callback == nullptr) {
401 return BAD_VALUE;
402 }
403
Eric Laurentb57604f2022-08-31 16:07:50 +0200404 if (mSpatializerCallback != nullptr) {
405 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
406 ALOGW("%s: Registering callback %p again",
407 __func__, mSpatializerCallback.get());
408 return NO_ERROR;
409 }
410 ALOGE("%s: Already one client registered with callback %p",
411 __func__, mSpatializerCallback.get());
412 return INVALID_OPERATION;
413 }
414
Eric Laurent6d607012021-07-05 11:54:40 +0200415 sp<IBinder> binder = IInterface::asBinder(callback);
416 status_t status = binder->linkToDeath(this);
417 if (status == NO_ERROR) {
418 mSpatializerCallback = callback;
419 }
420 ALOGV("%s status %d", __func__, status);
421 return status;
422}
423
424// IBinder::DeathRecipient
425void Spatializer::binderDied(__unused const wp<IBinder> &who) {
426 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700427 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200428 mLevel = SpatializationLevel::NONE;
429 mSpatializerCallback.clear();
430 }
431 ALOGV("%s", __func__);
432 mPolicyCallback->onCheckSpatializer();
433}
434
435// ISpatializer
436Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
437 ALOGV("%s", __func__);
438 if (levels == nullptr) {
439 return binderStatusFromStatusT(BAD_VALUE);
440 }
Andy Hunga461a002022-05-17 10:36:02 -0700441 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700442 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200443 return Status::ok();
444}
445
Eric Laurent2be8b292021-08-23 09:44:33 -0700446Status Spatializer::setLevel(SpatializationLevel level) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000447 ALOGV("%s level %s", __func__, media::toString(level).c_str());
448 mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
Eric Laurent6d607012021-07-05 11:54:40 +0200449 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700450 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200451 return binderStatusFromStatusT(BAD_VALUE);
452 }
453 sp<media::INativeSpatializerCallback> callback;
454 bool levelChanged = false;
455 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700456 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200457 levelChanged = mLevel != level;
458 mLevel = level;
459 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700460
461 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200462 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700463 }
Eric Laurent9249d342022-03-18 11:55:56 +0100464 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200465 }
466
467 if (levelChanged) {
468 mPolicyCallback->onCheckSpatializer();
469 if (callback != nullptr) {
470 callback->onLevelChanged(level);
471 }
472 }
473 return Status::ok();
474}
475
Eric Laurent2be8b292021-08-23 09:44:33 -0700476Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200477 if (level == nullptr) {
478 return binderStatusFromStatusT(BAD_VALUE);
479 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700480 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200481 *level = mLevel;
482 ALOGV("%s level %d", __func__, (int)*level);
483 return Status::ok();
484}
485
Eric Laurentc87402b2021-09-17 16:49:42 +0200486Status Spatializer::isHeadTrackingSupported(bool *supports) {
487 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
488 if (supports == nullptr) {
489 return binderStatusFromStatusT(BAD_VALUE);
490 }
491 std::lock_guard lock(mLock);
492 *supports = mSupportsHeadTracking;
493 return Status::ok();
494}
495
Eric Laurent6d607012021-07-05 11:54:40 +0200496Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700497 std::vector<SpatializerHeadTrackingMode>* modes) {
498 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200499 ALOGV("%s", __func__);
500 if (modes == nullptr) {
501 return binderStatusFromStatusT(BAD_VALUE);
502 }
Andy Hunga461a002022-05-17 10:36:02 -0700503 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200504 return Status::ok();
505}
506
Eric Laurent2be8b292021-08-23 09:44:33 -0700507Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000508 ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700509
510 if (!mSupportsHeadTracking) {
511 return binderStatusFromStatusT(INVALID_OPERATION);
512 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000513 mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700514 std::lock_guard lock(mLock);
515 switch (mode) {
516 case SpatializerHeadTrackingMode::OTHER:
517 return binderStatusFromStatusT(BAD_VALUE);
518 case SpatializerHeadTrackingMode::DISABLED:
519 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
520 break;
521 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
522 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
523 break;
524 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
525 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
526 break;
527 }
528
Eric Laurent11094172022-04-05 18:27:42 +0200529 checkPoseController_l();
530 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700531
532 return Status::ok();
533}
534
535Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200536 if (mode == nullptr) {
537 return binderStatusFromStatusT(BAD_VALUE);
538 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700539 std::lock_guard lock(mLock);
540 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200541 ALOGV("%s mode %d", __func__, (int)*mode);
542 return Status::ok();
543}
544
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700545Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200546 if (!mSupportsHeadTracking) {
547 return binderStatusFromStatusT(INVALID_OPERATION);
548 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700549 std::lock_guard lock(mLock);
550 if (mPoseController != nullptr) {
551 mPoseController->recenter();
552 }
Eric Laurent6d607012021-07-05 11:54:40 +0200553 return Status::ok();
554}
555
556Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200557 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200558 if (!mSupportsHeadTracking) {
559 return binderStatusFromStatusT(INVALID_OPERATION);
560 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700561 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
562 if (!maybePose.has_value()) {
563 ALOGW("Invalid screenToStage vector.");
564 return binderStatusFromStatusT(BAD_VALUE);
565 }
566 std::lock_guard lock(mLock);
567 if (mPoseController != nullptr) {
Andy Hung82a4eab2023-01-30 11:58:44 -0800568 mLocalLog.log("%s with screenToStage %s", __func__,
569 media::VectorRecorder::toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700570 mPoseController->setScreenToStagePose(maybePose.value());
571 }
Eric Laurent6d607012021-07-05 11:54:40 +0200572 return Status::ok();
573}
574
575Status Spatializer::release() {
576 ALOGV("%s", __func__);
577 bool levelChanged = false;
578 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700579 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200580 if (mSpatializerCallback == nullptr) {
581 return binderStatusFromStatusT(INVALID_OPERATION);
582 }
583
584 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
585 binder->unlinkToDeath(this);
586 mSpatializerCallback.clear();
587
588 levelChanged = mLevel != SpatializationLevel::NONE;
589 mLevel = SpatializationLevel::NONE;
590 }
591
592 if (levelChanged) {
593 mPolicyCallback->onCheckSpatializer();
594 }
595 return Status::ok();
596}
597
Eric Laurent2be8b292021-08-23 09:44:33 -0700598Status Spatializer::setHeadSensor(int sensorHandle) {
599 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200600 if (!mSupportsHeadTracking) {
601 return binderStatusFromStatusT(INVALID_OPERATION);
602 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700603 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700604 if (mHeadSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000605 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700606 mHeadSensor = sensorHandle;
607 checkPoseController_l();
608 checkSensorsState_l();
609 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700610 return Status::ok();
611}
612
613Status Spatializer::setScreenSensor(int sensorHandle) {
614 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200615 if (!mSupportsHeadTracking) {
616 return binderStatusFromStatusT(INVALID_OPERATION);
617 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700618 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700619 if (mScreenSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000620 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700621 mScreenSensor = sensorHandle;
622 // TODO: consider a new method setHeadAndScreenSensor()
623 // because we generally set both at the same time.
624 // This will avoid duplicated work and recentering.
625 checkSensorsState_l();
626 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700627 return Status::ok();
628}
629
630Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
631 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200632 if (!mSupportsHeadTracking) {
633 return binderStatusFromStatusT(INVALID_OPERATION);
634 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700635 std::lock_guard lock(mLock);
636 mDisplayOrientation = physicalToLogicalAngle;
Shunkai Yao5a251df2022-07-22 18:42:27 +0000637 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700638 if (mPoseController != nullptr) {
639 mPoseController->setDisplayOrientation(mDisplayOrientation);
640 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200641 if (mEngine != nullptr) {
642 setEffectParameter_l(
643 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
644 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700645 return Status::ok();
646}
647
648Status Spatializer::setHingeAngle(float hingeAngle) {
649 std::lock_guard lock(mLock);
650 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
651 if (mEngine != nullptr) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000652 mLocalLog.log("%s with %f", __func__, hingeAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700653 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
654 }
655 return Status::ok();
656}
657
658Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
659 ALOGV("%s", __func__);
660 if (modes == nullptr) {
661 return binderStatusFromStatusT(BAD_VALUE);
662 }
663 *modes = mSpatializationModes;
664 return Status::ok();
665}
666
Eric Laurent67816e32021-09-16 15:18:40 +0200667Status Spatializer::registerHeadTrackingCallback(
668 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
669 ALOGV("%s callback %p", __func__, callback.get());
670 std::lock_guard lock(mLock);
671 if (!mSupportsHeadTracking) {
672 return binderStatusFromStatusT(INVALID_OPERATION);
673 }
674 mHeadTrackingCallback = callback;
675 return Status::ok();
676}
677
Eric Laurentc87402b2021-09-17 16:49:42 +0200678Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
679 ALOGV("%s key %d", __func__, key);
680 std::lock_guard lock(mLock);
681 status_t status = INVALID_OPERATION;
682 if (mEngine != nullptr) {
683 status = setEffectParameter_l(key, value);
684 }
685 return binderStatusFromStatusT(status);
686}
687
688Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700689 ALOGV("%s key %d value size %d", __func__, key,
690 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200691 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700692 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200693 }
694 std::lock_guard lock(mLock);
695 status_t status = INVALID_OPERATION;
696 if (mEngine != nullptr) {
697 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
698 status = getEffectParameter_l(key, value);
699 }
700 return binderStatusFromStatusT(status);
701}
702
703Status Spatializer::getOutput(int *output) {
704 ALOGV("%s", __func__);
705 if (output == nullptr) {
706 binderStatusFromStatusT(BAD_VALUE);
707 }
708 std::lock_guard lock(mLock);
709 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
710 ALOGV("%s got output %d", __func__, *output);
711 return Status::ok();
712}
713
Eric Laurent2be8b292021-08-23 09:44:33 -0700714// SpatializerPoseController::Listener
715void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
716 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200717 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
718 "onHeadToStagePose() called with no head tracking support!");
719
Eric Laurent2be8b292021-08-23 09:44:33 -0700720 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200721 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
722 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200723 sp<AMessage> msg =
724 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
725 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
726 msg->setFloat(sHeadPoseKeys[i], vec[i]);
727 }
728 msg->post();
729}
730
Eric Laurent3c48ad92022-10-21 11:28:32 +0200731void Spatializer::resetEngineHeadPose_l() {
732 ALOGV("%s mEngine %p", __func__, mEngine.get());
733 if (mEngine == nullptr) {
734 return;
735 }
736 const std::vector<float> headToStage(6, 0.0);
737 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
738 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
739 std::vector<SpatializerHeadTrackingMode>{SpatializerHeadTrackingMode::DISABLED});
740}
741
Eric Laurent8a4259f2021-09-14 16:04:00 +0200742void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
743 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200744 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700745 {
746 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200747 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700748 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200749 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Shunkai Yao7de40382022-08-25 00:44:04 +0000750 mPoseRecorder.record(headToStage);
751 mPoseDurableRecorder.record(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700752 }
753 }
754
755 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200756 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700757 }
758}
759
760void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao51379452022-08-30 03:14:50 +0000761 std::string modeStr = media::toString(mode);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000762 ALOGV("%s(%s)", __func__, modeStr.c_str());
Shunkai Yao51379452022-08-30 03:14:50 +0000763 sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200764 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
765 msg->post();
766}
767
768void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
769 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200770 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700771 SpatializerHeadTrackingMode spatializerMode;
772 {
773 std::lock_guard lock(mLock);
774 if (!mSupportsHeadTracking) {
775 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
776 } else {
777 switch (mode) {
778 case HeadTrackingMode::STATIC:
779 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
780 break;
781 case HeadTrackingMode::WORLD_RELATIVE:
782 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
783 break;
784 case HeadTrackingMode::SCREEN_RELATIVE:
785 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
786 break;
787 default:
788 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
789 }
790 }
791 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200792 if (mEngine != nullptr) {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200793 if (spatializerMode == SpatializerHeadTrackingMode::DISABLED) {
794 resetEngineHeadPose_l();
795 } else {
796 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
797 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
798 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200799 }
Eric Laurent67816e32021-09-16 15:18:40 +0200800 callback = mHeadTrackingCallback;
Shunkai Yao51379452022-08-30 03:14:50 +0000801 mLocalLog.log("%s: %s, spatializerMode %s", __func__, media::toString(mode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +0000802 media::toString(spatializerMode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700803 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200804 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700805 callback->onHeadTrackingModeChanged(spatializerMode);
806 }
807}
808
Eric Laurent15903592022-02-24 20:44:36 +0100809status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200810 bool outputChanged = false;
811 sp<media::INativeSpatializerCallback> callback;
812
Eric Laurent2be8b292021-08-23 09:44:33 -0700813 {
814 std::lock_guard lock(mLock);
815 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000816 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
817 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700818 if (mOutput != AUDIO_IO_HANDLE_NONE) {
819 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
820 // remove FX instance
821 mEngine->setEnabled(false);
822 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100823 mPoseController.reset();
Eric Laurentb387fb42022-05-03 18:19:35 +0200824 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700825 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200826
Eric Laurent2be8b292021-08-23 09:44:33 -0700827 // create FX instance on output
828 AttributionSourceState attributionSource = AttributionSourceState();
829 mEngine = new AudioEffect(attributionSource);
830 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
831 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
832 false /* probe */, true /* notifyFramesProcessed */);
833 status_t status = mEngine->initCheck();
834 ALOGV("%s mEngine create status %d", __func__, (int)status);
835 if (status != NO_ERROR) {
836 return status;
837 }
838
Eric Laurent4a872862021-10-11 17:06:47 +0200839 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700840 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200841 mNumActiveTracks = numActiveTracks;
Eric Laurentb387fb42022-05-03 18:19:35 +0200842 AudioSystem::addSupportedLatencyModesCallback(this);
843
844 std::vector<audio_latency_mode_t> latencyModes;
845 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
846 if (status == OK) {
847 mSupportedLatencyModes = latencyModes;
848 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700849
Eric Laurent11094172022-04-05 18:27:42 +0200850 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200851 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200852 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100853 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200854 }
Eric Laurent4a872862021-10-11 17:06:47 +0200855 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200856 }
Eric Laurent4a872862021-10-11 17:06:47 +0200857
858 if (outputChanged && callback != nullptr) {
859 callback->onOutputChanged(output);
860 }
861
Eric Laurent6d607012021-07-05 11:54:40 +0200862 return NO_ERROR;
863}
864
865audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700866 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200867 sp<media::INativeSpatializerCallback> callback;
868
869 {
870 std::lock_guard lock(mLock);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000871 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +0200872 ALOGV("%s mOutput %d", __func__, (int)mOutput);
873 if (mOutput == AUDIO_IO_HANDLE_NONE) {
874 return output;
875 }
876 // remove FX instance
877 mEngine->setEnabled(false);
878 mEngine.clear();
Eric Laurentb387fb42022-05-03 18:19:35 +0200879 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200880 output = mOutput;
881 mOutput = AUDIO_IO_HANDLE_NONE;
882 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200883 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200884 }
Eric Laurent4a872862021-10-11 17:06:47 +0200885
886 if (callback != nullptr) {
887 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
888 }
Eric Laurent6d607012021-07-05 11:54:40 +0200889 return output;
890}
891
Eric Laurentb387fb42022-05-03 18:19:35 +0200892void Spatializer::onSupportedLatencyModesChanged(
893 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200894 ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
895 sp<AMessage> msg =
896 new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
897 msg->setObject(EngineCallbackHandler::kLatencyModesKey,
898 sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
899 msg->post();
900}
901
902void Spatializer::onSupportedLatencyModesChangedMsg(
903 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
Eric Laurentb387fb42022-05-03 18:19:35 +0200904 std::lock_guard lock(mLock);
Eric Laurentdf2ece42022-07-20 13:49:47 +0200905 ALOGV("%s output %d mOutput %d num modes %zu",
906 __func__, (int)output, (int)mOutput, modes.size());
Eric Laurentb387fb42022-05-03 18:19:35 +0200907 if (output == mOutput) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200908 mSupportedLatencyModes = std::move(modes);
Eric Laurentb387fb42022-05-03 18:19:35 +0200909 checkSensorsState_l();
910 }
911}
912
Eric Laurent15903592022-02-24 20:44:36 +0100913void Spatializer::updateActiveTracks(size_t numActiveTracks) {
914 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200915 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000916 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200917 mNumActiveTracks = numActiveTracks;
918 checkEngineState_l();
919 checkSensorsState_l();
920 }
Eric Laurent15903592022-02-24 20:44:36 +0100921}
922
Eric Laurent9249d342022-03-18 11:55:56 +0100923void Spatializer::checkSensorsState_l() {
Eric Laurentb387fb42022-05-03 18:19:35 +0200924 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
Andy Hungc0896c72022-10-21 17:30:30 -0700925 const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
926 const bool supportsLowLatencyMode = supportsSetLatencyMode && std::find(
927 mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
928 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
Eric Laurent3c48ad92022-10-21 11:28:32 +0200929 if (mSupportsHeadTracking) {
930 if (mPoseController != nullptr) {
Andy Hungc0896c72022-10-21 17:30:30 -0700931 // TODO(b/253297301, b/255433067) reenable low latency condition check
932 // for Head Tracking after Bluetooth HAL supports it correctly.
933 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent3c48ad92022-10-21 11:28:32 +0200934 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
935 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
936 if (mEngine != nullptr) {
937 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
938 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
939 }
940 mPoseController->setHeadSensor(mHeadSensor);
941 mPoseController->setScreenSensor(mScreenSensor);
Andy Hungc0896c72022-10-21 17:30:30 -0700942 if (supportsLowLatencyMode) requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent3c48ad92022-10-21 11:28:32 +0200943 } else {
944 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
945 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
946 resetEngineHeadPose_l();
947 }
Eric Laurent15903592022-02-24 20:44:36 +0100948 } else {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200949 resetEngineHeadPose_l();
Eric Laurent15903592022-02-24 20:44:36 +0100950 }
951 }
Andy Hungc0896c72022-10-21 17:30:30 -0700952 if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
Andy Hung5d8618d2022-11-17 17:21:45 -0800953 const status_t status =
954 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
955 ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
956 __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
Eric Laurentb387fb42022-05-03 18:19:35 +0200957 }
Eric Laurent15903592022-02-24 20:44:36 +0100958}
959
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200960void Spatializer::checkEngineState_l() {
961 if (mEngine != nullptr) {
962 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
963 mEngine->setEnabled(true);
964 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
965 std::vector<SpatializationLevel>{mLevel});
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200966 } else {
967 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
968 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
969 mEngine->setEnabled(false);
970 }
971 }
972}
973
Eric Laurent11094172022-04-05 18:27:42 +0200974void Spatializer::checkPoseController_l() {
975 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
976 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
977
978 if (isControllerNeeded && mPoseController == nullptr) {
979 mPoseController = std::make_shared<SpatializerPoseController>(
980 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +0200981 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +0200982 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
983 "%s could not allocate pose controller", __func__);
984 mPoseController->setDisplayOrientation(mDisplayOrientation);
985 } else if (!isControllerNeeded && mPoseController != nullptr) {
986 mPoseController.reset();
Eric Laurent3c48ad92022-10-21 11:28:32 +0200987 resetEngineHeadPose_l();
Eric Laurent11094172022-04-05 18:27:42 +0200988 }
989 if (mPoseController != nullptr) {
990 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
991 }
992}
993
Eric Laurent2be8b292021-08-23 09:44:33 -0700994void Spatializer::calculateHeadPose() {
995 ALOGV("%s", __func__);
996 std::lock_guard lock(mLock);
997 if (mPoseController != nullptr) {
998 mPoseController->calculateAsync();
999 }
1000}
Eric Laurent6d607012021-07-05 11:54:40 +02001001
Eric Laurent2be8b292021-08-23 09:44:33 -07001002void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +02001003 if (user == nullptr) {
1004 return;
1005 }
Eric Laurent2be8b292021-08-23 09:44:33 -07001006 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +02001007 switch (event) {
1008 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -07001009 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +01001010 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +02001011 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -07001012 } break;
Eric Laurent6d607012021-07-05 11:54:40 +02001013 default:
Eric Laurent9249d342022-03-18 11:55:56 +01001014 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +02001015 break;
1016 }
1017}
1018
Eric Laurent8a4259f2021-09-14 16:04:00 +02001019void Spatializer::postFramesProcessedMsg(int frames) {
1020 sp<AMessage> msg =
1021 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
1022 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
1023 msg->post();
1024}
1025
Shunkai Yao5a251df2022-07-22 18:42:27 +00001026std::string Spatializer::toString(unsigned level) const {
1027 std::string prefixSpace;
1028 prefixSpace.append(level, ' ');
1029 std::string ss = prefixSpace + "Spatializer:\n";
1030 bool needUnlock = false;
1031
1032 prefixSpace += ' ';
1033 if (!mLock.try_lock()) {
1034 // dumpsys even try_lock failed, information dump can be useful although may not accurate
1035 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1036 } else {
1037 needUnlock = true;
1038 }
1039
1040 // Spatializer class information.
1041 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1042 ss.append(prefixSpace).append("Supported levels: [");
1043 for (auto& level : mLevels) {
1044 base::StringAppendF(&ss, " %s", media::toString(level).c_str());
1045 }
1046 base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
1047
1048 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1049 for (auto& mode : mHeadTrackingModes) {
1050 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1051 }
1052 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
Shunkai Yao51379452022-08-30 03:14:50 +00001053 media::toString(mDesiredHeadTrackingMode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +00001054 media::toString(mActualHeadTrackingMode).c_str());
1055
1056 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1057 for (auto& mode : mSpatializationModes) {
1058 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1059 }
1060 ss += "]\n";
1061
1062 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1063 for (auto& mask : mChannelMasks) {
1064 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1065 }
1066 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1067 mSupportsHeadTracking ? "true" : "false");
1068 // 2. Settings (Output, tracks)
1069 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1070 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1071
1072 // 3. Sensors, Effect information.
1073 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1074 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1075 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1076 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1077 mDisplayOrientation);
1078
1079 ss.append(prefixSpace + "CommandLog:\n");
1080 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001081
1082 // PostController dump.
1083 if (mPoseController != nullptr) {
1084 ss += mPoseController->toString(level + 1);
Shunkai Yao7de40382022-08-25 00:44:04 +00001085 ss.append(prefixSpace +
1086 "Sensor data format - [rx, ry, rz, vx, vy, vz] (units-degree, "
1087 "r-transform, v-angular velocity, x-pitch, y-roll, z-yaw):\n");
Shunkai Yao51379452022-08-30 03:14:50 +00001088 ss.append(prefixSpace + " PerMinuteHistory:\n");
Shunkai Yao7de40382022-08-25 00:44:04 +00001089 ss += mPoseDurableRecorder.toString(level + 1);
Shunkai Yao51379452022-08-30 03:14:50 +00001090 ss.append(prefixSpace + " PerSecondHistory:\n");
Shunkai Yao7de40382022-08-25 00:44:04 +00001091 ss += mPoseRecorder.toString(level + 1);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001092 } else {
1093 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1094 }
1095
1096 if (needUnlock) {
1097 mLock.unlock();
1098 }
1099 return ss;
1100}
1101
Eric Laurent6d607012021-07-05 11:54:40 +02001102} // namespace android