blob: 277c91b824b2357ecc931a4039da8ea4154ea0c0 [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>
Eric Laurent6d607012021-07-05 11:54:40 +020037#include <mediautils/ServiceUtilities.h>
38#include <utils/Thread.h>
39
40#include "Spatializer.h"
41
42namespace android {
43
44using aidl_utils::statusTFromBinderStatus;
45using aidl_utils::binderStatusFromStatusT;
46using android::content::AttributionSourceState;
47using binder::Status;
Eric Laurent2be8b292021-08-23 09:44:33 -070048using media::HeadTrackingMode;
49using media::Pose3f;
Eric Laurent6d607012021-07-05 11:54:40 +020050using media::SpatializationLevel;
Eric Laurent2be8b292021-08-23 09:44:33 -070051using media::SpatializationMode;
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070052using media::SpatializerHeadTrackingMode;
Eric Laurent2be8b292021-08-23 09:44:33 -070053using media::SensorPoseProvider;
54
Eric Laurent2be8b292021-08-23 09:44:33 -070055using namespace std::chrono_literals;
Eric Laurent6d607012021-07-05 11:54:40 +020056
57#define VALUE_OR_RETURN_BINDER_STATUS(x) \
58 ({ auto _tmp = (x); \
59 if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
60 std::move(_tmp.value()); })
61
Andy Hung0e3205d2022-08-29 14:14:58 -070062static audio_channel_mask_t getMaxChannelMask(
63 const std::vector<audio_channel_mask_t>& masks, size_t channelLimit = SIZE_MAX) {
Andy Hunga461a002022-05-17 10:36:02 -070064 uint32_t maxCount = 0;
65 audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
66 for (auto mask : masks) {
67 const size_t count = audio_channel_count_from_out_mask(mask);
Andy Hung0e3205d2022-08-29 14:14:58 -070068 if (count > channelLimit) continue; // ignore masks greater than channelLimit
Andy Hunga461a002022-05-17 10:36:02 -070069 if (count > maxCount) {
70 maxMask = mask;
71 maxCount = count;
72 }
73 }
74 return maxMask;
75}
76
Eric Laurent6d607012021-07-05 11:54:40 +020077// ---------------------------------------------------------------------------
78
Eric Laurent8a4259f2021-09-14 16:04:00 +020079class Spatializer::EngineCallbackHandler : public AHandler {
80public:
81 EngineCallbackHandler(wp<Spatializer> spatializer)
82 : mSpatializer(spatializer) {
83 }
84
85 enum {
86 // Device state callbacks
87 kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
88 kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
89 kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
Eric Laurentdf2ece42022-07-20 13:49:47 +020090 kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
Eric Laurent8a4259f2021-09-14 16:04:00 +020091 };
92 static constexpr const char *kNumFramesKey = "numFrames";
93 static constexpr const char *kModeKey = "mode";
94 static constexpr const char *kTranslation0Key = "translation0";
95 static constexpr const char *kTranslation1Key = "translation1";
96 static constexpr const char *kTranslation2Key = "translation2";
97 static constexpr const char *kRotation0Key = "rotation0";
98 static constexpr const char *kRotation1Key = "rotation1";
99 static constexpr const char *kRotation2Key = "rotation2";
Eric Laurentdf2ece42022-07-20 13:49:47 +0200100 static constexpr const char *kLatencyModesKey = "latencyModes";
101
102 class LatencyModes : public RefBase {
103 public:
104 LatencyModes(audio_io_handle_t output,
105 const std::vector<audio_latency_mode_t>& latencyModes)
106 : mOutput(output), mLatencyModes(latencyModes) {}
107 ~LatencyModes() = default;
108
109 audio_io_handle_t mOutput;
110 std::vector<audio_latency_mode_t> mLatencyModes;
111 };
Eric Laurent8a4259f2021-09-14 16:04:00 +0200112
113 void onMessageReceived(const sp<AMessage> &msg) override {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200114 sp<Spatializer> spatializer = mSpatializer.promote();
115 if (spatializer == nullptr) {
116 ALOGW("%s: Cannot promote spatializer", __func__);
117 return;
118 }
Eric Laurent8a4259f2021-09-14 16:04:00 +0200119 switch (msg->what()) {
120 case kWhatOnFramesProcessed: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200121 int numFrames;
122 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
123 ALOGE("%s: Cannot find num frames!", __func__);
124 return;
125 }
126 if (numFrames > 0) {
127 spatializer->calculateHeadPose();
128 }
129 } break;
130 case kWhatOnHeadToStagePose: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200131 std::vector<float> headToStage(sHeadPoseKeys.size());
132 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
133 if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
134 ALOGE("%s: Cannot find kTranslation0Key!", __func__);
135 return;
136 }
137 }
138 spatializer->onHeadToStagePoseMsg(headToStage);
139 } break;
140 case kWhatOnActualModeChange: {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200141 int mode;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200142 if (!msg->findInt32(kModeKey, &mode)) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200143 ALOGE("%s: Cannot find actualMode!", __func__);
144 return;
145 }
146 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
147 } break;
Eric Laurentdf2ece42022-07-20 13:49:47 +0200148
149 case kWhatOnLatencyModesChanged: {
150 sp<RefBase> object;
151 if (!msg->findObject(kLatencyModesKey, &object)) {
152 ALOGE("%s: Cannot find latency modes!", __func__);
153 return;
154 }
155 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
156 spatializer->onSupportedLatencyModesChangedMsg(
157 latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
158 } break;
159
Eric Laurent8a4259f2021-09-14 16:04:00 +0200160 default:
161 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
162 }
163 }
164private:
165 wp<Spatializer> mSpatializer;
166};
167
168const std::vector<const char *> Spatializer::sHeadPoseKeys = {
169 Spatializer::EngineCallbackHandler::kTranslation0Key,
170 Spatializer::EngineCallbackHandler::kTranslation1Key,
171 Spatializer::EngineCallbackHandler::kTranslation2Key,
172 Spatializer::EngineCallbackHandler::kRotation0Key,
173 Spatializer::EngineCallbackHandler::kRotation1Key,
174 Spatializer::EngineCallbackHandler::kRotation2Key,
175};
176
177// ---------------------------------------------------------------------------
Shunkai Yao5a251df2022-07-22 18:42:27 +0000178
179// Convert recorded sensor data to string with level indentation.
Shunkai Yao7de40382022-08-25 00:44:04 +0000180std::string Spatializer::HeadToStagePoseRecorder::toString(unsigned level) const {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000181 std::string prefixSpace(level, ' ');
182 return mPoseRecordLog.dumpToString((prefixSpace + " ").c_str(), Spatializer::mMaxLocalLogLine);
183}
184
185// Compute sensor data, record into local log when it is time.
Shunkai Yao7de40382022-08-25 00:44:04 +0000186void Spatializer::HeadToStagePoseRecorder::record(const std::vector<float>& headToStage) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000187 if (headToStage.size() != mPoseVectorSize) return;
188
189 if (mNumOfSampleSinceLastRecord++ == 0) {
190 mFirstSampleTimestamp = std::chrono::steady_clock::now();
191 }
192 // if it's time, do record and reset.
193 if (shouldRecordLog()) {
194 poseSumToAverage();
195 mPoseRecordLog.log(
Shunkai Yao7de40382022-08-25 00:44:04 +0000196 "mean: %s, min: %s, max %s, calculated %d samples in %0.4f second(s)",
Shunkai Yao5a251df2022-07-22 18:42:27 +0000197 Spatializer::toString<double>(mPoseRadianSum, true /* radianToDegree */).c_str(),
198 Spatializer::toString<float>(mMinPoseAngle, true /* radianToDegree */).c_str(),
199 Spatializer::toString<float>(mMaxPoseAngle, true /* radianToDegree */).c_str(),
Shunkai Yao7de40382022-08-25 00:44:04 +0000200 mNumOfSampleSinceLastRecord, mNumOfSecondsSinceLastRecord.count());
201 resetRecord();
Shunkai Yao5a251df2022-07-22 18:42:27 +0000202 }
203 // update stream average.
204 for (int i = 0; i < mPoseVectorSize; i++) {
205 mPoseRadianSum[i] += headToStage[i];
206 mMaxPoseAngle[i] = std::max(mMaxPoseAngle[i], headToStage[i]);
207 mMinPoseAngle[i] = std::min(mMinPoseAngle[i], headToStage[i]);
208 }
209 return;
210}
211
212// ---------------------------------------------------------------------------
Eric Laurent6d607012021-07-05 11:54:40 +0200213sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
214 sp<Spatializer> spatializer;
215
216 sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
217 if (effectsFactoryHal == nullptr) {
218 ALOGW("%s failed to create effect factory interface", __func__);
219 return spatializer;
220 }
221
222 std::vector<effect_descriptor_t> descriptors;
223 status_t status =
Eric Laurent1c5e2e32021-08-18 18:50:28 +0200224 effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
Eric Laurent6d607012021-07-05 11:54:40 +0200225 if (status != NO_ERROR) {
226 ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
227 return spatializer;
228 }
229 ALOG_ASSERT(!descriptors.empty(),
230 "%s getDescriptors() returned no error but empty list", __func__);
231
Shunkai Yao5a251df2022-07-22 18:42:27 +0000232 // TODO: get supported spatialization modes from FX engine or descriptor
Eric Laurent6d607012021-07-05 11:54:40 +0200233 sp<EffectHalInterface> effect;
234 status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
235 AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000236 ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
237 effect ? effect->effectId() : 0);
Eric Laurent6d607012021-07-05 11:54:40 +0200238
239 if (status == NO_ERROR && effect != nullptr) {
240 spatializer = new Spatializer(descriptors[0], callback);
Eric Laurent2be8b292021-08-23 09:44:33 -0700241 if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
242 spatializer.clear();
Andy Hung0e3205d2022-08-29 14:14:58 -0700243 ALOGW("%s loadEngine error: %d effect Id %" PRId64,
244 __func__, status, effect ? effect->effectId() : 0);
245 } else {
246 spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
247 effect ? effect->effectId() : 0);
Eric Laurent2be8b292021-08-23 09:44:33 -0700248 }
Eric Laurent6d607012021-07-05 11:54:40 +0200249 }
250
251 return spatializer;
252}
253
Eric Laurent2be8b292021-08-23 09:44:33 -0700254Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
255 : mEngineDescriptor(engineDescriptor),
256 mPolicyCallback(callback) {
Eric Laurent6d607012021-07-05 11:54:40 +0200257 ALOGV("%s", __func__);
258}
259
Eric Laurent8a4259f2021-09-14 16:04:00 +0200260void Spatializer::onFirstRef() {
261 mLooper = new ALooper;
262 mLooper->setName("Spatializer-looper");
263 mLooper->start(
264 /*runOnCallingThread*/false,
265 /*canCallJava*/ false,
Andy Hung898a39f2022-11-07 20:09:20 -0800266 PRIORITY_URGENT_AUDIO);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200267
268 mHandler = new EngineCallbackHandler(this);
269 mLooper->registerHandler(mHandler);
270}
271
Eric Laurent6d607012021-07-05 11:54:40 +0200272Spatializer::~Spatializer() {
273 ALOGV("%s", __func__);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200274 if (mLooper != nullptr) {
275 mLooper->stop();
276 mLooper->unregisterHandler(mHandler->id());
277 }
278 mLooper.clear();
279 mHandler.clear();
Eric Laurent6d607012021-07-05 11:54:40 +0200280}
281
Andy Hung4442d042022-08-17 17:27:32 -0700282static std::string channelMaskVectorToString(
283 const std::vector<audio_channel_mask_t>& masks) {
284 std::stringstream ss;
285 for (const auto &mask : masks) {
286 if (ss.tellp() != 0) ss << "|";
287 ss << mask;
288 }
289 return ss.str();
290}
291
Eric Laurent2be8b292021-08-23 09:44:33 -0700292status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
293 ALOGV("%s", __func__);
294
295 std::vector<bool> supportsHeadTracking;
296 status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
297 &supportsHeadTracking);
298 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700299 ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700300 return status;
301 }
302 mSupportsHeadTracking = supportsHeadTracking[0];
303
Andy Hung119dbdb2022-05-11 19:20:13 -0700304 std::vector<media::SpatializationLevel> spatializationLevels;
305 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
306 &spatializationLevels);
Eric Laurent2be8b292021-08-23 09:44:33 -0700307 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700308 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700309 return status;
310 }
Andy Hung119dbdb2022-05-11 19:20:13 -0700311 bool noneLevelFound = false;
312 bool activeLevelFound = false;
313 for (const auto spatializationLevel : spatializationLevels) {
314 if (!aidl_utils::isValidEnum(spatializationLevel)) {
315 ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
316 continue;
317 }
318 if (spatializationLevel == media::SpatializationLevel::NONE) {
319 noneLevelFound = true;
320 } else {
321 activeLevelFound = true;
322 }
323 // we don't detect duplicates.
324 mLevels.emplace_back(spatializationLevel);
325 }
326 if (!noneLevelFound || !activeLevelFound) {
327 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
328 " and another valid level", __func__);
329 return BAD_VALUE;
330 }
331
332 std::vector<media::SpatializationMode> spatializationModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700333 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
Andy Hung119dbdb2022-05-11 19:20:13 -0700334 &spatializationModes);
Eric Laurent2be8b292021-08-23 09:44:33 -0700335 if (status != NO_ERROR) {
Andy Hung119dbdb2022-05-11 19:20:13 -0700336 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
Eric Laurent2be8b292021-08-23 09:44:33 -0700337 return status;
338 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000339
Andy Hung119dbdb2022-05-11 19:20:13 -0700340 for (const auto spatializationMode : spatializationModes) {
341 if (!aidl_utils::isValidEnum(spatializationMode)) {
342 ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
343 continue;
344 }
345 // we don't detect duplicates.
346 mSpatializationModes.emplace_back(spatializationMode);
347 }
348 if (mSpatializationModes.empty()) {
349 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
350 return BAD_VALUE;
351 }
352
353 std::vector<audio_channel_mask_t> channelMasks;
354 status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
355 &channelMasks);
356 if (status != NO_ERROR) {
357 ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
358 return status;
359 }
360 for (const auto channelMask : channelMasks) {
361 if (!audio_is_channel_mask_spatialized(channelMask)) {
362 ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
363 continue;
364 }
365 // we don't detect duplicates.
366 mChannelMasks.emplace_back(channelMask);
367 }
368 if (mChannelMasks.empty()) {
369 ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
370 return BAD_VALUE;
371 }
Andy Hunga461a002022-05-17 10:36:02 -0700372
373 // Currently we expose only RELATIVE_WORLD.
374 // This is a limitation of the head tracking library based on a UX choice.
375 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
376 if (mSupportsHeadTracking) {
377 mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
378 }
379 mediametrics::LogItem(mMetricsId)
380 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
Andy Hung4442d042022-08-17 17:27:32 -0700381 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
Andy Hunga461a002022-05-17 10:36:02 -0700382 .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
383 .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
384 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
385 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
386 .record();
Andy Hung119dbdb2022-05-11 19:20:13 -0700387 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700388}
389
Andy Hung757bc812022-09-13 18:53:06 -0700390/* static */
391void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
392 mediametrics::LogItem(kDefaultMetricsId)
393 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
394 .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
395 .set(AMEDIAMETRICS_PROP_LEVELS, "")
396 .set(AMEDIAMETRICS_PROP_MODES, "")
397 .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
398 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
399 .record();
400}
401
Eric Laurent2be8b292021-08-23 09:44:33 -0700402/** Gets the channel mask, sampling rate and format set for the spatializer input. */
403audio_config_base_t Spatializer::getAudioInConfig() const {
404 std::lock_guard lock(mLock);
405 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
406 // For now use highest supported channel count
Andy Hung0e3205d2022-08-29 14:14:58 -0700407 config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
Eric Laurent2be8b292021-08-23 09:44:33 -0700408 return config;
409}
410
Eric Laurent6d607012021-07-05 11:54:40 +0200411status_t Spatializer::registerCallback(
412 const sp<media::INativeSpatializerCallback>& callback) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700413 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200414 if (callback == nullptr) {
415 return BAD_VALUE;
416 }
417
Eric Laurentb57604f2022-08-31 16:07:50 +0200418 if (mSpatializerCallback != nullptr) {
419 if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
420 ALOGW("%s: Registering callback %p again",
421 __func__, mSpatializerCallback.get());
422 return NO_ERROR;
423 }
424 ALOGE("%s: Already one client registered with callback %p",
425 __func__, mSpatializerCallback.get());
426 return INVALID_OPERATION;
427 }
428
Eric Laurent6d607012021-07-05 11:54:40 +0200429 sp<IBinder> binder = IInterface::asBinder(callback);
430 status_t status = binder->linkToDeath(this);
431 if (status == NO_ERROR) {
432 mSpatializerCallback = callback;
433 }
434 ALOGV("%s status %d", __func__, status);
435 return status;
436}
437
438// IBinder::DeathRecipient
439void Spatializer::binderDied(__unused const wp<IBinder> &who) {
440 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700441 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200442 mLevel = SpatializationLevel::NONE;
443 mSpatializerCallback.clear();
444 }
445 ALOGV("%s", __func__);
446 mPolicyCallback->onCheckSpatializer();
447}
448
449// ISpatializer
450Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
451 ALOGV("%s", __func__);
452 if (levels == nullptr) {
453 return binderStatusFromStatusT(BAD_VALUE);
454 }
Andy Hunga461a002022-05-17 10:36:02 -0700455 // SpatializationLevel::NONE is already required from the effect or we don't load it.
Eric Laurent2be8b292021-08-23 09:44:33 -0700456 levels->insert(levels->end(), mLevels.begin(), mLevels.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200457 return Status::ok();
458}
459
Eric Laurent2be8b292021-08-23 09:44:33 -0700460Status Spatializer::setLevel(SpatializationLevel level) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000461 ALOGV("%s level %s", __func__, media::toString(level).c_str());
462 mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
Eric Laurent6d607012021-07-05 11:54:40 +0200463 if (level != SpatializationLevel::NONE
Eric Laurent2be8b292021-08-23 09:44:33 -0700464 && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
Eric Laurent6d607012021-07-05 11:54:40 +0200465 return binderStatusFromStatusT(BAD_VALUE);
466 }
467 sp<media::INativeSpatializerCallback> callback;
468 bool levelChanged = false;
469 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700470 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200471 levelChanged = mLevel != level;
472 mLevel = level;
473 callback = mSpatializerCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700474
475 if (levelChanged && mEngine != nullptr) {
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200476 checkEngineState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700477 }
Eric Laurent9249d342022-03-18 11:55:56 +0100478 checkSensorsState_l();
Eric Laurent6d607012021-07-05 11:54:40 +0200479 }
480
481 if (levelChanged) {
482 mPolicyCallback->onCheckSpatializer();
483 if (callback != nullptr) {
484 callback->onLevelChanged(level);
485 }
486 }
487 return Status::ok();
488}
489
Eric Laurent2be8b292021-08-23 09:44:33 -0700490Status Spatializer::getLevel(SpatializationLevel *level) {
Eric Laurent6d607012021-07-05 11:54:40 +0200491 if (level == nullptr) {
492 return binderStatusFromStatusT(BAD_VALUE);
493 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700494 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200495 *level = mLevel;
496 ALOGV("%s level %d", __func__, (int)*level);
497 return Status::ok();
498}
499
Eric Laurentc87402b2021-09-17 16:49:42 +0200500Status Spatializer::isHeadTrackingSupported(bool *supports) {
501 ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
502 if (supports == nullptr) {
503 return binderStatusFromStatusT(BAD_VALUE);
504 }
505 std::lock_guard lock(mLock);
506 *supports = mSupportsHeadTracking;
507 return Status::ok();
508}
509
Eric Laurent6d607012021-07-05 11:54:40 +0200510Status Spatializer::getSupportedHeadTrackingModes(
Eric Laurent2be8b292021-08-23 09:44:33 -0700511 std::vector<SpatializerHeadTrackingMode>* modes) {
512 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200513 ALOGV("%s", __func__);
514 if (modes == nullptr) {
515 return binderStatusFromStatusT(BAD_VALUE);
516 }
Andy Hunga461a002022-05-17 10:36:02 -0700517 modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
Eric Laurent6d607012021-07-05 11:54:40 +0200518 return Status::ok();
519}
520
Eric Laurent2be8b292021-08-23 09:44:33 -0700521Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000522 ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700523
524 if (!mSupportsHeadTracking) {
525 return binderStatusFromStatusT(INVALID_OPERATION);
526 }
Shunkai Yao5a251df2022-07-22 18:42:27 +0000527 mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700528 std::lock_guard lock(mLock);
529 switch (mode) {
530 case SpatializerHeadTrackingMode::OTHER:
531 return binderStatusFromStatusT(BAD_VALUE);
532 case SpatializerHeadTrackingMode::DISABLED:
533 mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
534 break;
535 case SpatializerHeadTrackingMode::RELATIVE_WORLD:
536 mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
537 break;
538 case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
539 mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
540 break;
541 }
542
Eric Laurent11094172022-04-05 18:27:42 +0200543 checkPoseController_l();
544 checkSensorsState_l();
Eric Laurent2be8b292021-08-23 09:44:33 -0700545
546 return Status::ok();
547}
548
549Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
Eric Laurent6d607012021-07-05 11:54:40 +0200550 if (mode == nullptr) {
551 return binderStatusFromStatusT(BAD_VALUE);
552 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700553 std::lock_guard lock(mLock);
554 *mode = mActualHeadTrackingMode;
Eric Laurent6d607012021-07-05 11:54:40 +0200555 ALOGV("%s mode %d", __func__, (int)*mode);
556 return Status::ok();
557}
558
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700559Status Spatializer::recenterHeadTracker() {
Eric Laurent780be4a2021-09-16 10:44:24 +0200560 if (!mSupportsHeadTracking) {
561 return binderStatusFromStatusT(INVALID_OPERATION);
562 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700563 std::lock_guard lock(mLock);
564 if (mPoseController != nullptr) {
565 mPoseController->recenter();
566 }
Eric Laurent6d607012021-07-05 11:54:40 +0200567 return Status::ok();
568}
569
570Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
Eric Laurent6d607012021-07-05 11:54:40 +0200571 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200572 if (!mSupportsHeadTracking) {
573 return binderStatusFromStatusT(INVALID_OPERATION);
574 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700575 std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
576 if (!maybePose.has_value()) {
577 ALOGW("Invalid screenToStage vector.");
578 return binderStatusFromStatusT(BAD_VALUE);
579 }
580 std::lock_guard lock(mLock);
581 if (mPoseController != nullptr) {
Shunkai Yao7de40382022-08-25 00:44:04 +0000582 mLocalLog.log("%s with screenToStage %s", __func__, toString<float>(screenToStage).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700583 mPoseController->setScreenToStagePose(maybePose.value());
584 }
Eric Laurent6d607012021-07-05 11:54:40 +0200585 return Status::ok();
586}
587
588Status Spatializer::release() {
589 ALOGV("%s", __func__);
590 bool levelChanged = false;
591 {
Eric Laurent2be8b292021-08-23 09:44:33 -0700592 std::lock_guard lock(mLock);
Eric Laurent6d607012021-07-05 11:54:40 +0200593 if (mSpatializerCallback == nullptr) {
594 return binderStatusFromStatusT(INVALID_OPERATION);
595 }
596
597 sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
598 binder->unlinkToDeath(this);
599 mSpatializerCallback.clear();
600
601 levelChanged = mLevel != SpatializationLevel::NONE;
602 mLevel = SpatializationLevel::NONE;
603 }
604
605 if (levelChanged) {
606 mPolicyCallback->onCheckSpatializer();
607 }
608 return Status::ok();
609}
610
Eric Laurent2be8b292021-08-23 09:44:33 -0700611Status Spatializer::setHeadSensor(int sensorHandle) {
612 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200613 if (!mSupportsHeadTracking) {
614 return binderStatusFromStatusT(INVALID_OPERATION);
615 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700616 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700617 if (mHeadSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000618 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700619 mHeadSensor = sensorHandle;
620 checkPoseController_l();
621 checkSensorsState_l();
622 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700623 return Status::ok();
624}
625
626Status Spatializer::setScreenSensor(int sensorHandle) {
627 ALOGV("%s sensorHandle %d", __func__, sensorHandle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200628 if (!mSupportsHeadTracking) {
629 return binderStatusFromStatusT(INVALID_OPERATION);
630 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700631 std::lock_guard lock(mLock);
Andy Hungba2a61a2022-05-20 12:00:28 -0700632 if (mScreenSensor != sensorHandle) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000633 mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
Andy Hungba2a61a2022-05-20 12:00:28 -0700634 mScreenSensor = sensorHandle;
635 // TODO: consider a new method setHeadAndScreenSensor()
636 // because we generally set both at the same time.
637 // This will avoid duplicated work and recentering.
638 checkSensorsState_l();
639 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700640 return Status::ok();
641}
642
643Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
644 ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
Eric Laurent780be4a2021-09-16 10:44:24 +0200645 if (!mSupportsHeadTracking) {
646 return binderStatusFromStatusT(INVALID_OPERATION);
647 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700648 std::lock_guard lock(mLock);
649 mDisplayOrientation = physicalToLogicalAngle;
Shunkai Yao5a251df2022-07-22 18:42:27 +0000650 mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700651 if (mPoseController != nullptr) {
652 mPoseController->setDisplayOrientation(mDisplayOrientation);
653 }
Eric Laurent16ddaf42021-09-17 15:00:35 +0200654 if (mEngine != nullptr) {
655 setEffectParameter_l(
656 SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{physicalToLogicalAngle});
657 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700658 return Status::ok();
659}
660
661Status Spatializer::setHingeAngle(float hingeAngle) {
662 std::lock_guard lock(mLock);
663 ALOGV("%s hingeAngle %f", __func__, hingeAngle);
664 if (mEngine != nullptr) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000665 mLocalLog.log("%s with %f", __func__, hingeAngle);
Eric Laurent2be8b292021-08-23 09:44:33 -0700666 setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{hingeAngle});
667 }
668 return Status::ok();
669}
670
671Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
672 ALOGV("%s", __func__);
673 if (modes == nullptr) {
674 return binderStatusFromStatusT(BAD_VALUE);
675 }
676 *modes = mSpatializationModes;
677 return Status::ok();
678}
679
Eric Laurent67816e32021-09-16 15:18:40 +0200680Status Spatializer::registerHeadTrackingCallback(
681 const sp<media::ISpatializerHeadTrackingCallback>& callback) {
682 ALOGV("%s callback %p", __func__, callback.get());
683 std::lock_guard lock(mLock);
684 if (!mSupportsHeadTracking) {
685 return binderStatusFromStatusT(INVALID_OPERATION);
686 }
687 mHeadTrackingCallback = callback;
688 return Status::ok();
689}
690
Eric Laurentc87402b2021-09-17 16:49:42 +0200691Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
692 ALOGV("%s key %d", __func__, key);
693 std::lock_guard lock(mLock);
694 status_t status = INVALID_OPERATION;
695 if (mEngine != nullptr) {
696 status = setEffectParameter_l(key, value);
697 }
698 return binderStatusFromStatusT(status);
699}
700
701Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
Greg Kaiserf7249f82021-09-21 07:10:12 -0700702 ALOGV("%s key %d value size %d", __func__, key,
703 (value != nullptr ? (int)value->size() : -1));
Eric Laurentc87402b2021-09-17 16:49:42 +0200704 if (value == nullptr) {
George Burgess IV22386222021-09-22 12:09:31 -0700705 return binderStatusFromStatusT(BAD_VALUE);
Eric Laurentc87402b2021-09-17 16:49:42 +0200706 }
707 std::lock_guard lock(mLock);
708 status_t status = INVALID_OPERATION;
709 if (mEngine != nullptr) {
710 ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
711 status = getEffectParameter_l(key, value);
712 }
713 return binderStatusFromStatusT(status);
714}
715
716Status Spatializer::getOutput(int *output) {
717 ALOGV("%s", __func__);
718 if (output == nullptr) {
719 binderStatusFromStatusT(BAD_VALUE);
720 }
721 std::lock_guard lock(mLock);
722 *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
723 ALOGV("%s got output %d", __func__, *output);
724 return Status::ok();
725}
726
Eric Laurent2be8b292021-08-23 09:44:33 -0700727// SpatializerPoseController::Listener
728void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
729 ALOGV("%s", __func__);
Eric Laurent780be4a2021-09-16 10:44:24 +0200730 LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
731 "onHeadToStagePose() called with no head tracking support!");
732
Eric Laurent2be8b292021-08-23 09:44:33 -0700733 auto vec = headToStage.toVector();
Eric Laurent8a4259f2021-09-14 16:04:00 +0200734 LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
735 "%s invalid head to stage vector size %zu", __func__, vec.size());
Eric Laurent8a4259f2021-09-14 16:04:00 +0200736 sp<AMessage> msg =
737 new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
738 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
739 msg->setFloat(sHeadPoseKeys[i], vec[i]);
740 }
741 msg->post();
742}
743
Eric Laurent3c48ad92022-10-21 11:28:32 +0200744void Spatializer::resetEngineHeadPose_l() {
745 ALOGV("%s mEngine %p", __func__, mEngine.get());
746 if (mEngine == nullptr) {
747 return;
748 }
749 const std::vector<float> headToStage(6, 0.0);
750 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
751 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
752 std::vector<SpatializerHeadTrackingMode>{SpatializerHeadTrackingMode::DISABLED});
753}
754
Eric Laurent8a4259f2021-09-14 16:04:00 +0200755void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
756 ALOGV("%s", __func__);
Eric Laurent67816e32021-09-16 15:18:40 +0200757 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700758 {
759 std::lock_guard lock(mLock);
Eric Laurent67816e32021-09-16 15:18:40 +0200760 callback = mHeadTrackingCallback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700761 if (mEngine != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200762 setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
Shunkai Yao7de40382022-08-25 00:44:04 +0000763 mPoseRecorder.record(headToStage);
764 mPoseDurableRecorder.record(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700765 }
766 }
767
768 if (callback != nullptr) {
Eric Laurent8a4259f2021-09-14 16:04:00 +0200769 callback->onHeadToSoundStagePoseUpdated(headToStage);
Eric Laurent2be8b292021-08-23 09:44:33 -0700770 }
771}
772
773void Spatializer::onActualModeChange(HeadTrackingMode mode) {
Shunkai Yao51379452022-08-30 03:14:50 +0000774 std::string modeStr = media::toString(mode);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000775 ALOGV("%s(%s)", __func__, modeStr.c_str());
Shunkai Yao51379452022-08-30 03:14:50 +0000776 sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200777 msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
778 msg->post();
779}
780
781void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
782 ALOGV("%s(%d)", __func__, (int) mode);
Eric Laurent67816e32021-09-16 15:18:40 +0200783 sp<media::ISpatializerHeadTrackingCallback> callback;
Eric Laurent2be8b292021-08-23 09:44:33 -0700784 SpatializerHeadTrackingMode spatializerMode;
785 {
786 std::lock_guard lock(mLock);
787 if (!mSupportsHeadTracking) {
788 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
789 } else {
790 switch (mode) {
791 case HeadTrackingMode::STATIC:
792 spatializerMode = SpatializerHeadTrackingMode::DISABLED;
793 break;
794 case HeadTrackingMode::WORLD_RELATIVE:
795 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
796 break;
797 case HeadTrackingMode::SCREEN_RELATIVE:
798 spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
799 break;
800 default:
801 LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
802 }
803 }
804 mActualHeadTrackingMode = spatializerMode;
Eric Laurente51f80e2022-04-14 10:20:38 +0200805 if (mEngine != nullptr) {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200806 if (spatializerMode == SpatializerHeadTrackingMode::DISABLED) {
807 resetEngineHeadPose_l();
808 } else {
809 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
810 std::vector<SpatializerHeadTrackingMode>{spatializerMode});
811 }
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200812 }
Eric Laurent67816e32021-09-16 15:18:40 +0200813 callback = mHeadTrackingCallback;
Shunkai Yao51379452022-08-30 03:14:50 +0000814 mLocalLog.log("%s: %s, spatializerMode %s", __func__, media::toString(mode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +0000815 media::toString(spatializerMode).c_str());
Eric Laurent2be8b292021-08-23 09:44:33 -0700816 }
Eric Laurente51f80e2022-04-14 10:20:38 +0200817 if (callback != nullptr) {
Eric Laurent2be8b292021-08-23 09:44:33 -0700818 callback->onHeadTrackingModeChanged(spatializerMode);
819 }
820}
821
Eric Laurent15903592022-02-24 20:44:36 +0100822status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
Eric Laurent4a872862021-10-11 17:06:47 +0200823 bool outputChanged = false;
824 sp<media::INativeSpatializerCallback> callback;
825
Eric Laurent2be8b292021-08-23 09:44:33 -0700826 {
827 std::lock_guard lock(mLock);
828 ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000829 mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
830 numActiveTracks, (int)mOutput);
Eric Laurent2be8b292021-08-23 09:44:33 -0700831 if (mOutput != AUDIO_IO_HANDLE_NONE) {
832 LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
833 // remove FX instance
834 mEngine->setEnabled(false);
835 mEngine.clear();
Eric Laurent15903592022-02-24 20:44:36 +0100836 mPoseController.reset();
Eric Laurentb387fb42022-05-03 18:19:35 +0200837 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent2be8b292021-08-23 09:44:33 -0700838 }
Eric Laurentb387fb42022-05-03 18:19:35 +0200839
Eric Laurent2be8b292021-08-23 09:44:33 -0700840 // create FX instance on output
841 AttributionSourceState attributionSource = AttributionSourceState();
842 mEngine = new AudioEffect(attributionSource);
843 mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
844 this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
845 false /* probe */, true /* notifyFramesProcessed */);
846 status_t status = mEngine->initCheck();
847 ALOGV("%s mEngine create status %d", __func__, (int)status);
848 if (status != NO_ERROR) {
849 return status;
850 }
851
Eric Laurent4a872862021-10-11 17:06:47 +0200852 outputChanged = mOutput != output;
Eric Laurent2be8b292021-08-23 09:44:33 -0700853 mOutput = output;
Eric Laurent11094172022-04-05 18:27:42 +0200854 mNumActiveTracks = numActiveTracks;
Eric Laurentb387fb42022-05-03 18:19:35 +0200855 AudioSystem::addSupportedLatencyModesCallback(this);
856
857 std::vector<audio_latency_mode_t> latencyModes;
858 status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
859 if (status == OK) {
860 mSupportedLatencyModes = latencyModes;
861 }
Eric Laurent2be8b292021-08-23 09:44:33 -0700862
Eric Laurent11094172022-04-05 18:27:42 +0200863 checkEngineState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200864 if (mSupportsHeadTracking) {
Eric Laurent11094172022-04-05 18:27:42 +0200865 checkPoseController_l();
Eric Laurent9249d342022-03-18 11:55:56 +0100866 checkSensorsState_l();
Eric Laurent780be4a2021-09-16 10:44:24 +0200867 }
Eric Laurent4a872862021-10-11 17:06:47 +0200868 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200869 }
Eric Laurent4a872862021-10-11 17:06:47 +0200870
871 if (outputChanged && callback != nullptr) {
872 callback->onOutputChanged(output);
873 }
874
Eric Laurent6d607012021-07-05 11:54:40 +0200875 return NO_ERROR;
876}
877
878audio_io_handle_t Spatializer::detachOutput() {
Eric Laurent2be8b292021-08-23 09:44:33 -0700879 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
Eric Laurent4a872862021-10-11 17:06:47 +0200880 sp<media::INativeSpatializerCallback> callback;
881
882 {
883 std::lock_guard lock(mLock);
Shunkai Yao5a251df2022-07-22 18:42:27 +0000884 mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
Eric Laurent4a872862021-10-11 17:06:47 +0200885 ALOGV("%s mOutput %d", __func__, (int)mOutput);
886 if (mOutput == AUDIO_IO_HANDLE_NONE) {
887 return output;
888 }
889 // remove FX instance
890 mEngine->setEnabled(false);
891 mEngine.clear();
Eric Laurentb387fb42022-05-03 18:19:35 +0200892 AudioSystem::removeSupportedLatencyModesCallback(this);
Eric Laurent4a872862021-10-11 17:06:47 +0200893 output = mOutput;
894 mOutput = AUDIO_IO_HANDLE_NONE;
895 mPoseController.reset();
Eric Laurent4a872862021-10-11 17:06:47 +0200896 callback = mSpatializerCallback;
Eric Laurent6d607012021-07-05 11:54:40 +0200897 }
Eric Laurent4a872862021-10-11 17:06:47 +0200898
899 if (callback != nullptr) {
900 callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
901 }
Eric Laurent6d607012021-07-05 11:54:40 +0200902 return output;
903}
904
Eric Laurentb387fb42022-05-03 18:19:35 +0200905void Spatializer::onSupportedLatencyModesChanged(
906 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200907 ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
908 sp<AMessage> msg =
909 new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
910 msg->setObject(EngineCallbackHandler::kLatencyModesKey,
911 sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
912 msg->post();
913}
914
915void Spatializer::onSupportedLatencyModesChangedMsg(
916 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
Eric Laurentb387fb42022-05-03 18:19:35 +0200917 std::lock_guard lock(mLock);
Eric Laurentdf2ece42022-07-20 13:49:47 +0200918 ALOGV("%s output %d mOutput %d num modes %zu",
919 __func__, (int)output, (int)mOutput, modes.size());
Eric Laurentb387fb42022-05-03 18:19:35 +0200920 if (output == mOutput) {
Eric Laurentdf2ece42022-07-20 13:49:47 +0200921 mSupportedLatencyModes = std::move(modes);
Eric Laurentb387fb42022-05-03 18:19:35 +0200922 checkSensorsState_l();
923 }
924}
925
Eric Laurent15903592022-02-24 20:44:36 +0100926void Spatializer::updateActiveTracks(size_t numActiveTracks) {
927 std::lock_guard lock(mLock);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200928 if (mNumActiveTracks != numActiveTracks) {
Shunkai Yao5a251df2022-07-22 18:42:27 +0000929 mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200930 mNumActiveTracks = numActiveTracks;
931 checkEngineState_l();
932 checkSensorsState_l();
933 }
Eric Laurent15903592022-02-24 20:44:36 +0100934}
935
Eric Laurent9249d342022-03-18 11:55:56 +0100936void Spatializer::checkSensorsState_l() {
Eric Laurentb387fb42022-05-03 18:19:35 +0200937 audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
Andy Hungc0896c72022-10-21 17:30:30 -0700938 const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
939 const bool supportsLowLatencyMode = supportsSetLatencyMode && std::find(
940 mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
941 AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
Eric Laurent3c48ad92022-10-21 11:28:32 +0200942 if (mSupportsHeadTracking) {
943 if (mPoseController != nullptr) {
Andy Hungc0896c72022-10-21 17:30:30 -0700944 // TODO(b/253297301, b/255433067) reenable low latency condition check
945 // for Head Tracking after Bluetooth HAL supports it correctly.
946 if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
Eric Laurent3c48ad92022-10-21 11:28:32 +0200947 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
948 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
949 if (mEngine != nullptr) {
950 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
951 std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
952 }
953 mPoseController->setHeadSensor(mHeadSensor);
954 mPoseController->setScreenSensor(mScreenSensor);
Andy Hungc0896c72022-10-21 17:30:30 -0700955 if (supportsLowLatencyMode) requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
Eric Laurent3c48ad92022-10-21 11:28:32 +0200956 } else {
957 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
958 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
959 resetEngineHeadPose_l();
960 }
Eric Laurent15903592022-02-24 20:44:36 +0100961 } else {
Eric Laurent3c48ad92022-10-21 11:28:32 +0200962 resetEngineHeadPose_l();
Eric Laurent15903592022-02-24 20:44:36 +0100963 }
964 }
Andy Hungc0896c72022-10-21 17:30:30 -0700965 if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
Andy Hung5d8618d2022-11-17 17:21:45 -0800966 const status_t status =
967 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
968 ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
969 __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
Eric Laurentb387fb42022-05-03 18:19:35 +0200970 }
Eric Laurent15903592022-02-24 20:44:36 +0100971}
972
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200973void Spatializer::checkEngineState_l() {
974 if (mEngine != nullptr) {
975 if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
976 mEngine->setEnabled(true);
977 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
978 std::vector<SpatializationLevel>{mLevel});
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200979 } else {
980 setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
981 std::vector<SpatializationLevel>{SpatializationLevel::NONE});
982 mEngine->setEnabled(false);
983 }
984 }
985}
986
Eric Laurent11094172022-04-05 18:27:42 +0200987void Spatializer::checkPoseController_l() {
988 bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
989 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
990
991 if (isControllerNeeded && mPoseController == nullptr) {
992 mPoseController = std::make_shared<SpatializerPoseController>(
993 static_cast<SpatializerPoseController::Listener*>(this),
Eric Laurente51f80e2022-04-14 10:20:38 +0200994 10ms, std::nullopt);
Eric Laurent11094172022-04-05 18:27:42 +0200995 LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
996 "%s could not allocate pose controller", __func__);
997 mPoseController->setDisplayOrientation(mDisplayOrientation);
998 } else if (!isControllerNeeded && mPoseController != nullptr) {
999 mPoseController.reset();
Eric Laurent3c48ad92022-10-21 11:28:32 +02001000 resetEngineHeadPose_l();
Eric Laurent11094172022-04-05 18:27:42 +02001001 }
1002 if (mPoseController != nullptr) {
1003 mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
1004 }
1005}
1006
Eric Laurent2be8b292021-08-23 09:44:33 -07001007void Spatializer::calculateHeadPose() {
1008 ALOGV("%s", __func__);
1009 std::lock_guard lock(mLock);
1010 if (mPoseController != nullptr) {
1011 mPoseController->calculateAsync();
1012 }
1013}
Eric Laurent6d607012021-07-05 11:54:40 +02001014
Eric Laurent2be8b292021-08-23 09:44:33 -07001015void Spatializer::engineCallback(int32_t event, void *user, void *info) {
Eric Laurent6d607012021-07-05 11:54:40 +02001016 if (user == nullptr) {
1017 return;
1018 }
Eric Laurent2be8b292021-08-23 09:44:33 -07001019 Spatializer* const me = reinterpret_cast<Spatializer *>(user);
Eric Laurent6d607012021-07-05 11:54:40 +02001020 switch (event) {
1021 case AudioEffect::EVENT_FRAMES_PROCESSED: {
Eric Laurent2be8b292021-08-23 09:44:33 -07001022 int frames = info == nullptr ? 0 : *(int*)info;
Eric Laurent9249d342022-03-18 11:55:56 +01001023 ALOGV("%s frames processed %d for me %p", __func__, frames, me);
Eric Laurent8a4259f2021-09-14 16:04:00 +02001024 me->postFramesProcessedMsg(frames);
Eric Laurent2be8b292021-08-23 09:44:33 -07001025 } break;
Eric Laurent6d607012021-07-05 11:54:40 +02001026 default:
Eric Laurent9249d342022-03-18 11:55:56 +01001027 ALOGV("%s event %d", __func__, event);
Eric Laurent6d607012021-07-05 11:54:40 +02001028 break;
1029 }
1030}
1031
Eric Laurent8a4259f2021-09-14 16:04:00 +02001032void Spatializer::postFramesProcessedMsg(int frames) {
1033 sp<AMessage> msg =
1034 new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
1035 msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
1036 msg->post();
1037}
1038
Shunkai Yao5a251df2022-07-22 18:42:27 +00001039std::string Spatializer::toString(unsigned level) const {
1040 std::string prefixSpace;
1041 prefixSpace.append(level, ' ');
1042 std::string ss = prefixSpace + "Spatializer:\n";
1043 bool needUnlock = false;
1044
1045 prefixSpace += ' ';
1046 if (!mLock.try_lock()) {
1047 // dumpsys even try_lock failed, information dump can be useful although may not accurate
1048 ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1049 } else {
1050 needUnlock = true;
1051 }
1052
1053 // Spatializer class information.
1054 // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1055 ss.append(prefixSpace).append("Supported levels: [");
1056 for (auto& level : mLevels) {
1057 base::StringAppendF(&ss, " %s", media::toString(level).c_str());
1058 }
1059 base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
1060
1061 base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1062 for (auto& mode : mHeadTrackingModes) {
1063 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1064 }
1065 base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
Shunkai Yao51379452022-08-30 03:14:50 +00001066 media::toString(mDesiredHeadTrackingMode).c_str(),
Shunkai Yao5a251df2022-07-22 18:42:27 +00001067 media::toString(mActualHeadTrackingMode).c_str());
1068
1069 base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1070 for (auto& mode : mSpatializationModes) {
1071 base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1072 }
1073 ss += "]\n";
1074
1075 base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1076 for (auto& mask : mChannelMasks) {
1077 base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1078 }
1079 base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1080 mSupportsHeadTracking ? "true" : "false");
1081 // 2. Settings (Output, tracks)
1082 base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1083 base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1084
1085 // 3. Sensors, Effect information.
1086 base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1087 base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1088 base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1089 base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1090 mDisplayOrientation);
1091
1092 ss.append(prefixSpace + "CommandLog:\n");
1093 ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001094
1095 // PostController dump.
1096 if (mPoseController != nullptr) {
1097 ss += mPoseController->toString(level + 1);
Shunkai Yao7de40382022-08-25 00:44:04 +00001098 ss.append(prefixSpace +
1099 "Sensor data format - [rx, ry, rz, vx, vy, vz] (units-degree, "
1100 "r-transform, v-angular velocity, x-pitch, y-roll, z-yaw):\n");
Shunkai Yao51379452022-08-30 03:14:50 +00001101 ss.append(prefixSpace + " PerMinuteHistory:\n");
Shunkai Yao7de40382022-08-25 00:44:04 +00001102 ss += mPoseDurableRecorder.toString(level + 1);
Shunkai Yao51379452022-08-30 03:14:50 +00001103 ss.append(prefixSpace + " PerSecondHistory:\n");
Shunkai Yao7de40382022-08-25 00:44:04 +00001104 ss += mPoseRecorder.toString(level + 1);
Shunkai Yao5a251df2022-07-22 18:42:27 +00001105 } else {
1106 ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1107 }
1108
1109 if (needUnlock) {
1110 mLock.unlock();
1111 }
1112 return ss;
1113}
1114
Eric Laurent6d607012021-07-05 11:54:40 +02001115} // namespace android