1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_MEDIA_SPATIALIZER_H
18 #define ANDROID_MEDIA_SPATIALIZER_H
19 
20 #include <android-base/stringprintf.h>
21 #include <android/media/BnEffect.h>
22 #include <android/media/BnSpatializer.h>
23 #include <android/media/audio/common/AudioLatencyMode.h>
24 #include <android/media/audio/common/HeadTracking.h>
25 #include <android/media/audio/common/Spatialization.h>
26 #include <audio_utils/mutex.h>
27 #include <audio_utils/SimpleLog.h>
28 #include <math.h>
29 #include <media/AudioEffect.h>
30 #include <media/MediaMetricsItem.h>
31 #include <media/audiohal/EffectsFactoryHalInterface.h>
32 #include <media/VectorRecorder.h>
33 #include <media/audiohal/EffectHalInterface.h>
34 #include <media/stagefright/foundation/ALooper.h>
35 #include <system/audio_effects/effect_spatializer.h>
36 #include <string>
37 #include <unordered_set>
38 
39 #include "SpatializerPoseController.h"
40 
41 namespace android {
42 
43 
44 // ----------------------------------------------------------------------------
45 
46 /**
47  * A callback interface from the Spatializer object or its parent AudioPolicyService.
48  * This is implemented by the audio policy service hosting the Spatializer to perform
49  * actions needed when a state change inside the Spatializer requires some audio system
50  * changes that cannot be performed by the Spatializer. For instance opening or closing a
51  * spatializer output stream when the spatializer is enabled or disabled
52  */
53 class SpatializerPolicyCallback {
54 public:
55     /** Called when a stage change occurs that requires the parent audio policy service to take
56      * some action.
57      */
58     virtual void onCheckSpatializer() = 0;
59 
60     virtual ~SpatializerPolicyCallback() = default;
61 };
62 /**
63  * The Spatializer class implements all functional controlling the multichannel spatializer
64  * with head tracking implementation in the native audio service: audio policy and audio flinger.
65  * It presents an AIDL interface available to the java audio service to discover the availability
66  * of the feature and options, control its state and register an active head tracking sensor.
67  * It maintains the current state of the platform spatializer and applies the stored parameters
68  * when the spatializer engine is created and enabled.
69  * Based on the requested spatializer level, it will request the creation of a specialized output
70  * mixer to the audio policy service which will in turn notify the Spatializer of the output
71  * stream on which a spatializer engine should be created, configured and enabled.
72  * The spatializer also hosts the head tracking management logic. This logic receives the
73  * desired head tracking mode and selected head tracking sensor, registers a sensor event listener
74  * and derives the compounded head pose information to the spatializer engine.
75  *
76  * Workflow:
77  * - Initialization: when the audio policy service starts, it checks if a spatializer effect
78  * engine exists and if the audio policy manager reports a dedicated spatializer output profile.
79  * If both conditions are met, a Spatializer object is created
80  * - Capabilities discovery: AudioService will call AudioSystem::canBeSpatialized() and if true,
81  * acquire an ISpatializer interface with AudioSystem::getSpatializer(). This interface
82  * will be used to query the implementation capabilities and configure the spatializer.
83  * - Enabling: when ISpatializer::setLevel() sets a level different from NONE the spatializer
84  * is considered enabled. The audio policy callback onCheckSpatializer() is called. This
85  * triggers a request to audio policy manager to open a spatialization output stream and a
86  * spatializer mixer is created in audio flinger. When an output is returned by audio policy
87  * manager, Spatializer::attachOutput() is called which creates and enables the spatializer
88  * stage engine on the specified output.
89  * - Disabling: when the spatialization level is set to NONE, the spatializer is considered
90  * disabled. The audio policy callback onCheckSpatializer() is called. This triggers a call
91  * to Spatializer::detachOutput() and the spatializer engine is released. Then a request is
92  * made to audio policy manager to release and close the spatializer output stream and the
93  * spatializer mixer thread is destroyed.
94  */
95 class Spatializer : public media::BnSpatializer,
96                     public AudioEffect::IAudioEffectCallback,
97                     public IBinder::DeathRecipient,
98                     private SpatializerPoseController::Listener,
99                     public virtual AudioSystem::SupportedLatencyModesCallback {
100   public:
101     static sp<Spatializer> create(SpatializerPolicyCallback* callback,
102                                   const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
103 
104            ~Spatializer() override;
105 
106     /** RefBase */
107     void onFirstRef();
108 
109     /** ISpatializer, see ISpatializer.aidl */
110     binder::Status release() override;
111     binder::Status getSupportedLevels(
112             std::vector<media::audio::common::Spatialization::Level>* levels) override;
113     binder::Status setLevel(media::audio::common::Spatialization::Level level) override;
114     binder::Status getLevel(media::audio::common::Spatialization::Level *level) override;
115     binder::Status isHeadTrackingSupported(bool *supports);
116     binder::Status getSupportedHeadTrackingModes(
117             std::vector<media::audio::common::HeadTracking::Mode>* modes) override;
118     binder::Status setDesiredHeadTrackingMode(
119             media::audio::common::HeadTracking::Mode mode) override;
120     binder::Status getActualHeadTrackingMode(
121             media::audio::common::HeadTracking::Mode* mode) override;
122     binder::Status recenterHeadTracker() override;
123     binder::Status setGlobalTransform(const std::vector<float>& screenToStage) override;
124     binder::Status setHeadSensor(int sensorHandle) override;
125     binder::Status setScreenSensor(int sensorHandle) override;
126     binder::Status setDisplayOrientation(float physicalToLogicalAngle) override;
127     binder::Status setHingeAngle(float hingeAngle) override;
128     binder::Status setFoldState(bool folded) override;
129     binder::Status getSupportedModes(
130             std::vector<media::audio::common::Spatialization::Mode>* modes) override;
131     binder::Status registerHeadTrackingCallback(
132         const sp<media::ISpatializerHeadTrackingCallback>& callback) override;
133     binder::Status setParameter(int key, const std::vector<unsigned char>& value) override;
134     binder::Status getParameter(int key, std::vector<unsigned char> *value) override;
135     binder::Status getOutput(int *output);
136 
137     /** IBinder::DeathRecipient. Listen to the death of the INativeSpatializerCallback. */
138     virtual void binderDied(const wp<IBinder>& who);
139 
140     /** SupportedLatencyModesCallback */
141     void onSupportedLatencyModesChanged(
142             audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) override;
143 
144     /** Registers a INativeSpatializerCallback when a client is attached to this Spatializer
145      * by audio policy service.
146      */
147     status_t registerCallback(const sp<media::INativeSpatializerCallback>& callback);
148 
149     status_t loadEngineConfiguration(sp<EffectHalInterface> effect);
150 
151     /** Level getter for use by local classes. */
getLevel()152     media::audio::common::Spatialization::Level getLevel() const {
153         audio_utils::lock_guard lock(mMutex);
154         return mLevel;
155     }
156 
157     /** For test only */
158     std::unordered_set<media::audio::common::HeadTracking::ConnectionMode>
getSupportedHeadtrackingConnectionModes()159             getSupportedHeadtrackingConnectionModes() const {
160         return mSupportedHeadtrackingConnectionModes;
161     }
162 
163     /** For test only */
getHeadtrackingConnectionMode()164     media::audio::common::HeadTracking::ConnectionMode getHeadtrackingConnectionMode() const {
165         return mHeadtrackingConnectionMode;
166     }
167 
168     /** For test only */
getSupportedLatencyModes()169     std::vector<audio_latency_mode_t> getSupportedLatencyModes() const {
170         audio_utils::lock_guard lock(mMutex);
171         return mSupportedLatencyModes;
172     }
173 
174     /** For test only */
getOrderedLowLatencyModes()175     std::vector<audio_latency_mode_t> getOrderedLowLatencyModes() const {
176         return mOrderedLowLatencyModes;
177     }
178 
179     /** For test only */
getRequestedLatencyMode()180     audio_latency_mode_t getRequestedLatencyMode() const {
181         audio_utils::lock_guard lock(mMutex);
182         return mRequestedLatencyMode;
183     }
184 
185     /** Called by audio policy service when the special output mixer dedicated to spatialization
186      * is opened and the spatializer engine must be created.
187      */
188     status_t attachOutput(audio_io_handle_t output, size_t numActiveTracks);
189     /** Called by audio policy service when the special output mixer dedicated to spatialization
190      * is closed and the spatializer engine must be release.
191      */
192     audio_io_handle_t detachOutput();
193     /** Returns the output stream the spatializer is attached to. */
getOutput()194     audio_io_handle_t getOutput() const { audio_utils::lock_guard lock(mMutex); return mOutput; }
195 
196     /** For test only */
setOutput(audio_io_handle_t output)197     void setOutput(audio_io_handle_t output) {
198         audio_utils::lock_guard lock(mMutex);
199         mOutput = output;
200     }
201 
202     void updateActiveTracks(size_t numActiveTracks);
203 
204     /** Gets the channel mask, sampling rate and format set for the spatializer input. */
205     audio_config_base_t getAudioInConfig() const;
206 
207     void calculateHeadPose();
208 
209     /** Convert fields in Spatializer and sub-modules to a string. Disable thread-safety-analysis
210      * here because we want to dump mutex guarded members even try_lock failed to provide as much
211      * information as possible for debugging purpose. */
212     std::string toString(unsigned level) const NO_THREAD_SAFETY_ANALYSIS;
213 
toString(audio_latency_mode_t mode)214     static std::string toString(audio_latency_mode_t mode) {
215         // We convert to the AIDL type to print (eventually the legacy type will be removed).
216         const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
217         return result.has_value() ?
218                 media::audio::common::toString(*result) : "unknown_latency_mode";
219     }
220 
221     // If the Spatializer is not created, we send the status for metrics purposes.
222     // OK:      Spatializer not expected to be created.
223     // NO_INIT: Spatializer creation failed.
224     static void sendEmptyCreateSpatializerMetricWithStatus(status_t status);
225 
226     /** Made public for test only */
227     void onSupportedLatencyModesChangedMsg(
228             audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes);
229 
230 private:
231     Spatializer(effect_descriptor_t engineDescriptor,
232                      SpatializerPolicyCallback *callback);
233 
234     static void engineCallback(int32_t event, void* user, void *info);
235 
236     // From VirtualizerStageController::Listener
237     void onHeadToStagePose(const media::Pose3f& headToStage) override;
238     void onActualModeChange(media::HeadTrackingMode mode) override;
239 
240     void onHeadToStagePoseMsg(const std::vector<float>& headToStage);
241     void onActualModeChangeMsg(media::HeadTrackingMode mode);
242 
243     static constexpr int kMaxEffectParamValues = 10;
244     /**
245      * Get a parameter from spatializer engine by calling the effect HAL command method directly.
246      * To be used when the engine instance mEngine is not yet created in the effect framework.
247      * When MULTI_VALUES is false, the expected reply is only one value of type T.
248      * When MULTI_VALUES is true, the expected reply is made of a number (of type T) indicating
249      * how many values are returned, followed by this number for values of type T.
250      */
251     template<bool MULTI_VALUES, typename T>
getHalParameter(sp<EffectHalInterface> effect,uint32_t type,std::vector<T> * values)252     status_t getHalParameter(sp<EffectHalInterface> effect, uint32_t type,
253                                           std::vector<T> *values) {
254         static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
255 
256         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1];
257         uint32_t reply[sizeof(effect_param_t) / sizeof(uint32_t) + 2 + kMaxEffectParamValues];
258 
259         effect_param_t *p = (effect_param_t *)cmd;
260         p->psize = sizeof(uint32_t);
261         if (MULTI_VALUES) {
262             p->vsize = (kMaxEffectParamValues + 1) * sizeof(T);
263         } else {
264             p->vsize = sizeof(T);
265         }
266         *(uint32_t *)p->data = type;
267         uint32_t replySize = sizeof(effect_param_t) + p->psize + p->vsize;
268 
269         status_t status = effect->command(EFFECT_CMD_GET_PARAM,
270                                           sizeof(effect_param_t) + sizeof(uint32_t), cmd,
271                                           &replySize, reply);
272         if (status != NO_ERROR) {
273             return status;
274         }
275         if (p->status != NO_ERROR) {
276             return p->status;
277         }
278         if (replySize <
279                 sizeof(effect_param_t) + sizeof(uint32_t) + (MULTI_VALUES ? 2 : 1) * sizeof(T)) {
280             return BAD_VALUE;
281         }
282 
283         T *params = (T *)((uint8_t *)reply + sizeof(effect_param_t) + sizeof(uint32_t));
284         int numParams = 1;
285         if (MULTI_VALUES) {
286             numParams = (int)*params++;
287         }
288         if (numParams > kMaxEffectParamValues) {
289             return BAD_VALUE;
290         }
291         (*values).clear();
292         std::copy(&params[0], &params[numParams], back_inserter(*values));
293         return NO_ERROR;
294     }
295 
296     /**
297      * Set a parameter to spatializer engine by calling setParameter on mEngine AudioEffect object.
298      * It is possible to pass more than one value of type T according to the parameter type
299      *  according to values vector size.
300      */
301     template<typename T>
setEffectParameter_l(uint32_t type,const std::vector<T> & values)302     status_t setEffectParameter_l(uint32_t type, const std::vector<T>& values) REQUIRES(mMutex) {
303         static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
304 
305         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values.size()];
306         effect_param_t *p = (effect_param_t *)cmd;
307         p->psize = sizeof(uint32_t);
308         p->vsize = sizeof(T) * values.size();
309         *(uint32_t *)p->data = type;
310         memcpy((uint32_t *)p->data + 1, values.data(), sizeof(T) * values.size());
311 
312         status_t status = mEngine->setParameter(p);
313         if (status != NO_ERROR) {
314             return status;
315         }
316         if (p->status != NO_ERROR) {
317             return p->status;
318         }
319         return NO_ERROR;
320     }
321 
322     /**
323      * Set a parameter to spatializer engine by calling setParameter on mEngine AudioEffect object.
324      * The variant is for compound parameters with two values of different base types
325      */
326     template<typename P1, typename P2>
setEffectParameter_l(uint32_t type,const P1 val1,const P2 val2)327     status_t setEffectParameter_l(uint32_t type, const P1 val1, const P2 val2) REQUIRES(mMutex) {
328         static_assert(sizeof(P1) <= sizeof(uint32_t), "The size of P1 must less than 32 bits");
329         static_assert(sizeof(P2) <= sizeof(uint32_t), "The size of P2 must less than 32 bits");
330 
331         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 3];
332         effect_param_t *p = (effect_param_t *)cmd;
333         p->psize = sizeof(uint32_t);
334         p->vsize = 2 * sizeof(uint32_t);
335         *(uint32_t *)p->data = type;
336         *((uint32_t *)p->data + 1) = static_cast<uint32_t>(val1);
337         *((uint32_t *)p->data + 2) = static_cast<uint32_t>(val2);
338 
339         status_t status = mEngine->setParameter(p);
340         if (status != NO_ERROR) {
341             return status;
342         }
343         if (p->status != NO_ERROR) {
344             return p->status;
345         }
346         return NO_ERROR;
347     }
348 
349     /**
350      * Get a parameter from spatializer engine by calling getParameter on AudioEffect object.
351      * It is possible to read more than one value of type T according to the parameter type
352      * by specifying values vector size.
353      */
354     template<typename T>
getEffectParameter_l(uint32_t type,std::vector<T> * values)355     status_t getEffectParameter_l(uint32_t type, std::vector<T> *values) REQUIRES(mMutex) {
356         static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
357 
358         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values->size()];
359         effect_param_t *p = (effect_param_t *)cmd;
360         p->psize = sizeof(uint32_t);
361         p->vsize = sizeof(T) * values->size();
362         *(uint32_t *)p->data = type;
363 
364         status_t status = mEngine->getParameter(p);
365 
366         if (status != NO_ERROR) {
367             return status;
368         }
369         if (p->status != NO_ERROR) {
370             return p->status;
371         }
372 
373         int numValues = std::min(p->vsize / sizeof(T), values->size());
374         (*values).clear();
375         T *retValues = (T *)((uint8_t *)p->data + sizeof(uint32_t));
376         std::copy(&retValues[0], &retValues[numValues], back_inserter(*values));
377 
378         return NO_ERROR;
379     }
380 
381     /**
382      * Get a parameter from spatializer engine by calling getParameter on AudioEffect object.
383      * The variant is for compound parameters with two values of different base types
384      */
385     template<typename P1, typename P2>
getEffectParameter_l(uint32_t type,P1 * val1,P2 * val2)386     status_t getEffectParameter_l(uint32_t type, P1 *val1, P2 *val2) REQUIRES(mMutex) {
387         static_assert(sizeof(P1) <= sizeof(uint32_t), "The size of P1 must less than 32 bits");
388         static_assert(sizeof(P2) <= sizeof(uint32_t), "The size of P2 must less than 32 bits");
389 
390         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 3];
391         effect_param_t *p = (effect_param_t *)cmd;
392         p->psize = sizeof(uint32_t);
393         p->vsize = 2 * sizeof(uint32_t);
394         *(uint32_t *)p->data = type;
395 
396         status_t status = mEngine->getParameter(p);
397 
398         if (status != NO_ERROR) {
399             return status;
400         }
401         if (p->status != NO_ERROR) {
402             return p->status;
403         }
404         *val1 = static_cast<P1>(*((uint32_t *)p->data + 1));
405         *val2 = static_cast<P2>(*((uint32_t *)p->data + 2));
406         return NO_ERROR;
407     }
408 
409     virtual void onFramesProcessed(int32_t framesProcessed) override;
410 
411     /**
412      * Checks if head and screen sensors must be actively monitored based on
413      * spatializer state and playback activity and configures the pose controller
414      * accordingly.
415      */
416     void checkSensorsState_l() REQUIRES(mMutex);
417 
418     /**
419      * Checks if the head pose controller should be created or destroyed according
420      * to desired head tracking mode.
421      */
422     void checkPoseController_l() REQUIRES(mMutex);
423 
424     /**
425      * Checks if the spatializer effect should be enabled based on
426      * playback activity and requested level.
427      */
428     void checkEngineState_l() REQUIRES(mMutex);
429 
430     /**
431      * Reset head tracking mode and recenter pose in engine: Called when the head tracking
432      * is disabled.
433      */
434     void resetEngineHeadPose_l() REQUIRES(mMutex);
435 
436     /** Read bluetooth.core.le.dsa_transport_preference property and populate the ordered list of
437      * preferred low latency modes in mOrderedLowLatencyModes.
438      */
439     void loadOrderedLowLatencyModes();
440 
441     /**
442      * Sort mSupportedLatencyModes list according to the preference order stored in
443      * mOrderedLowLatencyModes.
444      * Note: Because MODE_FREE is not in mOrderedLowLatencyModes, it will always be at
445      * the end of the list.
446      */
447     void sortSupportedLatencyModes_l() REQUIRES(mMutex);
448 
449     /**
450      * Called after enabling head tracking in the spatializer engine to indicate which
451      * connection mode should be used among those supported. The selection depends on
452      * currently supported latency modes reported by the audio HAL.
453      * When the connection mode is direct to the sensor, the sensor ID is also communicated
454      * to the spatializer engine.
455      */
456     void setEngineHeadtrackingConnectionMode_l() REQUIRES(mMutex);
457 
458     /**
459      * Select the desired head tracking connection mode for the spatializer engine among the list
460      * stored in mSupportedHeadtrackingConnectionModes at init time.
461      * Also returns the desired low latency mode according to selected connection mode.
462      */
463     audio_latency_mode_t selectHeadtrackingConnectionMode_l() REQUIRES(mMutex);
464 
465     /** Effect engine descriptor */
466     const effect_descriptor_t mEngineDescriptor;
467     /** Callback interface to parent audio policy service */
468     SpatializerPolicyCallback* const mPolicyCallback;
469 
470     /** Currently there is only one version of the spatializer running */
471     static constexpr const char* kDefaultMetricsId =
472             AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER "0";
473     const std::string mMetricsId = kDefaultMetricsId;
474 
475     /** Mutex protecting internal state */
476     mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kSpatializer_Mutex};
477 
478     /** Client AudioEffect for the engine */
479     sp<AudioEffect> mEngine GUARDED_BY(mMutex);
480     /** Output stream the spatializer mixer thread is attached to */
481     audio_io_handle_t mOutput GUARDED_BY(mMutex) = AUDIO_IO_HANDLE_NONE;
482 
483     /** Callback interface to the client (AudioService) controlling this`Spatializer */
484     sp<media::INativeSpatializerCallback> mSpatializerCallback GUARDED_BY(mMutex);
485 
486     /** Callback interface for head tracking */
487     sp<media::ISpatializerHeadTrackingCallback> mHeadTrackingCallback GUARDED_BY(mMutex);
488 
489     /** Requested spatialization level */
490     media::audio::common::Spatialization::Level mLevel GUARDED_BY(mMutex) =
491             media::audio::common::Spatialization::Level::NONE;
492 
493     /** Control logic for head-tracking, etc. */
494     std::shared_ptr<SpatializerPoseController> mPoseController GUARDED_BY(mMutex);
495 
496     /** Last requested head tracking mode */
497     media::HeadTrackingMode mDesiredHeadTrackingMode GUARDED_BY(mMutex)
498             = media::HeadTrackingMode::STATIC;
499 
500     /** Last-reported actual head-tracking mode. */
501     media::audio::common::HeadTracking::Mode mActualHeadTrackingMode GUARDED_BY(mMutex)
502             = media::audio::common::HeadTracking::Mode::DISABLED;
503 
504     /** Selected Head pose sensor */
505     int32_t mHeadSensor GUARDED_BY(mMutex) = SpatializerPoseController::INVALID_SENSOR;
506 
507     /** Selected Screen pose sensor */
508     int32_t mScreenSensor GUARDED_BY(mMutex) = SpatializerPoseController::INVALID_SENSOR;
509 
510     /** Last display orientation received */
511     float mDisplayOrientation GUARDED_BY(mMutex) = 0.f;  // aligned to natural up orientation.
512 
513     /** Last folded state */
514     bool mFoldedState GUARDED_BY(mMutex) = false;  // foldable: true means folded.
515 
516     /** Last hinge angle */
517     float mHingeAngle GUARDED_BY(mMutex) = 0.f;  // foldable: 0.f is closed, M_PI flat open.
518 
519     std::vector<media::audio::common::Spatialization::Level> mLevels;
520     std::vector<media::audio::common::HeadTracking::Mode> mHeadTrackingModes;
521     std::vector<media::audio::common::Spatialization::Mode> mSpatializationModes;
522     std::vector<audio_channel_mask_t> mChannelMasks;
523     bool mSupportsHeadTracking;
524 
525     /** List of supported head tracking connection modes reported by the spatializer.
526      * If the list is empty, the spatializer does not support any optional connection
527      * mode and mode HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED is assumed.
528      * This is set in the factory constructor and can be accessed without mutex.
529      */
530     std::unordered_set<media::audio::common::HeadTracking::ConnectionMode>
531             mSupportedHeadtrackingConnectionModes;
532     /** Selected HT connection mode when several modes are supported by the spatializer */
533     media::audio::common::HeadTracking::ConnectionMode mHeadtrackingConnectionMode =
534             media::audio::common::HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED;
535 
536     // Looper thread for mEngine callbacks
537     class EngineCallbackHandler;
538 
539     sp<ALooper> mLooper;
540     sp<EngineCallbackHandler> mHandler;
541 
542     size_t mNumActiveTracks GUARDED_BY(mMutex) = 0;
543     std::vector<audio_latency_mode_t> mSupportedLatencyModes GUARDED_BY(mMutex);
544     /** preference order for low latency modes according to persist.bluetooth.hid.transport */
545     std::vector<audio_latency_mode_t> mOrderedLowLatencyModes;
546 
547     audio_latency_mode_t mRequestedLatencyMode GUARDED_BY(mMutex) = AUDIO_LATENCY_MODE_FREE;
548 
549     /** string to latency mode map used to parse bluetooth.core.le.dsa_transport_preference */
550     static const std::map<std::string, audio_latency_mode_t> sStringToLatencyModeMap;
551     static const std::vector<const char*> sHeadPoseKeys;
552 
553     // Local log for command messages.
554     static constexpr int mMaxLocalLogLine = 10;
555     SimpleLog mLocalLog{mMaxLocalLogLine};
556 
557     /**
558      * @brief Calculate and record sensor data.
559      * Dump to local log with max/average pose angle every mPoseRecordThreshold.
560      */
561     // Record one log line per second (up to mMaxLocalLogLine) to capture most recent sensor data.
GUARDED_BY(mMutex)562     media::VectorRecorder mPoseRecorder GUARDED_BY(mMutex) {
563         6 /* vectorSize */, std::chrono::seconds(1), mMaxLocalLogLine, { 3 } /* delimiterIdx */};
564     // Record one log line per minute (up to mMaxLocalLogLine) to capture durable sensor data.
GUARDED_BY(mMutex)565     media::VectorRecorder mPoseDurableRecorder GUARDED_BY(mMutex) {
566         6 /* vectorSize */, std::chrono::minutes(1), mMaxLocalLogLine, { 3 } /* delimiterIdx */};
567 };  // Spatializer
568 
569 }; // namespace android
570 
571 #endif // ANDROID_MEDIA_SPATIALIZER_H
572