xref: /aosp_15_r20/frameworks/av/services/audiopolicy/service/Spatializer.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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     binder::Status getSpatializedChannelMasks(std::vector<int>* masks) override;
137 
138     /** IBinder::DeathRecipient. Listen to the death of the INativeSpatializerCallback. */
139     virtual void binderDied(const wp<IBinder>& who);
140 
141     /** SupportedLatencyModesCallback */
142     void onSupportedLatencyModesChanged(
143             audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) override;
144 
145     /** Registers a INativeSpatializerCallback when a client is attached to this Spatializer
146      * by audio policy service.
147      */
148     status_t registerCallback(const sp<media::INativeSpatializerCallback>& callback);
149 
150     status_t loadEngineConfiguration(sp<EffectHalInterface> effect);
151 
152     /** Level getter for use by local classes. */
getLevel()153     media::audio::common::Spatialization::Level getLevel() const {
154         audio_utils::lock_guard lock(mMutex);
155         return mLevel;
156     }
157 
158     /** For test only */
159     std::unordered_set<media::audio::common::HeadTracking::ConnectionMode>
getSupportedHeadtrackingConnectionModes()160             getSupportedHeadtrackingConnectionModes() const {
161         return mSupportedHeadtrackingConnectionModes;
162     }
163 
164     /** For test only */
getHeadtrackingConnectionMode()165     media::audio::common::HeadTracking::ConnectionMode getHeadtrackingConnectionMode() const {
166         return mHeadtrackingConnectionMode;
167     }
168 
169     /** For test only */
getSupportedLatencyModes()170     std::vector<audio_latency_mode_t> getSupportedLatencyModes() const {
171         audio_utils::lock_guard lock(mMutex);
172         return mSupportedLatencyModes;
173     }
174 
175     /** For test only */
getOrderedLowLatencyModes()176     std::vector<audio_latency_mode_t> getOrderedLowLatencyModes() const {
177         return mOrderedLowLatencyModes;
178     }
179 
180     /** For test only */
getRequestedLatencyMode()181     audio_latency_mode_t getRequestedLatencyMode() const {
182         audio_utils::lock_guard lock(mMutex);
183         return mRequestedLatencyMode;
184     }
185 
186     /** Called by audio policy service when the special output mixer dedicated to spatialization
187      * is opened and the spatializer engine must be created.
188      */
189     status_t attachOutput(audio_io_handle_t output,
190                           const std::vector<audio_channel_mask_t>& activeTracksMasks);
191     /** Called by audio policy service when the special output mixer dedicated to spatialization
192      * is closed and the spatializer engine must be release.
193      */
194     audio_io_handle_t detachOutput();
195     /** Returns the output stream the spatializer is attached to. */
getOutput()196     audio_io_handle_t getOutput() const { audio_utils::lock_guard lock(mMutex); return mOutput; }
197 
198     /** For test only */
setOutput(audio_io_handle_t output)199     void setOutput(audio_io_handle_t output) {
200         audio_utils::lock_guard lock(mMutex);
201         mOutput = output;
202     }
203 
204     void updateActiveTracks(const std::vector<audio_channel_mask_t>& activeTracksMasks);
205 
206     /** Gets the channel mask, sampling rate and format set for the spatializer input. */
207     audio_config_base_t getAudioInConfig() const;
208 
209     void calculateHeadPose();
210 
211     /** Convert fields in Spatializer and sub-modules to a string. Disable thread-safety-analysis
212      * here because we want to dump mutex guarded members even try_lock failed to provide as much
213      * information as possible for debugging purpose. */
214     std::string toString(unsigned level) const NO_THREAD_SAFETY_ANALYSIS;
215 
toString(audio_latency_mode_t mode)216     static std::string toString(audio_latency_mode_t mode) {
217         // We convert to the AIDL type to print (eventually the legacy type will be removed).
218         const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
219         return result.has_value() ?
220                 media::audio::common::toString(*result) : "unknown_latency_mode";
221     }
222 
223     // If the Spatializer is not created, we send the status for metrics purposes.
224     // OK:      Spatializer not expected to be created.
225     // NO_INIT: Spatializer creation failed.
226     static void sendEmptyCreateSpatializerMetricWithStatus(status_t status);
227 
228     /** Made public for test only */
229     void onSupportedLatencyModesChangedMsg(
230             audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes);
231 
232     // Made public for test only
233     /**
234      * Returns true if there exists an immersive channel mask in the vector.
235      *
236      * Example of a non-immersive channel mask such as AUDIO_CHANNEL_OUT_STEREO
237      * versus an immersive channel mask such as AUDIO_CHANNEL_OUT_5POINT1.
238      */
239     static bool containsImmersiveChannelMask(
240             const std::vector<audio_channel_mask_t>& masks);
241 
242 private:
243     Spatializer(effect_descriptor_t engineDescriptor,
244                      SpatializerPolicyCallback *callback);
245 
246     static void engineCallback(int32_t event, void* user, void *info);
247 
248     // From VirtualizerStageController::Listener
249     void onHeadToStagePose(const media::Pose3f& headToStage) override;
250     void onActualModeChange(media::HeadTrackingMode mode) override;
251 
252     void onHeadToStagePoseMsg(const std::vector<float>& headToStage);
253     void onActualModeChangeMsg(media::HeadTrackingMode mode);
254 
255     static constexpr int kMaxEffectParamValues = 10;
256     /**
257      * Get a parameter from spatializer engine by calling the effect HAL command method directly.
258      * To be used when the engine instance mEngine is not yet created in the effect framework.
259      * When MULTI_VALUES is false, the expected reply is only one value of type T.
260      * When MULTI_VALUES is true, the expected reply is made of a number (of type T) indicating
261      * how many values are returned, followed by this number for values of type T.
262      */
263     template<bool MULTI_VALUES, typename T>
getHalParameter(sp<EffectHalInterface> effect,uint32_t type,std::vector<T> * values)264     status_t getHalParameter(sp<EffectHalInterface> effect, uint32_t type,
265                                           std::vector<T> *values) {
266         static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
267 
268         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1];
269         uint32_t reply[sizeof(effect_param_t) / sizeof(uint32_t) + 2 + kMaxEffectParamValues];
270 
271         effect_param_t *p = (effect_param_t *)cmd;
272         p->psize = sizeof(uint32_t);
273         if (MULTI_VALUES) {
274             p->vsize = (kMaxEffectParamValues + 1) * sizeof(T);
275         } else {
276             p->vsize = sizeof(T);
277         }
278         *(uint32_t *)p->data = type;
279         uint32_t replySize = sizeof(effect_param_t) + p->psize + p->vsize;
280 
281         status_t status = effect->command(EFFECT_CMD_GET_PARAM,
282                                           sizeof(effect_param_t) + sizeof(uint32_t), cmd,
283                                           &replySize, reply);
284         if (status != NO_ERROR) {
285             return status;
286         }
287         if (p->status != NO_ERROR) {
288             return p->status;
289         }
290         if (replySize <
291                 sizeof(effect_param_t) + sizeof(uint32_t) + (MULTI_VALUES ? 2 : 1) * sizeof(T)) {
292             return BAD_VALUE;
293         }
294 
295         T *params = (T *)((uint8_t *)reply + sizeof(effect_param_t) + sizeof(uint32_t));
296         int numParams = 1;
297         if (MULTI_VALUES) {
298             numParams = (int)*params++;
299         }
300         if (numParams > kMaxEffectParamValues) {
301             return BAD_VALUE;
302         }
303         (*values).clear();
304         std::copy(&params[0], &params[numParams], back_inserter(*values));
305         return NO_ERROR;
306     }
307 
308     /**
309      * Set a parameter to spatializer engine by calling setParameter on mEngine AudioEffect object.
310      * It is possible to pass more than one value of type T according to the parameter type
311      *  according to values vector size.
312      */
313     template<typename T>
setEffectParameter_l(uint32_t type,const std::vector<T> & values)314     status_t setEffectParameter_l(uint32_t type, const std::vector<T>& values) REQUIRES(mMutex) {
315         static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
316 
317         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values.size()];
318         effect_param_t *p = (effect_param_t *)cmd;
319         p->psize = sizeof(uint32_t);
320         p->vsize = sizeof(T) * values.size();
321         *(uint32_t *)p->data = type;
322         memcpy((uint32_t *)p->data + 1, values.data(), sizeof(T) * values.size());
323 
324         status_t status = mEngine->setParameter(p);
325         if (status != NO_ERROR) {
326             return status;
327         }
328         if (p->status != NO_ERROR) {
329             return p->status;
330         }
331         return NO_ERROR;
332     }
333 
334     /**
335      * Set a parameter to spatializer engine by calling setParameter on mEngine AudioEffect object.
336      * The variant is for compound parameters with two values of different base types
337      */
338     template<typename P1, typename P2>
setEffectParameter_l(uint32_t type,const P1 val1,const P2 val2)339     status_t setEffectParameter_l(uint32_t type, const P1 val1, const P2 val2) REQUIRES(mMutex) {
340         static_assert(sizeof(P1) <= sizeof(uint32_t), "The size of P1 must less than 32 bits");
341         static_assert(sizeof(P2) <= sizeof(uint32_t), "The size of P2 must less than 32 bits");
342 
343         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 3];
344         effect_param_t *p = (effect_param_t *)cmd;
345         p->psize = sizeof(uint32_t);
346         p->vsize = 2 * sizeof(uint32_t);
347         *(uint32_t *)p->data = type;
348         *((uint32_t *)p->data + 1) = static_cast<uint32_t>(val1);
349         *((uint32_t *)p->data + 2) = static_cast<uint32_t>(val2);
350 
351         status_t status = mEngine->setParameter(p);
352         if (status != NO_ERROR) {
353             return status;
354         }
355         if (p->status != NO_ERROR) {
356             return p->status;
357         }
358         return NO_ERROR;
359     }
360 
361     /**
362      * Get a parameter from spatializer engine by calling getParameter on AudioEffect object.
363      * It is possible to read more than one value of type T according to the parameter type
364      * by specifying values vector size.
365      */
366     template<typename T>
getEffectParameter_l(uint32_t type,std::vector<T> * values)367     status_t getEffectParameter_l(uint32_t type, std::vector<T> *values) REQUIRES(mMutex) {
368         static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
369 
370         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values->size()];
371         effect_param_t *p = (effect_param_t *)cmd;
372         p->psize = sizeof(uint32_t);
373         p->vsize = sizeof(T) * values->size();
374         *(uint32_t *)p->data = type;
375 
376         status_t status = mEngine->getParameter(p);
377 
378         if (status != NO_ERROR) {
379             return status;
380         }
381         if (p->status != NO_ERROR) {
382             return p->status;
383         }
384 
385         int numValues = std::min(p->vsize / sizeof(T), values->size());
386         (*values).clear();
387         T *retValues = (T *)((uint8_t *)p->data + sizeof(uint32_t));
388         std::copy(&retValues[0], &retValues[numValues], back_inserter(*values));
389 
390         return NO_ERROR;
391     }
392 
393     /**
394      * Get a parameter from spatializer engine by calling getParameter on AudioEffect object.
395      * The variant is for compound parameters with two values of different base types
396      */
397     template<typename P1, typename P2>
getEffectParameter_l(uint32_t type,P1 * val1,P2 * val2)398     status_t getEffectParameter_l(uint32_t type, P1 *val1, P2 *val2) REQUIRES(mMutex) {
399         static_assert(sizeof(P1) <= sizeof(uint32_t), "The size of P1 must less than 32 bits");
400         static_assert(sizeof(P2) <= sizeof(uint32_t), "The size of P2 must less than 32 bits");
401 
402         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 3];
403         effect_param_t *p = (effect_param_t *)cmd;
404         p->psize = sizeof(uint32_t);
405         p->vsize = 2 * sizeof(uint32_t);
406         *(uint32_t *)p->data = type;
407 
408         status_t status = mEngine->getParameter(p);
409 
410         if (status != NO_ERROR) {
411             return status;
412         }
413         if (p->status != NO_ERROR) {
414             return p->status;
415         }
416         *val1 = static_cast<P1>(*((uint32_t *)p->data + 1));
417         *val2 = static_cast<P2>(*((uint32_t *)p->data + 2));
418         return NO_ERROR;
419     }
420 
421     virtual void onFramesProcessed(int32_t framesProcessed) override;
422 
423     /**
424      * Checks if head and screen sensors must be actively monitored based on
425      * spatializer state and playback activity and configures the pose controller
426      * accordingly.
427      */
428     void checkSensorsState_l() REQUIRES(mMutex);
429 
430     /**
431      * Checks if the head pose controller should be created or destroyed according
432      * to desired head tracking mode.
433      */
434     void checkPoseController_l() REQUIRES(mMutex);
435 
436     /**
437      * Checks if the spatializer effect should be enabled based on
438      * playback activity and requested level.
439      */
440     void checkEngineState_l() REQUIRES(mMutex);
441 
442     /**
443      * Reset head tracking mode and recenter pose in engine: Called when the head tracking
444      * is disabled.
445      */
446     void resetEngineHeadPose_l() REQUIRES(mMutex);
447 
448     /** Read bluetooth.core.le.dsa_transport_preference property and populate the ordered list of
449      * preferred low latency modes in mOrderedLowLatencyModes.
450      */
451     void loadOrderedLowLatencyModes();
452 
453     /**
454      * Sort mSupportedLatencyModes list according to the preference order stored in
455      * mOrderedLowLatencyModes.
456      * Note: Because MODE_FREE is not in mOrderedLowLatencyModes, it will always be at
457      * the end of the list.
458      */
459     void sortSupportedLatencyModes_l() REQUIRES(mMutex);
460 
461     /**
462      * Called after enabling head tracking in the spatializer engine to indicate which
463      * connection mode should be used among those supported. The selection depends on
464      * currently supported latency modes reported by the audio HAL.
465      * When the connection mode is direct to the sensor, the sensor ID is also communicated
466      * to the spatializer engine.
467      */
468     void setEngineHeadtrackingConnectionMode_l() REQUIRES(mMutex);
469 
470     /**
471      * Select the desired head tracking connection mode for the spatializer engine among the list
472      * stored in mSupportedHeadtrackingConnectionModes at init time.
473      * Also returns the desired low latency mode according to selected connection mode.
474      */
475     audio_latency_mode_t selectHeadtrackingConnectionMode_l() REQUIRES(mMutex);
476 
477     /**
478      * Indicates if current conditions are compatible with head tracking.
479      */
480     bool shouldUseHeadTracking_l() const REQUIRES(mMutex);
481 
482     /** Effect engine descriptor */
483     const effect_descriptor_t mEngineDescriptor;
484     /** Callback interface to parent audio policy service */
485     SpatializerPolicyCallback* const mPolicyCallback;
486 
487     /** Currently there is only one version of the spatializer running */
488     static constexpr const char* kDefaultMetricsId =
489             AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER "0";
490     const std::string mMetricsId = kDefaultMetricsId;
491 
492     /** Mutex protecting internal state */
493     mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kSpatializer_Mutex};
494 
495     /** Client AudioEffect for the engine */
496     sp<AudioEffect> mEngine GUARDED_BY(mMutex);
497     /** Output stream the spatializer mixer thread is attached to */
498     audio_io_handle_t mOutput GUARDED_BY(mMutex) = AUDIO_IO_HANDLE_NONE;
499 
500     /** Callback interface to the client (AudioService) controlling this`Spatializer */
501     sp<media::INativeSpatializerCallback> mSpatializerCallback GUARDED_BY(mMutex);
502 
503     /** Callback interface for head tracking */
504     sp<media::ISpatializerHeadTrackingCallback> mHeadTrackingCallback GUARDED_BY(mMutex);
505 
506     /** Requested spatialization level */
507     media::audio::common::Spatialization::Level mLevel GUARDED_BY(mMutex) =
508             media::audio::common::Spatialization::Level::NONE;
509 
510     /** Control logic for head-tracking, etc. */
511     std::shared_ptr<SpatializerPoseController> mPoseController GUARDED_BY(mMutex);
512 
513     /** Last requested head tracking mode */
514     media::HeadTrackingMode mDesiredHeadTrackingMode GUARDED_BY(mMutex)
515             = media::HeadTrackingMode::STATIC;
516 
517     /** Last-reported actual head-tracking mode. */
518     media::audio::common::HeadTracking::Mode mActualHeadTrackingMode GUARDED_BY(mMutex)
519             = media::audio::common::HeadTracking::Mode::DISABLED;
520 
521     /** Selected Head pose sensor */
522     int32_t mHeadSensor GUARDED_BY(mMutex) = SpatializerPoseController::INVALID_SENSOR;
523 
524     /** Selected Screen pose sensor */
525     int32_t mScreenSensor GUARDED_BY(mMutex) = SpatializerPoseController::INVALID_SENSOR;
526 
527     /** Last display orientation received */
528     float mDisplayOrientation GUARDED_BY(mMutex) = 0.f;  // aligned to natural up orientation.
529 
530     /** Last folded state */
531     bool mFoldedState GUARDED_BY(mMutex) = false;  // foldable: true means folded.
532 
533     /** Last hinge angle */
534     float mHingeAngle GUARDED_BY(mMutex) = 0.f;  // foldable: 0.f is closed, M_PI flat open.
535 
536     std::vector<media::audio::common::Spatialization::Level> mLevels;
537     std::vector<media::audio::common::HeadTracking::Mode> mHeadTrackingModes;
538     std::vector<media::audio::common::Spatialization::Mode> mSpatializationModes;
539     std::vector<audio_channel_mask_t> mChannelMasks;
540     std::vector<audio_channel_mask_t> mSpatializedChannelMasks;
541     bool mSupportsHeadTracking;
542 
543     /** List of supported head tracking connection modes reported by the spatializer.
544      * If the list is empty, the spatializer does not support any optional connection
545      * mode and mode HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED is assumed.
546      * This is set in the factory constructor and can be accessed without mutex.
547      */
548     std::unordered_set<media::audio::common::HeadTracking::ConnectionMode>
549             mSupportedHeadtrackingConnectionModes;
550     /** Selected HT connection mode when several modes are supported by the spatializer */
551     media::audio::common::HeadTracking::ConnectionMode mHeadtrackingConnectionMode =
552             media::audio::common::HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED;
553 
554     // Looper thread for mEngine callbacks
555     class EngineCallbackHandler;
556 
557     sp<ALooper> mLooper;
558     sp<EngineCallbackHandler> mHandler;
559 
560     std::vector<audio_channel_mask_t> mActiveTracksMasks GUARDED_BY(mMutex);
561     std::vector<audio_latency_mode_t> mSupportedLatencyModes GUARDED_BY(mMutex);
562     /** preference order for low latency modes according to persist.bluetooth.hid.transport */
563     std::vector<audio_latency_mode_t> mOrderedLowLatencyModes;
564 
565     audio_latency_mode_t mRequestedLatencyMode GUARDED_BY(mMutex) = AUDIO_LATENCY_MODE_FREE;
566 
567     /** string to latency mode map used to parse bluetooth.core.le.dsa_transport_preference */
568     static const std::map<std::string, audio_latency_mode_t> sStringToLatencyModeMap;
569     static const std::vector<const char*> sHeadPoseKeys;
570 
571     // Local log for command messages.
572     static constexpr int mMaxLocalLogLine = 10;
573     SimpleLog mLocalLog{mMaxLocalLogLine};
574 
575     /**
576      * @brief Calculate and record sensor data.
577      * Dump to local log with max/average pose angle every mPoseRecordThreshold.
578      */
579     // Record one log line per second (up to mMaxLocalLogLine) to capture most recent sensor data.
GUARDED_BY(mMutex)580     media::VectorRecorder mPoseRecorder GUARDED_BY(mMutex) {
581         6 /* vectorSize */, std::chrono::seconds(1), mMaxLocalLogLine, { 3 } /* delimiterIdx */};
582     // Record one log line per minute (up to mMaxLocalLogLine) to capture durable sensor data.
GUARDED_BY(mMutex)583     media::VectorRecorder mPoseDurableRecorder GUARDED_BY(mMutex) {
584         6 /* vectorSize */, std::chrono::minutes(1), mMaxLocalLogLine, { 3 } /* delimiterIdx */};
585 };  // Spatializer
586 
587 }; // namespace android
588 
589 #endif // ANDROID_MEDIA_SPATIALIZER_H
590