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