blob: 2fe7b9e5e2a581ff46b120d0a6cbbb990ba99352 [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
Eric Laurent6d607012021-07-05 11:54:40 +020078// ---------------------------------------------------------------------------
79
Eric Laurent8a4259f2021-09-14 16:04:00 +020080class Spatializer::EngineCallbackHandler : public AHandler {
81public:
82 EngineCallbackHandler(wp<Spatializer> spatializer)
83 : mSpatializer(spatializer) {
84 }
85
86 enum {
87 // Device state callbacks
88 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
89 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
90 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
Eric Laurentdf2ece42022-07-20 13:49:47 +020091 kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
Eric Laurent8a4259f2021-09-14 16:04:00 +020092 };
93 static constexpr const char *kNumFramesKey = "numFrames";
94 static constexpr const char *kModeKey = "mode";
95 static constexpr const char *kTranslation0Key = "translation0";
96 static constexpr const char *kTranslation1Key = "translation1";
97 static constexpr const char *kTranslation2Key = "translation2";
98 static constexpr const char *kRotation0Key = "rotation0";
99 static constexpr const char *kRotation1Key = "rotation1";
100 static constexpr const char *kRotation2Key = "rotation2";
Eric Laurentdf2ece42022-07-20 13:49:47 +0200101 static constexpr const char *kLatencyModesKey = "latencyModes";
102
103 class LatencyModes : public RefBase {
104 public:
105 LatencyModes(audio_io_handle_t output,
106 const std::vector<audio_latency_mode_t>& latencyModes)
107 : mOutput(output), mLatencyModes(latencyModes) {}
108 ~LatencyModes() = default;
109
110 audio_io_handle_t mOutput;
111 std::vector<audio_latency_mode_t> mLatencyModes;
112 };
Eric Laurent8a4259f2021-09-14 16:04:00 +0200113
114 void onMessageReceived(const sp<AMessage> &msg) override {
Andy Hungb725c692022-12-14 14:25:49 -0800115 // No ALooper method to get the tid so update
116 // Spatializer priority on the first message received.
117 std::call_once(mPrioritySetFlag, [](){
118 const pid_t pid = getpid();
119 const pid_t tid = gettid();
120 (void)requestSpatializerPriority(pid, tid);
121 });
122
Eric Laurentdf2ece42022-07-20 13:49:47 +0200123 sp<Spatializer> spatializer = mSpatializer.promote();
124 if (spatializer == nullptr) {
125 ALOGW("%s: Cannot promote spatializer", __func__);
126 return;
127 }
Eric Laurent8a4259f2021-09-14 16:04:00 +0200128 switch (msg->what()) {
129 case kWhatOnFramesProcessed: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200130 int numFrames;
131 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
132 ALOGE("%s: Cannot find num frames!", __func__);
133 return;
134 }
135 if (numFrames > 0) {
136 spatializer->calculateHeadPose();
137 }
138 } break;
139 case kWhatOnHeadToStagePose: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200140 std::vector<float> headToStage(sHeadPoseKeys.size());
141 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
142 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
143 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
144 return;
145 }
146 }
147 spatializer->onHeadToStagePoseMsg(headToStage);
148 } break;
149 case kWhatOnActualModeChange: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200150 int mode;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200151 if (!msg->findInt32(kModeKey, &mode)) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200152 ALOGE("%s: Cannot find actualMode!", __func__);
153 return;
154 }
155 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
156 } break;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200157
158 case kWhatOnLatencyModesChanged: {
159 sp<RefBase> object;
160 if (!msg->findObject(kLatencyModesKey, &object)) {
161 ALOGE("%s: Cannot find latency modes!", __func__);
162 return;
163 }
164 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
165 spatializer->onSupportedLatencyModesChangedMsg(
166 latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
167 } break;
168
Eric Laurent8a4259f2021-09-14 16:04:00 +0200169 default:
170 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
171 }
172 }
173private:
174 wp<Spatializer> mSpatializer;
Andy Hungb725c692022-12-14 14:25:49 -0800175 std::once_flag mPrioritySetFlag;
Eric Laurent8a4259f2021-09-14 16:04:00 +0200176};
177
178const std::vector<const char *> Spatializer::sHeadPoseKeys = {
179 Spatializer::EngineCallbackHandler::kTranslation0Key,
180 Spatializer::EngineCallbackHandler::kTranslation1Key,
181 Spatializer::EngineCallbackHandler::kTranslation2Key,
182 Spatializer::EngineCallbackHandler::kRotation0Key,
183 Spatializer::EngineCallbackHandler::kRotation1Key,
184 Spatializer::EngineCallbackHandler::kRotation2Key,
185};
186
187// ---------------------------------------------------------------------------
Shunkai Yao5a251df2022-07-22 18:42:27 +0000188
189// Convert recorded sensor data to string with level indentation.
Shunkai Yao7de40382022-08-25 00:44:04 +0000190std::string Spatializer::HeadToStagePoseRecorder::toString(unsigned level) const {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000191 std::string prefixSpace(level, ' ');
192 return mPoseRecordLog.dumpToString((prefixSpace + " ").c_str(), Spatializer::mMaxLocalLogLine);
193}
194
195// Compute sensor data, record into local log when it is time.
Shunkai Yao7de40382022-08-25 00:44:04 +0000196void Spatializer::HeadToStagePoseRecorder::record(const std::vector<float>& headToStage) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000197 if (headToStage.size() != mPoseVectorSize) return;
198
199 if (mNumOfSampleSinceLastRecord++ == 0) {
200 mFirstSampleTimestamp = std::chrono::steady_clock::now();
201 }
202 // if it's time, do record and reset.
203 if (shouldRecordLog()) {
204 poseSumToAverage();
205 mPoseRecordLog.log(
Shunkai Yao7de40382022-08-25 00:44:04 +0000206 "mean: %s, min: %s, max %s, calculated %d samples in %0.4f second(s)",
Shunkai Yao5a251df2022-07-22 18:42:27 +0000207 Spatializer::toString<double>(mPoseRadianSum, true /* radianToDegree */).c_str(),
208 Spatializer::toString<float>(mMinPoseAngle, true /* radianToDegree */).c_str(),
209 Spatializer::toString<float>(mMaxPoseAngle, true /* radianToDegree */).c_str(),
Shunkai Yao7de40382022-08-25 00:44:04 +0000210 mNumOfSampleSinceLastRecord, mNumOfSecondsSinceLastRecord.count());
211 resetRecord();
Shunkai Yao5a251df2022-07-22 18:42:27 +0000212 }
213 // update stream average.
214 for (int i = 0; i < mPoseVectorSize; i++) {
215 mPoseRadianSum[i] += headToStage[i];
216 mMaxPoseAngle[i] = std::max(mMaxPoseAngle[i], headToStage[i]);
217 mMinPoseAngle[i] = std::min(mMinPoseAngle[i], headToStage[i]);
218 }
219 return;
220}
221
222// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200223sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
224 sp<Spatializer> spatializer;
225
226 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
227 if (effectsFactoryHal == nullptr) {
228 ALOGW("%s failed to create effect factory interface", __func__);
229 return spatializer;
230 }
231
232 std::vector<effect_descriptor_t> descriptors;
233 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200234 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200235 if (status != NO_ERROR) {
236 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
237 return spatializer;
238 }
239 ALOG_ASSERT(!descriptors.empty(),
240 "%s getDescriptors() returned no error but empty list", __func__);
241
Shunkai Yao5a251df2022-07-22 18:42:27 +0000242 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200243 sp<EffectHalInterface> effect;
244 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
245 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000246 ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
247 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200248
249 if (status == NO_ERROR && effect != nullptr) {
250 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700251 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
252 spatializer.clear();
Andy Hung0e3205d2022-08-29 14:14:58 -0700253 ALOGW("%s loadEngine error: %d effect Id %" PRId64,
254 __func__, status, effect ? effect->effectId() : 0);
255 } else {
256 spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
257 effect ? effect->effectId() : 0);
Eric Laurent2be8b292021-08-23 09:44:33 -0700258 }
Eric Laurent6d607012021-07-05 11:54:40 +0200259 }
260
261 return spatializer;
262}
263
Eric Laurent2be8b292021-08-23 09:44:33 -0700264Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
265 : mEngineDescriptor(engineDescriptor),
266 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200267 ALOGV("%s", __func__);
Andy Hung393de3a2022-12-06 16:33:20 -0800268 setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
Eric Laurent6d607012021-07-05 11:54:40 +0200269}
270
Eric Laurent8a4259f2021-09-14 16:04:00 +0200271void Spatializer::onFirstRef() {
272 mLooper = new ALooper;
273 mLooper->setName("Spatializer-looper");
274 mLooper->start(
275 /*runOnCallingThread*/false,
276 /*canCallJava*/ false,
Andy Hung898a39f2022-11-07 20:09:20 -0800277 PRIORITY_URGENT_AUDIO);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200278
279 mHandler = new EngineCallbackHandler(this);
280 mLooper->registerHandler(mHandler);
281}
282
Eric Laurent6d607012021-07-05 11:54:40 +0200283Spatializer::~Spatializer() {
284 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200285 if (mLooper != nullptr) {
286 mLooper->stop();
287 mLooper->unregisterHandler(mHandler->id());
288 }
289 mLooper.clear();
290 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200291}
292
Andy Hung4442d042022-08-17 17:27:32 -0700293static std::string channelMaskVectorToString(
294 const std::vector<audio_channel_mask_t>& masks) {
295 std::stringstream ss;
296 for (const auto &mask : masks) {
297 if (ss.tellp() != 0) ss << "|";
298 ss << mask;
299 }
300 return ss.str();
301}
302
Eric Laurent2be8b292021-08-23 09:44:33 -0700303status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
304 ALOGV("%s", __func__);
305
306 std::vector<bool> supportsHeadTracking;
307 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
308 &supportsHeadTracking);
309 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700310 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700311 return status;
312 }
313 mSupportsHeadTracking = supportsHeadTracking[0];
314
Andy Hung119dbdb2022-05-11 19:20:13 -0700315 std::vector<media::SpatializationLevel> spatializationLevels;
316 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
317 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700318 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700319 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700320 return status;
321 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700322 bool noneLevelFound = false;
323 bool activeLevelFound = false;
324 for (const auto spatializationLevel : spatializationLevels) {
325 if (!aidl_utils::isValidEnum(spatializationLevel)) {
326 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
327 continue;
328 }
329 if (spatializationLevel == media::SpatializationLevel::NONE) {
330 noneLevelFound = true;
331 } else {
332 activeLevelFound = true;
333 }
334 // we don't detect duplicates.
335 mLevels.emplace_back(spatializationLevel);
336 }
337 if (!noneLevelFound || !activeLevelFound) {
338 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
339 " and another valid level", __func__);
340 return BAD_VALUE;
341 }
342
343 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700344 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700345 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700346 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700347 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700348 return status;
349 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000350
Andy Hung119dbdb2022-05-11 19:20:13 -0700351 for (const auto spatializationMode : spatializationModes) {
352 if (!aidl_utils::isValidEnum(spatializationMode)) {
353 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
354 continue;
355 }
356 // we don't detect duplicates.
357 mSpatializationModes.emplace_back(spatializationMode);
358 }
359 if (mSpatializationModes.empty()) {
360 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
361 return BAD_VALUE;
362 }
363
364 std::vector<audio_channel_mask_t> channelMasks;
365 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
366 &channelMasks);
367 if (status != NO_ERROR) {
368 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
369 return status;
370 }
371 for (const auto channelMask : channelMasks) {
372 if (!audio_is_channel_mask_spatialized(channelMask)) {
373 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
374 continue;
375 }
376 // we don't detect duplicates.
377 mChannelMasks.emplace_back(channelMask);
378 }
379 if (mChannelMasks.empty()) {
380 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
381 return BAD_VALUE;
382 }
Andy Hunga461a002022-05-17 10:36:02 -0700383
384 // Currently we expose only RELATIVE_WORLD.
385 // This is a limitation of the head tracking library based on a UX choice.
386 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
387 if (mSupportsHeadTracking) {
388 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
389 }
390 mediametrics::LogItem(mMetricsId)
391 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
Andy Hung4442d042022-08-17 17:27:32 -0700392 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
Andy Hunga461a002022-05-17 10:36:02 -0700393 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
394 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
395 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
396 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
397 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700398 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700399}
400
Andy Hung757bc812022-09-13 18:53:06 -0700401/* static */
402void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
403 mediametrics::LogItem(kDefaultMetricsId)
404 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
405 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
406 .set(AMEDIAMETRICS_PROP_LEVELS, "")
407 .set(AMEDIAMETRICS_PROP_MODES, "")
408 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
409 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
410 .record();
411}
412
Eric Laurent2be8b292021-08-23 09:44:33 -0700413/** Gets the channel mask, sampling rate and format set for the spatializer input. */
414audio_config_base_t Spatializer::getAudioInConfig() const {
415 std::lock_guard lock(mLock);
416 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
417 // For now use highest supported channel count
Andy Hung0e3205d2022-08-29 14:14:58 -0700418 config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
Eric Laurent2be8b292021-08-23 09:44:33 -0700419 return config;
420}
421
Eric Laurent6d607012021-07-05 11:54:40 +0200422status_t Spatializer::registerCallback(
423 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700424 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200425 if (callback == nullptr) {
426 return BAD_VALUE;
427 }
428
Eric Laurentb57604f2022-08-31 16:07:50 +0200429 if (mSpatializerCallback != nullptr) {
430 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
431 ALOGW("%s: Registering callback %p again",
432 __func__, mSpatializerCallback.get());
433 return NO_ERROR;
434 }
435 ALOGE("%s: Already one client registered with callback %p",
436 __func__, mSpatializerCallback.get());
437 return INVALID_OPERATION;
438 }
439
Eric Laurent6d607012021-07-05 11:54:40 +0200440 sp<IBinder> binder = IInterface::asBinder(callback);
441 status_t status = binder->linkToDeath(this);
442 if (status == NO_ERROR) {
443 mSpatializerCallback = callback;
444 }
445 ALOGV("%s status %d", __func__, status);
446 return status;
447}
448
449// IBinder::DeathRecipient
450void Spatializer::binderDied(__unused const wp<IBinder> &who) {
451 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700452 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200453 mLevel = SpatializationLevel::NONE;
454 mSpatializerCallback.clear();
455 }
456 ALOGV("%s", __func__);
457 mPolicyCallback->onCheckSpatializer();
458}
459
460// ISpatializer
461Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
462 ALOGV("%s", __func__);
463 if (levels == nullptr) {
464 return binderStatusFromStatusT(BAD_VALUE);
465 }
Andy Hunga461a002022-05-17 10:36:02 -0700466 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700467 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200468 return Status::ok();
469}
470
Eric Laurent2be8b292021-08-23 09:44:33 -0700471Status Spatializer::setLevel(SpatializationLevel level) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000472 ALOGV("%s level %s", __func__, media::toString(level).c_str());
473 mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
Eric Laurent6d607012021-07-05 11:54:40 +0200474 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700475 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200476 return binderStatusFromStatusT(BAD_VALUE);
477 }
478 sp<media::INativeSpatializerCallback> callback;
479 bool levelChanged = false;
480 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700481 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200482 levelChanged = mLevel != level;
483 mLevel = level;
484 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700485
486 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200487 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700488 }
Eric Laurent9249d342022-03-18 11:55:56 +0100489 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200490 }
491
492 if (levelChanged) {
493 mPolicyCallback->onCheckSpatializer();
494 if (callback != nullptr) {
495 callback->onLevelChanged(level);
496 }
497 }
498 return Status::ok();
499}
500
Eric Laurent2be8b292021-08-23 09:44:33 -0700501Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200502 if (level == nullptr) {
503 return binderStatusFromStatusT(BAD_VALUE);
504 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700505 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200506 *level = mLevel;
507 ALOGV("%s level %d", __func__, (int)*level);
508 return Status::ok();
509}
510
Eric Laurentc87402b2021-09-17 16:49:42 +0200511Status Spatializer::isHeadTrackingSupported(bool *supports) {
512 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
513 if (supports == nullptr) {
514 return binderStatusFromStatusT(BAD_VALUE);
515 }
516 std::lock_guard lock(mLock);
517 *supports = mSupportsHeadTracking;
518 return Status::ok();
519}
520
Eric Laurent6d607012021-07-05 11:54:40 +0200521Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700522 std::vector<SpatializerHeadTrackingMode>* modes) {
523 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200524 ALOGV("%s", __func__);
525 if (modes == nullptr) {
526 return binderStatusFromStatusT(BAD_VALUE);
527 }
Andy Hunga461a002022-05-17 10:36:02 -0700528 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200529 return Status::ok();
530}
531
Eric Laurent2be8b292021-08-23 09:44:33 -0700532Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000533 ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700534
535 if (!mSupportsHeadTracking) {
536 return binderStatusFromStatusT(INVALID_OPERATION);
537 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000538 mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700539 std::lock_guard lock(mLock);
540 switch (mode) {
541 case SpatializerHeadTrackingMode::OTHER:
542 return binderStatusFromStatusT(BAD_VALUE);
543 case SpatializerHeadTrackingMode::DISABLED:
544 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
545 break;
546 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
547 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
548 break;
549 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
550 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
551 break;
552 }
553
Eric Laurent11094172022-04-05 18:27:42 +0200554 checkPoseController_l();
555 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700556
557 return Status::ok();
558}
559
560Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200561 if (mode == nullptr) {
562 return binderStatusFromStatusT(BAD_VALUE);
563 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700564 std::lock_guard lock(mLock);
565 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200566 ALOGV("%s mode %d", __func__, (int)*mode);
567 return Status::ok();
568}
569
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700570Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200571 if (!mSupportsHeadTracking) {
572 return binderStatusFromStatusT(INVALID_OPERATION);
573 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700574 std::lock_guard lock(mLock);
575 if (mPoseController != nullptr) {
576 mPoseController->recenter();
577 }
Eric Laurent6d607012021-07-05 11:54:40 +0200578 return Status::ok();
579}
580
581Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200582 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200583 if (!mSupportsHeadTracking) {
584 return binderStatusFromStatusT(INVALID_OPERATION);
585 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700586 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
587 if (!maybePose.has_value()) {
588 ALOGW("Invalid screenToStage vector.");
589 return binderStatusFromStatusT(BAD_VALUE);
590 }
591 std::lock_guard lock(mLock);
592 if (mPoseController != nullptr) {
Shunkai Yao7de40382022-08-25 00:44:04 +0000593 mLocalLog.log("%s with screenToStage %s", __func__, toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700594 mPoseController->setScreenToStagePose(maybePose.value());
595 }
Eric Laurent6d607012021-07-05 11:54:40 +0200596 return Status::ok();
597}
598
599Status Spatializer::release() {
600 ALOGV("%s", __func__);
601 bool levelChanged = false;
602 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700603 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200604 if (mSpatializerCallback == nullptr) {
605 return binderStatusFromStatusT(INVALID_OPERATION);
606 }
607
608 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
609 binder->unlinkToDeath(this);
610 mSpatializerCallback.clear();
611
612 levelChanged = mLevel != SpatializationLevel::NONE;
613 mLevel = SpatializationLevel::NONE;
614 }
615
616 if (levelChanged) {
617 mPolicyCallback->onCheckSpatializer();
618 }
619 return Status::ok();
620}
621
Eric Laurent2be8b292021-08-23 09:44:33 -0700622Status Spatializer::setHeadSensor(int sensorHandle) {
623 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200624 if (!mSupportsHeadTracking) {
625 return binderStatusFromStatusT(INVALID_OPERATION);
626 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700627 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700628 if (mHeadSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000629 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700630 mHeadSensor = sensorHandle;
631 checkPoseController_l();
632 checkSensorsState_l();
633 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700634 return Status::ok();
635}
636
637Status Spatializer::setScreenSensor(int sensorHandle) {
638 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200639 if (!mSupportsHeadTracking) {
640 return binderStatusFromStatusT(INVALID_OPERATION);
641 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700642 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700643 if (mScreenSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000644 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700645 mScreenSensor = sensorHandle;
646 // TODO: consider a new method setHeadAndScreenSensor()
647 // because we generally set both at the same time.
648 // This will avoid duplicated work and recentering.
649 checkSensorsState_l();
650 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700651 return Status::ok();
652}
653
654Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
655 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200656 if (!mSupportsHeadTracking) {
657 return binderStatusFromStatusT(INVALID_OPERATION);
658 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700659 std::lock_guard lock(mLock);
660 mDisplayOrientation = physicalToLogicalAngle;
Shunkai Yao5a251df2022-07-22 18:42:27 +0000661 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700662 if (mPoseController != nullptr) {
663 mPoseController->setDisplayOrientation(mDisplayOrientation);
664 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200665 if (mEngine != nullptr) {
666 setEffectParameter_l(
667 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
668 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700669 return Status::ok();
670}
671
672Status Spatializer::setHingeAngle(float hingeAngle) {
673 std::lock_guard lock(mLock);
674 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
675 if (mEngine != nullptr) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000676 mLocalLog.log("%s with %f", __func__, hingeAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700677 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
678 }
679 return Status::ok();
680}
681
682Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
683 ALOGV("%s", __func__);
684 if (modes == nullptr) {
685 return binderStatusFromStatusT(BAD_VALUE);
686 }
687 *modes = mSpatializationModes;
688 return Status::ok();
689}
690
Eric Laurent67816e32021-09-16 15:18:40 +0200691Status Spatializer::registerHeadTrackingCallback(
692 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
693 ALOGV("%s callback %p", __func__, callback.get());
694 std::lock_guard lock(mLock);
695 if (!mSupportsHeadTracking) {
696 return binderStatusFromStatusT(INVALID_OPERATION);
697 }
698 mHeadTrackingCallback = callback;
699 return Status::ok();
700}
701
Eric Laurentc87402b2021-09-17 16:49:42 +0200702Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
703 ALOGV("%s key %d", __func__, key);
704 std::lock_guard lock(mLock);
705 status_t status = INVALID_OPERATION;
706 if (mEngine != nullptr) {
707 status = setEffectParameter_l(key, value);
708 }
709 return binderStatusFromStatusT(status);
710}
711
712Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700713 ALOGV("%s key %d value size %d", __func__, key,
714 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200715 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700716 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200717 }
718 std::lock_guard lock(mLock);
719 status_t status = INVALID_OPERATION;
720 if (mEngine != nullptr) {
721 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
722 status = getEffectParameter_l(key, value);
723 }
724 return binderStatusFromStatusT(status);
725}
726
727Status Spatializer::getOutput(int *output) {
728 ALOGV("%s", __func__);
729 if (output == nullptr) {
730 binderStatusFromStatusT(BAD_VALUE);
731 }
732 std::lock_guard lock(mLock);
733 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
734 ALOGV("%s got output %d", __func__, *output);
735 return Status::ok();
736}
737
Eric Laurent2be8b292021-08-23 09:44:33 -0700738// SpatializerPoseController::Listener
739void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
740 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200741 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
742 "onHeadToStagePose() called with no head tracking support!");
743
Eric Laurent2be8b292021-08-23 09:44:33 -0700744 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200745 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
746 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200747 sp<AMessage> msg =
748 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
749 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
750 msg->setFloat(sHeadPoseKeys[i], vec[i]);
751 }
752 msg->post();
753}
754
Eric Laurent3c48ad92022-10-21 11:28:32 +0200755void Spatializer::resetEngineHeadPose_l() {
756 ALOGV("%s mEngine %p", __func__, mEngine.get());
757 if (mEngine == nullptr) {
758 return;
759 }
760 const std::vector<float> headToStage(6, 0.0);
761 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
762 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
763 std::vector<SpatializerHeadTrackingMode>{SpatializerHeadTrackingMode::DISABLED});
764}
765
Eric Laurent8a4259f2021-09-14 16:04:00 +0200766void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
767 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200768 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700769 {
770 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200771 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700772 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200773 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Shunkai Yao7de40382022-08-25 00:44:04 +0000774 mPoseRecorder.record(headToStage);
775 mPoseDurableRecorder.record(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700776 }
777 }
778
779 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200780 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700781 }
782}
783
784void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao51379452022-08-30 03:14:50 +0000785 std::string modeStr = media::toString(mode);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000786 ALOGV("%s(%s)", __func__, modeStr.c_str());
Shunkai Yao51379452022-08-30 03:14:50 +0000787 sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200788 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
789 msg->post();
790}
791
792void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
793 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200794 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700795 SpatializerHeadTrackingMode spatializerMode;
796 {
797 std::lock_guard lock(mLock);
798 if (!mSupportsHeadTracking) {
799 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
800 } else {
801 switch (mode) {
802 case HeadTrackingMode::STATIC:
803 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
804 break;
805 case HeadTrackingMode::WORLD_RELATIVE:
806 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
807 break;
808 case HeadTrackingMode::SCREEN_RELATIVE:
809 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
810 break;
811 default:
812 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
813 }
814 }
815 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200816 if (mEngine != nullptr) {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200817 if (spatializerMode == SpatializerHeadTrackingMode::DISABLED) {
818 resetEngineHeadPose_l();
819 } else {
820 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
821 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
822 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200823 }
Eric Laurent67816e32021-09-16 15:18:40 +0200824 callback = mHeadTrackingCallback;
Shunkai Yao51379452022-08-30 03:14:50 +0000825 mLocalLog.log("%s: %s, spatializerMode %s", __func__, media::toString(mode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +0000826 media::toString(spatializerMode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700827 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200828 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700829 callback->onHeadTrackingModeChanged(spatializerMode);
830 }
831}
832
Eric Laurent15903592022-02-24 20:44:36 +0100833status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200834 bool outputChanged = false;
835 sp<media::INativeSpatializerCallback> callback;
836
Eric Laurent2be8b292021-08-23 09:44:33 -0700837 {
838 std::lock_guard lock(mLock);
839 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000840 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
841 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700842 if (mOutput != AUDIO_IO_HANDLE_NONE) {
843 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
844 // remove FX instance
845 mEngine->setEnabled(false);
846 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100847 mPoseController.reset();
Eric Laurentb387fb42022-05-03 18:19:35 +0200848 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700849 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200850
Eric Laurent2be8b292021-08-23 09:44:33 -0700851 // create FX instance on output
852 AttributionSourceState attributionSource = AttributionSourceState();
853 mEngine = new AudioEffect(attributionSource);
854 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
855 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
856 false /* probe */, true /* notifyFramesProcessed */);
857 status_t status = mEngine->initCheck();
858 ALOGV("%s mEngine create status %d", __func__, (int)status);
859 if (status != NO_ERROR) {
860 return status;
861 }
862
Eric Laurent4a872862021-10-11 17:06:47 +0200863 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700864 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200865 mNumActiveTracks = numActiveTracks;
Eric Laurentb387fb42022-05-03 18:19:35 +0200866 AudioSystem::addSupportedLatencyModesCallback(this);
867
868 std::vector<audio_latency_mode_t> latencyModes;
869 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
870 if (status == OK) {
871 mSupportedLatencyModes = latencyModes;
872 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700873
Eric Laurent11094172022-04-05 18:27:42 +0200874 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200875 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200876 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100877 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200878 }
Eric Laurent4a872862021-10-11 17:06:47 +0200879 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200880 }
Eric Laurent4a872862021-10-11 17:06:47 +0200881
882 if (outputChanged && callback != nullptr) {
883 callback->onOutputChanged(output);
884 }
885
Eric Laurent6d607012021-07-05 11:54:40 +0200886 return NO_ERROR;
887}
888
889audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700890 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200891 sp<media::INativeSpatializerCallback> callback;
892
893 {
894 std::lock_guard lock(mLock);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000895 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +0200896 ALOGV("%s mOutput %d", __func__, (int)mOutput);
897 if (mOutput == AUDIO_IO_HANDLE_NONE) {
898 return output;
899 }
900 // remove FX instance
901 mEngine->setEnabled(false);
902 mEngine.clear();
Eric Laurentb387fb42022-05-03 18:19:35 +0200903 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200904 output = mOutput;
905 mOutput = AUDIO_IO_HANDLE_NONE;
906 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200907 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200908 }
Eric Laurent4a872862021-10-11 17:06:47 +0200909
910 if (callback != nullptr) {
911 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
912 }
Eric Laurent6d607012021-07-05 11:54:40 +0200913 return output;
914}
915
Eric Laurentb387fb42022-05-03 18:19:35 +0200916void Spatializer::onSupportedLatencyModesChanged(
917 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200918 ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
919 sp<AMessage> msg =
920 new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
921 msg->setObject(EngineCallbackHandler::kLatencyModesKey,
922 sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
923 msg->post();
924}
925
926void Spatializer::onSupportedLatencyModesChangedMsg(
927 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
Eric Laurentb387fb42022-05-03 18:19:35 +0200928 std::lock_guard lock(mLock);
Eric Laurentdf2ece42022-07-20 13:49:47 +0200929 ALOGV("%s output %d mOutput %d num modes %zu",
930 __func__, (int)output, (int)mOutput, modes.size());
Eric Laurentb387fb42022-05-03 18:19:35 +0200931 if (output == mOutput) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200932 mSupportedLatencyModes = std::move(modes);
Eric Laurentb387fb42022-05-03 18:19:35 +0200933 checkSensorsState_l();
934 }
935}
936
Eric Laurent15903592022-02-24 20:44:36 +0100937void Spatializer::updateActiveTracks(size_t numActiveTracks) {
938 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200939 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000940 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200941 mNumActiveTracks = numActiveTracks;
942 checkEngineState_l();
943 checkSensorsState_l();
944 }
Eric Laurent15903592022-02-24 20:44:36 +0100945}
946
Eric Laurent9249d342022-03-18 11:55:56 +0100947void Spatializer::checkSensorsState_l() {
Eric Laurentb387fb42022-05-03 18:19:35 +0200948 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
Andy Hungc0896c72022-10-21 17:30:30 -0700949 const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
950 const bool supportsLowLatencyMode = supportsSetLatencyMode && std::find(
951 mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
952 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
Eric Laurent3c48ad92022-10-21 11:28:32 +0200953 if (mSupportsHeadTracking) {
954 if (mPoseController != nullptr) {
Andy Hungc0896c72022-10-21 17:30:30 -0700955 // TODO(b/253297301, b/255433067) reenable low latency condition check
956 // for Head Tracking after Bluetooth HAL supports it correctly.
957 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent3c48ad92022-10-21 11:28:32 +0200958 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
959 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
960 if (mEngine != nullptr) {
961 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
962 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
963 }
964 mPoseController->setHeadSensor(mHeadSensor);
965 mPoseController->setScreenSensor(mScreenSensor);
Andy Hungc0896c72022-10-21 17:30:30 -0700966 if (supportsLowLatencyMode) requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent3c48ad92022-10-21 11:28:32 +0200967 } else {
968 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
969 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
970 resetEngineHeadPose_l();
971 }
Eric Laurent15903592022-02-24 20:44:36 +0100972 } else {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200973 resetEngineHeadPose_l();
Eric Laurent15903592022-02-24 20:44:36 +0100974 }
975 }
Andy Hungc0896c72022-10-21 17:30:30 -0700976 if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
Andy Hung5d8618d2022-11-17 17:21:45 -0800977 const status_t status =
978 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
979 ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
980 __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
Eric Laurentb387fb42022-05-03 18:19:35 +0200981 }
Eric Laurent15903592022-02-24 20:44:36 +0100982}
983
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200984void Spatializer::checkEngineState_l() {
985 if (mEngine != nullptr) {
986 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
987 mEngine->setEnabled(true);
988 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
989 std::vector<SpatializationLevel>{mLevel});
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200990 } else {
991 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
992 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
993 mEngine->setEnabled(false);
994 }
995 }
996}
997
Eric Laurent11094172022-04-05 18:27:42 +0200998void Spatializer::checkPoseController_l() {
999 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
1000 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
1001
1002 if (isControllerNeeded && mPoseController == nullptr) {
1003 mPoseController = std::make_shared<SpatializerPoseController>(
1004 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +02001005 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +02001006 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
1007 "%s could not allocate pose controller", __func__);
1008 mPoseController->setDisplayOrientation(mDisplayOrientation);
1009 } else if (!isControllerNeeded && mPoseController != nullptr) {
1010 mPoseController.reset();
Eric Laurent3c48ad92022-10-21 11:28:32 +02001011 resetEngineHeadPose_l();
Eric Laurent11094172022-04-05 18:27:42 +02001012 }
1013 if (mPoseController != nullptr) {
1014 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
1015 }
1016}
1017
Eric Laurent2be8b292021-08-23 09:44:33 -07001018void Spatializer::calculateHeadPose() {
1019 ALOGV("%s", __func__);
1020 std::lock_guard lock(mLock);
1021 if (mPoseController != nullptr) {
1022 mPoseController->calculateAsync();
1023 }
1024}
Eric Laurent6d607012021-07-05 11:54:40 +02001025
Eric Laurent2be8b292021-08-23 09:44:33 -07001026void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +02001027 if (user == nullptr) {
1028 return;
1029 }
Eric Laurent2be8b292021-08-23 09:44:33 -07001030 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +02001031 switch (event) {
1032 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -07001033 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +01001034 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +02001035 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -07001036 } break;
Eric Laurent6d607012021-07-05 11:54:40 +02001037 default:
Eric Laurent9249d342022-03-18 11:55:56 +01001038 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +02001039 break;
1040 }
1041}
1042
Eric Laurent8a4259f2021-09-14 16:04:00 +02001043void Spatializer::postFramesProcessedMsg(int frames) {
1044 sp<AMessage> msg =
1045 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
1046 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
1047 msg->post();
1048}
1049
Shunkai Yao5a251df2022-07-22 18:42:27 +00001050std::string Spatializer::toString(unsigned level) const {
1051 std::string prefixSpace;
1052 prefixSpace.append(level, ' ');
1053 std::string ss = prefixSpace + "Spatializer:\n";
1054 bool needUnlock = false;
1055
1056 prefixSpace += ' ';
1057 if (!mLock.try_lock()) {
1058 // dumpsys even try_lock failed, information dump can be useful although may not accurate
1059 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1060 } else {
1061 needUnlock = true;
1062 }
1063
1064 // Spatializer class information.
1065 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1066 ss.append(prefixSpace).append("Supported levels: [");
1067 for (auto& level : mLevels) {
1068 base::StringAppendF(&ss, " %s", media::toString(level).c_str());
1069 }
1070 base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
1071
1072 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1073 for (auto& mode : mHeadTrackingModes) {
1074 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1075 }
1076 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
Shunkai Yao51379452022-08-30 03:14:50 +00001077 media::toString(mDesiredHeadTrackingMode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +00001078 media::toString(mActualHeadTrackingMode).c_str());
1079
1080 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1081 for (auto& mode : mSpatializationModes) {
1082 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1083 }
1084 ss += "]\n";
1085
1086 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1087 for (auto& mask : mChannelMasks) {
1088 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1089 }
1090 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1091 mSupportsHeadTracking ? "true" : "false");
1092 // 2. Settings (Output, tracks)
1093 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1094 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1095
1096 // 3. Sensors, Effect information.
1097 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1098 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1099 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1100 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1101 mDisplayOrientation);
1102
1103 ss.append(prefixSpace + "CommandLog:\n");
1104 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001105
1106 // PostController dump.
1107 if (mPoseController != nullptr) {
1108 ss += mPoseController->toString(level + 1);
Shunkai Yao7de40382022-08-25 00:44:04 +00001109 ss.append(prefixSpace +
1110 "Sensor data format - [rx, ry, rz, vx, vy, vz] (units-degree, "
1111 "r-transform, v-angular velocity, x-pitch, y-roll, z-yaw):\n");
Shunkai Yao51379452022-08-30 03:14:50 +00001112 ss.append(prefixSpace + " PerMinuteHistory:\n");
Shunkai Yao7de40382022-08-25 00:44:04 +00001113 ss += mPoseDurableRecorder.toString(level + 1);
Shunkai Yao51379452022-08-30 03:14:50 +00001114 ss.append(prefixSpace + " PerSecondHistory:\n");
Shunkai Yao7de40382022-08-25 00:44:04 +00001115 ss += mPoseRecorder.toString(level + 1);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001116 } else {
1117 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1118 }
1119
1120 if (needUnlock) {
1121 mLock.unlock();
1122 }
1123 return ss;
1124}
1125
Eric Laurent6d607012021-07-05 11:54:40 +02001126} // namespace android