• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
18 #include <string>
19 #define LOG_TAG "Spatializer"
20 //#define LOG_NDEBUG 0
21 #include <utils/Log.h>
22 
23 #include <algorithm>
24 #include <inttypes.h>
25 #include <limits.h>
26 #include <stdint.h>
27 #include <sys/types.h>
28 
29 #include <android/content/AttributionSourceState.h>
30 #include <audio_utils/fixedfft.h>
31 #include <cutils/bitops.h>
32 #include <hardware/sensors.h>
33 #include <media/audiohal/EffectsFactoryHalInterface.h>
34 #include <media/stagefright/foundation/AHandler.h>
35 #include <media/stagefright/foundation/AMessage.h>
36 #include <media/MediaMetricsItem.h>
37 #include <media/QuaternionUtil.h>
38 #include <media/ShmemCompat.h>
39 #include <mediautils/SchedulingPolicyService.h>
40 #include <mediautils/ServiceUtilities.h>
41 #include <utils/Thread.h>
42 
43 #include "Spatializer.h"
44 
45 namespace android {
46 
47 using aidl_utils::statusTFromBinderStatus;
48 using aidl_utils::binderStatusFromStatusT;
49 using android::content::AttributionSourceState;
50 using binder::Status;
51 using media::HeadTrackingMode;
52 using media::Pose3f;
53 using media::SpatializationLevel;
54 using media::SpatializationMode;
55 using media::SpatializerHeadTrackingMode;
56 using media::SensorPoseProvider;
57 
58 using namespace std::chrono_literals;
59 
60 #define VALUE_OR_RETURN_BINDER_STATUS(x) \
61     ({ auto _tmp = (x); \
62        if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
63        std::move(_tmp.value()); })
64 
getMaxChannelMask(const std::vector<audio_channel_mask_t> & masks,size_t channelLimit=SIZE_MAX)65 static audio_channel_mask_t getMaxChannelMask(
66         const std::vector<audio_channel_mask_t>& masks, size_t channelLimit = SIZE_MAX) {
67     uint32_t maxCount = 0;
68     audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
69     for (auto mask : masks) {
70         const size_t count = audio_channel_count_from_out_mask(mask);
71         if (count > channelLimit) continue;  // ignore masks greater than channelLimit
72         if (count > maxCount) {
73             maxMask = mask;
74             maxCount = count;
75         }
76     }
77     return maxMask;
78 }
79 
recordFromTranslationRotationVector(const std::vector<float> & trVector)80 static std::vector<float> recordFromTranslationRotationVector(
81         const std::vector<float>& trVector) {
82     auto headToStageOpt = Pose3f::fromVector(trVector);
83     if (!headToStageOpt) return {};
84 
85     const auto stageToHead = headToStageOpt.value().inverse();
86     const auto stageToHeadTranslation = stageToHead.translation();
87     constexpr float RAD_TO_DEGREE = 180.f / M_PI;
88     std::vector<float> record{
89         stageToHeadTranslation[0], stageToHeadTranslation[1], stageToHeadTranslation[2],
90         0.f, 0.f, 0.f};
91     media::quaternionToAngles(stageToHead.rotation(), &record[3], &record[4], &record[5]);
92     record[3] *= RAD_TO_DEGREE;
93     record[4] *= RAD_TO_DEGREE;
94     record[5] *= RAD_TO_DEGREE;
95     return record;
96 }
97 
98 template<typename T>
safe_clamp(const T & value,const T & low,const T & high)99 static constexpr const T& safe_clamp(const T& value, const T& low, const T& high) {
100     if constexpr (std::is_floating_point_v<T>) {
101         return value != value /* constexpr isnan */
102                 ? low : std::clamp(value, low, high);
103     } else /* constexpr */ {
104         return std::clamp(value, low, high);
105     }
106 }
107 
108 // ---------------------------------------------------------------------------
109 
110 class Spatializer::EngineCallbackHandler : public AHandler {
111 public:
EngineCallbackHandler(wp<Spatializer> spatializer)112     EngineCallbackHandler(wp<Spatializer> spatializer)
113             : mSpatializer(spatializer) {
114     }
115 
116     enum {
117         // Device state callbacks
118         kWhatOnFramesProcessed,    // AudioEffect::EVENT_FRAMES_PROCESSED
119         kWhatOnHeadToStagePose,    // SpatializerPoseController::Listener::onHeadToStagePose
120         kWhatOnActualModeChange,   // SpatializerPoseController::Listener::onActualModeChange
121         kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
122     };
123     static constexpr const char *kNumFramesKey = "numFrames";
124     static constexpr const char *kModeKey = "mode";
125     static constexpr const char *kTranslation0Key = "translation0";
126     static constexpr const char *kTranslation1Key = "translation1";
127     static constexpr const char *kTranslation2Key = "translation2";
128     static constexpr const char *kRotation0Key = "rotation0";
129     static constexpr const char *kRotation1Key = "rotation1";
130     static constexpr const char *kRotation2Key = "rotation2";
131     static constexpr const char *kLatencyModesKey = "latencyModes";
132 
133     class LatencyModes : public RefBase {
134     public:
LatencyModes(audio_io_handle_t output,const std::vector<audio_latency_mode_t> & latencyModes)135         LatencyModes(audio_io_handle_t output,
136                 const std::vector<audio_latency_mode_t>& latencyModes)
137             : mOutput(output), mLatencyModes(latencyModes) {}
138         ~LatencyModes() = default;
139 
140         audio_io_handle_t mOutput;
141         std::vector<audio_latency_mode_t> mLatencyModes;
142     };
143 
onMessageReceived(const sp<AMessage> & msg)144     void onMessageReceived(const sp<AMessage> &msg) override {
145         // No ALooper method to get the tid so update
146         // Spatializer priority on the first message received.
147         std::call_once(mPrioritySetFlag, [](){
148             const pid_t pid = getpid();
149             const pid_t tid = gettid();
150             (void)requestSpatializerPriority(pid, tid);
151         });
152 
153         sp<Spatializer> spatializer = mSpatializer.promote();
154         if (spatializer == nullptr) {
155             ALOGW("%s: Cannot promote spatializer", __func__);
156             return;
157         }
158         switch (msg->what()) {
159             case kWhatOnFramesProcessed: {
160                 int numFrames;
161                 if (!msg->findInt32(kNumFramesKey, &numFrames)) {
162                     ALOGE("%s: Cannot find num frames!", __func__);
163                     return;
164                 }
165                 if (numFrames > 0) {
166                     spatializer->calculateHeadPose();
167                 }
168                 } break;
169             case kWhatOnHeadToStagePose: {
170                 std::vector<float> headToStage(sHeadPoseKeys.size());
171                 for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
172                     if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
173                         ALOGE("%s: Cannot find kTranslation0Key!", __func__);
174                         return;
175                     }
176                 }
177                 spatializer->onHeadToStagePoseMsg(headToStage);
178                 } break;
179             case kWhatOnActualModeChange: {
180                 int mode;
181                 if (!msg->findInt32(kModeKey, &mode)) {
182                     ALOGE("%s: Cannot find actualMode!", __func__);
183                     return;
184                 }
185                 spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
186                 } break;
187 
188             case kWhatOnLatencyModesChanged: {
189                 sp<RefBase> object;
190                 if (!msg->findObject(kLatencyModesKey, &object)) {
191                     ALOGE("%s: Cannot find latency modes!", __func__);
192                     return;
193                 }
194                 sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
195                 spatializer->onSupportedLatencyModesChangedMsg(
196                     latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
197                 } break;
198 
199             default:
200                 LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
201         }
202     }
203 private:
204     wp<Spatializer> mSpatializer;
205     std::once_flag mPrioritySetFlag;
206 };
207 
208 const std::vector<const char *> Spatializer::sHeadPoseKeys = {
209     Spatializer::EngineCallbackHandler::kTranslation0Key,
210     Spatializer::EngineCallbackHandler::kTranslation1Key,
211     Spatializer::EngineCallbackHandler::kTranslation2Key,
212     Spatializer::EngineCallbackHandler::kRotation0Key,
213     Spatializer::EngineCallbackHandler::kRotation1Key,
214     Spatializer::EngineCallbackHandler::kRotation2Key,
215 };
216 
217 // ---------------------------------------------------------------------------
create(SpatializerPolicyCallback * callback)218 sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
219     sp<Spatializer> spatializer;
220 
221     sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
222     if (effectsFactoryHal == nullptr) {
223         ALOGW("%s failed to create effect factory interface", __func__);
224         return spatializer;
225     }
226 
227     std::vector<effect_descriptor_t> descriptors;
228     status_t status =
229             effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
230     if (status != NO_ERROR) {
231         ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
232         return spatializer;
233     }
234     ALOG_ASSERT(!descriptors.empty(),
235             "%s getDescriptors() returned no error but empty list", __func__);
236 
237     // TODO: get supported spatialization modes from FX engine or descriptor
238     sp<EffectHalInterface> effect;
239     status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
240             AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
241     ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status,
242           effect ? effect->effectId() : 0);
243 
244     if (status == NO_ERROR && effect != nullptr) {
245         spatializer = new Spatializer(descriptors[0], callback);
246         if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
247             spatializer.clear();
248             ALOGW("%s loadEngine error: %d  effect Id %" PRId64,
249                     __func__, status, effect ? effect->effectId() : 0);
250         } else {
251             spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__,
252                                        effect ? effect->effectId() : 0);
253         }
254     }
255 
256     return spatializer;
257 }
258 
Spatializer(effect_descriptor_t engineDescriptor,SpatializerPolicyCallback * callback)259 Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
260     : mEngineDescriptor(engineDescriptor),
261       mPolicyCallback(callback) {
262     ALOGV("%s", __func__);
263     setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
264 }
265 
onFirstRef()266 void Spatializer::onFirstRef() {
267     mLooper = new ALooper;
268     mLooper->setName("Spatializer-looper");
269     mLooper->start(
270             /*runOnCallingThread*/false,
271             /*canCallJava*/       false,
272             PRIORITY_URGENT_AUDIO);
273 
274     mHandler = new EngineCallbackHandler(this);
275     mLooper->registerHandler(mHandler);
276 }
277 
~Spatializer()278 Spatializer::~Spatializer() {
279     ALOGV("%s", __func__);
280     if (mLooper != nullptr) {
281         mLooper->stop();
282         mLooper->unregisterHandler(mHandler->id());
283     }
284     mLooper.clear();
285     mHandler.clear();
286 }
287 
channelMaskVectorToString(const std::vector<audio_channel_mask_t> & masks)288 static std::string channelMaskVectorToString(
289         const std::vector<audio_channel_mask_t>& masks) {
290     std::stringstream ss;
291     for (const auto &mask : masks) {
292         if (ss.tellp() != 0) ss << "|";
293         ss << mask;
294     }
295     return ss.str();
296 }
297 
loadEngineConfiguration(sp<EffectHalInterface> effect)298 status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
299     ALOGV("%s", __func__);
300 
301     std::vector<bool> supportsHeadTracking;
302     status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
303                                          &supportsHeadTracking);
304     if (status != NO_ERROR) {
305         ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
306         return status;
307     }
308     mSupportsHeadTracking = supportsHeadTracking[0];
309 
310     std::vector<media::SpatializationLevel> spatializationLevels;
311     status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
312             &spatializationLevels);
313     if (status != NO_ERROR) {
314         ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
315         return status;
316     }
317     bool noneLevelFound = false;
318     bool activeLevelFound = false;
319     for (const auto spatializationLevel : spatializationLevels) {
320         if (!aidl_utils::isValidEnum(spatializationLevel)) {
321             ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
322             continue;
323         }
324         if (spatializationLevel == media::SpatializationLevel::NONE) {
325             noneLevelFound = true;
326         } else {
327             activeLevelFound = true;
328         }
329         // we don't detect duplicates.
330         mLevels.emplace_back(spatializationLevel);
331     }
332     if (!noneLevelFound || !activeLevelFound) {
333         ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
334                 " and another valid level",  __func__);
335         return BAD_VALUE;
336     }
337 
338     std::vector<media::SpatializationMode> spatializationModes;
339     status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
340             &spatializationModes);
341     if (status != NO_ERROR) {
342         ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
343         return status;
344     }
345 
346     for (const auto spatializationMode : spatializationModes) {
347         if (!aidl_utils::isValidEnum(spatializationMode)) {
348             ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
349             continue;
350         }
351         // we don't detect duplicates.
352         mSpatializationModes.emplace_back(spatializationMode);
353     }
354     if (mSpatializationModes.empty()) {
355         ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
356         return BAD_VALUE;
357     }
358 
359     std::vector<audio_channel_mask_t> channelMasks;
360     status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
361                                  &channelMasks);
362     if (status != NO_ERROR) {
363         ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
364         return status;
365     }
366     for (const auto channelMask : channelMasks) {
367         if (!audio_is_channel_mask_spatialized(channelMask)) {
368             ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
369             continue;
370         }
371         // we don't detect duplicates.
372         mChannelMasks.emplace_back(channelMask);
373     }
374     if (mChannelMasks.empty()) {
375         ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
376         return BAD_VALUE;
377     }
378 
379     // Currently we expose only RELATIVE_WORLD.
380     // This is a limitation of the head tracking library based on a UX choice.
381     mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::DISABLED);
382     if (mSupportsHeadTracking) {
383         mHeadTrackingModes.push_back(SpatializerHeadTrackingMode::RELATIVE_WORLD);
384     }
385     mediametrics::LogItem(mMetricsId)
386         .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
387         .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
388         .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
389         .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
390         .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
391         .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
392         .record();
393     return NO_ERROR;
394 }
395 
396 /* static */
sendEmptyCreateSpatializerMetricWithStatus(status_t status)397 void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
398     mediametrics::LogItem(kDefaultMetricsId)
399         .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
400         .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
401         .set(AMEDIAMETRICS_PROP_LEVELS, "")
402         .set(AMEDIAMETRICS_PROP_MODES, "")
403         .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
404         .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
405         .record();
406 }
407 
408 /** Gets the channel mask, sampling rate and format set for the spatializer input. */
getAudioInConfig() const409 audio_config_base_t Spatializer::getAudioInConfig() const {
410     std::lock_guard lock(mLock);
411     audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
412     // For now use highest supported channel count
413     config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
414     return config;
415 }
416 
registerCallback(const sp<media::INativeSpatializerCallback> & callback)417 status_t Spatializer::registerCallback(
418         const sp<media::INativeSpatializerCallback>& callback) {
419     std::lock_guard lock(mLock);
420     if (callback == nullptr) {
421         return BAD_VALUE;
422     }
423 
424     if (mSpatializerCallback != nullptr) {
425         if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
426             ALOGW("%s: Registering callback %p again",
427                 __func__, mSpatializerCallback.get());
428             return NO_ERROR;
429         }
430         ALOGE("%s: Already one client registered with callback %p",
431             __func__, mSpatializerCallback.get());
432         return INVALID_OPERATION;
433     }
434 
435     sp<IBinder> binder = IInterface::asBinder(callback);
436     status_t status = binder->linkToDeath(this);
437     if (status == NO_ERROR) {
438         mSpatializerCallback = callback;
439     }
440     ALOGV("%s status %d", __func__, status);
441     return status;
442 }
443 
444 // IBinder::DeathRecipient
binderDied(__unused const wp<IBinder> & who)445 void Spatializer::binderDied(__unused const wp<IBinder> &who) {
446     {
447         std::lock_guard lock(mLock);
448         mLevel = SpatializationLevel::NONE;
449         mSpatializerCallback.clear();
450     }
451     ALOGV("%s", __func__);
452     mPolicyCallback->onCheckSpatializer();
453 }
454 
455 // ISpatializer
getSupportedLevels(std::vector<SpatializationLevel> * levels)456 Status Spatializer::getSupportedLevels(std::vector<SpatializationLevel> *levels) {
457     ALOGV("%s", __func__);
458     if (levels == nullptr) {
459         return binderStatusFromStatusT(BAD_VALUE);
460     }
461     // SpatializationLevel::NONE is already required from the effect or we don't load it.
462     levels->insert(levels->end(), mLevels.begin(), mLevels.end());
463     return Status::ok();
464 }
465 
setLevel(SpatializationLevel level)466 Status Spatializer::setLevel(SpatializationLevel level) {
467     ALOGV("%s level %s", __func__, media::toString(level).c_str());
468     mLocalLog.log("%s with %s", __func__, media::toString(level).c_str());
469     if (level != SpatializationLevel::NONE
470             && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
471         return binderStatusFromStatusT(BAD_VALUE);
472     }
473     sp<media::INativeSpatializerCallback> callback;
474     bool levelChanged = false;
475     {
476         std::lock_guard lock(mLock);
477         levelChanged = mLevel != level;
478         mLevel = level;
479         callback = mSpatializerCallback;
480 
481         if (levelChanged && mEngine != nullptr) {
482             checkEngineState_l();
483         }
484         checkSensorsState_l();
485     }
486 
487     if (levelChanged) {
488         mPolicyCallback->onCheckSpatializer();
489         if (callback != nullptr) {
490             callback->onLevelChanged(level);
491         }
492     }
493     return Status::ok();
494 }
495 
getLevel(SpatializationLevel * level)496 Status Spatializer::getLevel(SpatializationLevel *level) {
497     if (level == nullptr) {
498         return binderStatusFromStatusT(BAD_VALUE);
499     }
500     std::lock_guard lock(mLock);
501     *level = mLevel;
502     ALOGV("%s level %d", __func__, (int)*level);
503     return Status::ok();
504 }
505 
isHeadTrackingSupported(bool * supports)506 Status Spatializer::isHeadTrackingSupported(bool *supports) {
507     ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
508     if (supports == nullptr) {
509         return binderStatusFromStatusT(BAD_VALUE);
510     }
511     std::lock_guard lock(mLock);
512     *supports = mSupportsHeadTracking;
513     return Status::ok();
514 }
515 
getSupportedHeadTrackingModes(std::vector<SpatializerHeadTrackingMode> * modes)516 Status Spatializer::getSupportedHeadTrackingModes(
517         std::vector<SpatializerHeadTrackingMode>* modes) {
518     std::lock_guard lock(mLock);
519     ALOGV("%s", __func__);
520     if (modes == nullptr) {
521         return binderStatusFromStatusT(BAD_VALUE);
522     }
523     modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
524     return Status::ok();
525 }
526 
setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode)527 Status Spatializer::setDesiredHeadTrackingMode(SpatializerHeadTrackingMode mode) {
528     ALOGV("%s mode %s", __func__, media::toString(mode).c_str());
529 
530     if (!mSupportsHeadTracking) {
531         return binderStatusFromStatusT(INVALID_OPERATION);
532     }
533     mLocalLog.log("%s with %s", __func__, media::toString(mode).c_str());
534     std::lock_guard lock(mLock);
535     switch (mode) {
536         case SpatializerHeadTrackingMode::OTHER:
537             return binderStatusFromStatusT(BAD_VALUE);
538         case SpatializerHeadTrackingMode::DISABLED:
539             mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
540             break;
541         case SpatializerHeadTrackingMode::RELATIVE_WORLD:
542             mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
543             break;
544         case SpatializerHeadTrackingMode::RELATIVE_SCREEN:
545             mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
546             break;
547     }
548 
549     checkPoseController_l();
550     checkSensorsState_l();
551 
552     return Status::ok();
553 }
554 
getActualHeadTrackingMode(SpatializerHeadTrackingMode * mode)555 Status Spatializer::getActualHeadTrackingMode(SpatializerHeadTrackingMode *mode) {
556     if (mode == nullptr) {
557         return binderStatusFromStatusT(BAD_VALUE);
558     }
559     std::lock_guard lock(mLock);
560     *mode = mActualHeadTrackingMode;
561     ALOGV("%s mode %d", __func__, (int)*mode);
562     return Status::ok();
563 }
564 
recenterHeadTracker()565 Status Spatializer::recenterHeadTracker() {
566     if (!mSupportsHeadTracking) {
567         return binderStatusFromStatusT(INVALID_OPERATION);
568     }
569     std::lock_guard lock(mLock);
570     if (mPoseController != nullptr) {
571         mPoseController->recenter();
572     }
573     return Status::ok();
574 }
575 
setGlobalTransform(const std::vector<float> & screenToStage)576 Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
577     ALOGV("%s", __func__);
578     if (!mSupportsHeadTracking) {
579         return binderStatusFromStatusT(INVALID_OPERATION);
580     }
581     std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
582     if (!maybePose.has_value()) {
583         ALOGW("Invalid screenToStage vector.");
584         return binderStatusFromStatusT(BAD_VALUE);
585     }
586     std::lock_guard lock(mLock);
587     if (mPoseController != nullptr) {
588         mLocalLog.log("%s with screenToStage %s", __func__,
589                 media::VectorRecorder::toString<float>(screenToStage).c_str());
590         mPoseController->setScreenToStagePose(maybePose.value());
591     }
592     return Status::ok();
593 }
594 
release()595 Status Spatializer::release() {
596     ALOGV("%s", __func__);
597     bool levelChanged = false;
598     {
599         std::lock_guard lock(mLock);
600         if (mSpatializerCallback == nullptr) {
601             return binderStatusFromStatusT(INVALID_OPERATION);
602         }
603 
604         sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
605         binder->unlinkToDeath(this);
606         mSpatializerCallback.clear();
607 
608         levelChanged = mLevel != SpatializationLevel::NONE;
609         mLevel = SpatializationLevel::NONE;
610     }
611 
612     if (levelChanged) {
613         mPolicyCallback->onCheckSpatializer();
614     }
615     return Status::ok();
616 }
617 
setHeadSensor(int sensorHandle)618 Status Spatializer::setHeadSensor(int sensorHandle) {
619     ALOGV("%s sensorHandle %d", __func__, sensorHandle);
620     if (!mSupportsHeadTracking) {
621         return binderStatusFromStatusT(INVALID_OPERATION);
622     }
623     std::lock_guard lock(mLock);
624     if (mHeadSensor != sensorHandle) {
625         mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
626         mHeadSensor = sensorHandle;
627         checkPoseController_l();
628         checkSensorsState_l();
629     }
630     return Status::ok();
631 }
632 
setScreenSensor(int sensorHandle)633 Status Spatializer::setScreenSensor(int sensorHandle) {
634     ALOGV("%s sensorHandle %d", __func__, sensorHandle);
635     if (!mSupportsHeadTracking) {
636         return binderStatusFromStatusT(INVALID_OPERATION);
637     }
638     std::lock_guard lock(mLock);
639     if (mScreenSensor != sensorHandle) {
640         mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
641         mScreenSensor = sensorHandle;
642         // TODO: consider a new method setHeadAndScreenSensor()
643         // because we generally set both at the same time.
644         // This will avoid duplicated work and recentering.
645         checkSensorsState_l();
646     }
647     return Status::ok();
648 }
649 
setDisplayOrientation(float physicalToLogicalAngle)650 Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
651     ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
652     mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
653     const float angle = safe_clamp(physicalToLogicalAngle, 0.f, (float)(2. * M_PI));
654     // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
655     ALOGI_IF(angle != physicalToLogicalAngle,
656             "%s: clamping %f to %f", __func__, physicalToLogicalAngle, angle);
657     std::lock_guard lock(mLock);
658     mDisplayOrientation = angle;
659     if (mPoseController != nullptr) {
660         // This turns on the rate-limiter.
661         mPoseController->setDisplayOrientation(angle);
662     }
663     if (mEngine != nullptr) {
664         setEffectParameter_l(
665             SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{angle});
666     }
667     return Status::ok();
668 }
669 
setHingeAngle(float hingeAngle)670 Status Spatializer::setHingeAngle(float hingeAngle) {
671     ALOGV("%s hingeAngle %f", __func__, hingeAngle);
672     mLocalLog.log("%s with %f", __func__, hingeAngle);
673     const float angle = safe_clamp(hingeAngle, 0.f, (float)(2. * M_PI));
674     // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
675     ALOGI_IF(angle != hingeAngle,
676             "%s: clamping %f to %f", __func__, hingeAngle, angle);
677     std::lock_guard lock(mLock);
678     mHingeAngle = angle;
679     if (mEngine != nullptr) {
680         setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{angle});
681     }
682     return Status::ok();
683 }
684 
setFoldState(bool folded)685 Status Spatializer::setFoldState(bool folded) {
686     ALOGV("%s foldState %d", __func__, (int)folded);
687     mLocalLog.log("%s with %d", __func__, (int)folded);
688     std::lock_guard lock(mLock);
689     mFoldedState = folded;
690     if (mEngine != nullptr) {
691         // we don't suppress multiple calls with the same folded state - that's
692         // done at the caller.
693         setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE, std::vector<uint8_t>{mFoldedState});
694     }
695     return Status::ok();
696 }
697 
getSupportedModes(std::vector<SpatializationMode> * modes)698 Status Spatializer::getSupportedModes(std::vector<SpatializationMode> *modes) {
699     ALOGV("%s", __func__);
700     if (modes == nullptr) {
701         return binderStatusFromStatusT(BAD_VALUE);
702     }
703     *modes = mSpatializationModes;
704     return Status::ok();
705 }
706 
registerHeadTrackingCallback(const sp<media::ISpatializerHeadTrackingCallback> & callback)707 Status Spatializer::registerHeadTrackingCallback(
708         const sp<media::ISpatializerHeadTrackingCallback>& callback) {
709     ALOGV("%s callback %p", __func__, callback.get());
710     std::lock_guard lock(mLock);
711     if (!mSupportsHeadTracking) {
712         return binderStatusFromStatusT(INVALID_OPERATION);
713     }
714     mHeadTrackingCallback = callback;
715     return Status::ok();
716 }
717 
setParameter(int key,const std::vector<unsigned char> & value)718 Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
719     ALOGV("%s key %d", __func__, key);
720     std::lock_guard lock(mLock);
721     status_t status = INVALID_OPERATION;
722     if (mEngine != nullptr) {
723         status = setEffectParameter_l(key, value);
724     }
725     return binderStatusFromStatusT(status);
726 }
727 
getParameter(int key,std::vector<unsigned char> * value)728 Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
729     ALOGV("%s key %d value size %d", __func__, key,
730           (value != nullptr ? (int)value->size() : -1));
731     if (value == nullptr) {
732         return binderStatusFromStatusT(BAD_VALUE);
733     }
734     std::lock_guard lock(mLock);
735     status_t status = INVALID_OPERATION;
736     if (mEngine != nullptr) {
737         ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
738         status = getEffectParameter_l(key, value);
739     }
740     return binderStatusFromStatusT(status);
741 }
742 
getOutput(int * output)743 Status Spatializer::getOutput(int *output) {
744     ALOGV("%s", __func__);
745     if (output == nullptr) {
746         binderStatusFromStatusT(BAD_VALUE);
747     }
748     std::lock_guard lock(mLock);
749     *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
750     ALOGV("%s got output %d", __func__, *output);
751     return Status::ok();
752 }
753 
754 // SpatializerPoseController::Listener
onHeadToStagePose(const Pose3f & headToStage)755 void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
756     ALOGV("%s", __func__);
757     LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
758             "onHeadToStagePose() called with no head tracking support!");
759 
760     auto vec = headToStage.toVector();
761     LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
762             "%s invalid head to stage vector size %zu", __func__, vec.size());
763     sp<AMessage> msg =
764             new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
765     for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
766         msg->setFloat(sHeadPoseKeys[i], vec[i]);
767     }
768     msg->post();
769 }
770 
resetEngineHeadPose_l()771 void Spatializer::resetEngineHeadPose_l() {
772     ALOGV("%s mEngine %p", __func__, mEngine.get());
773     if (mEngine == nullptr) {
774         return;
775     }
776     const std::vector<float> headToStage(6, 0.0);
777     setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
778     setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
779             std::vector<SpatializerHeadTrackingMode>{SpatializerHeadTrackingMode::DISABLED});
780 }
781 
onHeadToStagePoseMsg(const std::vector<float> & headToStage)782 void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
783     ALOGV("%s", __func__);
784     sp<media::ISpatializerHeadTrackingCallback> callback;
785     {
786         std::lock_guard lock(mLock);
787         callback = mHeadTrackingCallback;
788         if (mEngine != nullptr) {
789             setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
790             const auto record = recordFromTranslationRotationVector(headToStage);
791             mPoseRecorder.record(record);
792             mPoseDurableRecorder.record(record);
793         }
794     }
795 
796     if (callback != nullptr) {
797         callback->onHeadToSoundStagePoseUpdated(headToStage);
798     }
799 }
800 
onActualModeChange(HeadTrackingMode mode)801 void Spatializer::onActualModeChange(HeadTrackingMode mode) {
802     std::string modeStr = media::toString(mode);
803     ALOGV("%s(%s)", __func__, modeStr.c_str());
804     sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
805     msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
806     msg->post();
807 }
808 
onActualModeChangeMsg(HeadTrackingMode mode)809 void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
810     ALOGV("%s(%d)", __func__, (int) mode);
811     sp<media::ISpatializerHeadTrackingCallback> callback;
812     SpatializerHeadTrackingMode spatializerMode;
813     {
814         std::lock_guard lock(mLock);
815         if (!mSupportsHeadTracking) {
816             spatializerMode = SpatializerHeadTrackingMode::DISABLED;
817         } else {
818             switch (mode) {
819                 case HeadTrackingMode::STATIC:
820                     spatializerMode = SpatializerHeadTrackingMode::DISABLED;
821                     break;
822                 case HeadTrackingMode::WORLD_RELATIVE:
823                     spatializerMode = SpatializerHeadTrackingMode::RELATIVE_WORLD;
824                     break;
825                 case HeadTrackingMode::SCREEN_RELATIVE:
826                     spatializerMode = SpatializerHeadTrackingMode::RELATIVE_SCREEN;
827                     break;
828                 default:
829                     LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
830             }
831         }
832         mActualHeadTrackingMode = spatializerMode;
833         if (mEngine != nullptr) {
834             if (spatializerMode == SpatializerHeadTrackingMode::DISABLED) {
835                 resetEngineHeadPose_l();
836             } else {
837                 setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
838                                      std::vector<SpatializerHeadTrackingMode>{spatializerMode});
839             }
840         }
841         callback = mHeadTrackingCallback;
842         mLocalLog.log("%s: updating mode to %s", __func__, media::toString(mode).c_str());
843     }
844     if (callback != nullptr) {
845         callback->onHeadTrackingModeChanged(spatializerMode);
846     }
847 }
848 
attachOutput(audio_io_handle_t output,size_t numActiveTracks)849 status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
850     bool outputChanged = false;
851     sp<media::INativeSpatializerCallback> callback;
852 
853     {
854         std::lock_guard lock(mLock);
855         ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
856         mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
857                       numActiveTracks, (int)mOutput);
858         if (mOutput != AUDIO_IO_HANDLE_NONE) {
859             LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
860             // remove FX instance
861             mEngine->setEnabled(false);
862             mEngine.clear();
863             mPoseController.reset();
864             AudioSystem::removeSupportedLatencyModesCallback(this);
865         }
866 
867         // create FX instance on output
868         AttributionSourceState attributionSource = AttributionSourceState();
869         mEngine = new AudioEffect(attributionSource);
870         mEngine->set(nullptr, &mEngineDescriptor.uuid, 0, Spatializer::engineCallback /* cbf */,
871                      this /* user */, AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */,
872                      false /* probe */, true /* notifyFramesProcessed */);
873         status_t status = mEngine->initCheck();
874         ALOGV("%s mEngine create status %d", __func__, (int)status);
875         if (status != NO_ERROR) {
876             return status;
877         }
878 
879         outputChanged = mOutput != output;
880         mOutput = output;
881         mNumActiveTracks = numActiveTracks;
882         AudioSystem::addSupportedLatencyModesCallback(this);
883 
884         std::vector<audio_latency_mode_t> latencyModes;
885         status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
886         if (status == OK) {
887             mSupportedLatencyModes = latencyModes;
888         }
889 
890         checkEngineState_l();
891         if (mSupportsHeadTracking) {
892             checkPoseController_l();
893             checkSensorsState_l();
894         }
895         callback = mSpatializerCallback;
896 
897         // Restore common effect state.
898         setEffectParameter_l(SPATIALIZER_PARAM_DISPLAY_ORIENTATION,
899                 std::vector<float>{mDisplayOrientation});
900         setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE,
901                 std::vector<uint8_t>{mFoldedState});
902         setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE,
903                 std::vector<float>{mHingeAngle});
904     }
905 
906     if (outputChanged && callback != nullptr) {
907         callback->onOutputChanged(output);
908     }
909 
910     return NO_ERROR;
911 }
912 
detachOutput()913 audio_io_handle_t Spatializer::detachOutput() {
914     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
915     sp<media::INativeSpatializerCallback> callback;
916 
917     {
918         std::lock_guard lock(mLock);
919         mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
920         ALOGV("%s mOutput %d", __func__, (int)mOutput);
921         if (mOutput == AUDIO_IO_HANDLE_NONE) {
922             return output;
923         }
924         // remove FX instance
925         mEngine->setEnabled(false);
926         mEngine.clear();
927         AudioSystem::removeSupportedLatencyModesCallback(this);
928         output = mOutput;
929         mOutput = AUDIO_IO_HANDLE_NONE;
930         mPoseController.reset();
931         callback = mSpatializerCallback;
932     }
933 
934     if (callback != nullptr) {
935         callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
936     }
937     return output;
938 }
939 
onSupportedLatencyModesChanged(audio_io_handle_t output,const std::vector<audio_latency_mode_t> & modes)940 void Spatializer::onSupportedLatencyModesChanged(
941         audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
942     ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
943     sp<AMessage> msg =
944             new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
945     msg->setObject(EngineCallbackHandler::kLatencyModesKey,
946         sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
947     msg->post();
948 }
949 
onSupportedLatencyModesChangedMsg(audio_io_handle_t output,std::vector<audio_latency_mode_t> && modes)950 void Spatializer::onSupportedLatencyModesChangedMsg(
951         audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
952     std::lock_guard lock(mLock);
953     ALOGV("%s output %d mOutput %d num modes %zu",
954             __func__, (int)output, (int)mOutput, modes.size());
955     if (output == mOutput) {
956         mSupportedLatencyModes = std::move(modes);
957         checkSensorsState_l();
958     }
959 }
960 
updateActiveTracks(size_t numActiveTracks)961 void Spatializer::updateActiveTracks(size_t numActiveTracks) {
962     std::lock_guard lock(mLock);
963     if (mNumActiveTracks != numActiveTracks) {
964         mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
965         mNumActiveTracks = numActiveTracks;
966         checkEngineState_l();
967         checkSensorsState_l();
968     }
969 }
970 
checkSensorsState_l()971 void Spatializer::checkSensorsState_l() {
972     audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
973     const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
974     const bool supportsLowLatencyMode = supportsSetLatencyMode && std::find(
975             mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
976             AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
977     if (mSupportsHeadTracking) {
978         if (mPoseController != nullptr) {
979             // TODO(b/253297301, b/255433067) reenable low latency condition check
980             // for Head Tracking after Bluetooth HAL supports it correctly.
981             if (mNumActiveTracks > 0 && mLevel != SpatializationLevel::NONE
982                 && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
983                 && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
984                 if (mEngine != nullptr) {
985                     setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
986                             std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
987                 }
988                 mPoseController->setHeadSensor(mHeadSensor);
989                 mPoseController->setScreenSensor(mScreenSensor);
990                 if (supportsLowLatencyMode) requestedLatencyMode = AUDIO_LATENCY_MODE_LOW;
991             } else {
992                 mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
993                 mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
994                 resetEngineHeadPose_l();
995             }
996         } else {
997             resetEngineHeadPose_l();
998         }
999     }
1000     if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
1001         const status_t status =
1002                 AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
1003         ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
1004                 __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
1005     }
1006 }
1007 
checkEngineState_l()1008 void Spatializer::checkEngineState_l() {
1009     if (mEngine != nullptr) {
1010         if (mLevel != SpatializationLevel::NONE && mNumActiveTracks > 0) {
1011             mEngine->setEnabled(true);
1012             setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
1013                     std::vector<SpatializationLevel>{mLevel});
1014         } else {
1015             setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
1016                     std::vector<SpatializationLevel>{SpatializationLevel::NONE});
1017             mEngine->setEnabled(false);
1018         }
1019     }
1020 }
1021 
checkPoseController_l()1022 void Spatializer::checkPoseController_l() {
1023     bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
1024             && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
1025 
1026     if (isControllerNeeded && mPoseController == nullptr) {
1027         mPoseController = std::make_shared<SpatializerPoseController>(
1028                 static_cast<SpatializerPoseController::Listener*>(this),
1029                 10ms, std::nullopt);
1030         LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
1031                             "%s could not allocate pose controller", __func__);
1032         mPoseController->setDisplayOrientation(mDisplayOrientation);
1033     } else if (!isControllerNeeded && mPoseController != nullptr) {
1034         mPoseController.reset();
1035         resetEngineHeadPose_l();
1036     }
1037     if (mPoseController != nullptr) {
1038         mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
1039     }
1040 }
1041 
calculateHeadPose()1042 void Spatializer::calculateHeadPose() {
1043     ALOGV("%s", __func__);
1044     std::lock_guard lock(mLock);
1045     if (mPoseController != nullptr) {
1046         mPoseController->calculateAsync();
1047     }
1048 }
1049 
engineCallback(int32_t event,void * user,void * info)1050 void Spatializer::engineCallback(int32_t event, void *user, void *info) {
1051     if (user == nullptr) {
1052         return;
1053     }
1054     Spatializer* const me = reinterpret_cast<Spatializer *>(user);
1055     switch (event) {
1056         case AudioEffect::EVENT_FRAMES_PROCESSED: {
1057             int frames = info == nullptr ? 0 : *(int*)info;
1058             ALOGV("%s frames processed %d for me %p", __func__, frames, me);
1059             me->postFramesProcessedMsg(frames);
1060         } break;
1061         default:
1062             ALOGV("%s event %d", __func__, event);
1063             break;
1064     }
1065 }
1066 
postFramesProcessedMsg(int frames)1067 void Spatializer::postFramesProcessedMsg(int frames) {
1068     sp<AMessage> msg =
1069             new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
1070     msg->setInt32(EngineCallbackHandler::kNumFramesKey, frames);
1071     msg->post();
1072 }
1073 
toString(unsigned level) const1074 std::string Spatializer::toString(unsigned level) const {
1075     std::string prefixSpace(level, ' ');
1076     std::string ss = prefixSpace + "Spatializer:\n";
1077     bool needUnlock = false;
1078 
1079     prefixSpace += ' ';
1080     if (!mLock.try_lock()) {
1081         // dumpsys even try_lock failed, information dump can be useful although may not accurate
1082         ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1083     } else {
1084         needUnlock = true;
1085     }
1086 
1087     // Spatializer class information.
1088     // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1089     ss.append(prefixSpace).append("Supported levels: [");
1090     for (auto& level : mLevels) {
1091         base::StringAppendF(&ss, " %s", media::toString(level).c_str());
1092     }
1093     base::StringAppendF(&ss, "], mLevel: %s", media::toString(mLevel).c_str());
1094 
1095     base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1096     for (auto& mode : mHeadTrackingModes) {
1097         base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1098     }
1099     base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
1100                         media::toString(mDesiredHeadTrackingMode).c_str(),
1101                         media::toString(mActualHeadTrackingMode).c_str());
1102 
1103     base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1104     for (auto& mode : mSpatializationModes) {
1105         base::StringAppendF(&ss, " %s", media::toString(mode).c_str());
1106     }
1107     ss += "]\n";
1108 
1109     base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1110     for (auto& mask : mChannelMasks) {
1111         base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1112     }
1113     base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1114                         mSupportsHeadTracking ? "true" : "false");
1115     // 2. Settings (Output, tracks)
1116     base::StringAppendF(&ss, "%smNumActiveTracks: %zu\n", prefixSpace.c_str(), mNumActiveTracks);
1117     base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1118 
1119     // 3. Sensors, Effect information.
1120     base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1121     base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1122     base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1123     base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1124                         mDisplayOrientation);
1125 
1126     ss.append(prefixSpace + "CommandLog:\n");
1127     ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
1128 
1129     // PostController dump.
1130     if (mPoseController != nullptr) {
1131         ss.append(mPoseController->toString(level + 1))
1132             .append(prefixSpace)
1133             .append("Pose (active stage-to-head) [tx, ty, tz : pitch, roll, yaw]:\n")
1134             .append(prefixSpace)
1135             .append(" PerMinuteHistory:\n")
1136             .append(mPoseDurableRecorder.toString(level + 3))
1137             .append(prefixSpace)
1138             .append(" PerSecondHistory:\n")
1139             .append(mPoseRecorder.toString(level + 3));
1140     } else {
1141         ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1142     }
1143 
1144     if (needUnlock) {
1145         mLock.unlock();
1146     }
1147     return ss;
1148 }
1149 
1150 } // namespace android
1151