blob: bc95fe43108e494b6adcb3a4ec49506afc78d2ea [file] [log] [blame]
Eric Laurent6d607012021-07-05 11:54:40 +02001/*
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/media/BnEffect.h>
21#include <android/media/BnSpatializer.h>
Eric Laurent6d607012021-07-05 11:54:40 +020022#include <android/media/SpatializationLevel.h>
Eric Laurent2be8b292021-08-23 09:44:33 -070023#include <android/media/SpatializationMode.h>
24#include <android/media/SpatializerHeadTrackingMode.h>
Eric Laurent2be8b292021-08-23 09:44:33 -070025#include <media/audiohal/EffectHalInterface.h>
Eric Laurent8a4259f2021-09-14 16:04:00 +020026#include <media/stagefright/foundation/ALooper.h>
Eric Laurent6d607012021-07-05 11:54:40 +020027#include <media/AudioEffect.h>
Eric Laurent1c5e2e32021-08-18 18:50:28 +020028#include <system/audio_effects/effect_spatializer.h>
Eric Laurent6d607012021-07-05 11:54:40 +020029
Eric Laurent2be8b292021-08-23 09:44:33 -070030#include "SpatializerPoseController.h"
Eric Laurent6d607012021-07-05 11:54:40 +020031
32namespace android {
33
34
35// ----------------------------------------------------------------------------
36
37/**
38 * A callback interface from the Spatializer object or its parent AudioPolicyService.
39 * This is implemented by the audio policy service hosting the Spatializer to perform
40 * actions needed when a state change inside the Spatializer requires some audio system
41 * changes that cannot be performed by the Spatializer. For instance opening or closing a
42 * spatializer output stream when the spatializer is enabled or disabled
43 */
44class SpatializerPolicyCallback {
45public:
46 /** Called when a stage change occurs that requires the parent audio policy service to take
47 * some action.
48 */
49 virtual void onCheckSpatializer() = 0;
50
51 virtual ~SpatializerPolicyCallback() = default;
52};
53/**
54 * The Spatializer class implements all functional controlling the multichannel spatializer
55 * with head tracking implementation in the native audio service: audio policy and audio flinger.
56 * It presents an AIDL interface available to the java audio service to discover the availability
57 * of the feature and options, control its state and register an active head tracking sensor.
58 * It maintains the current state of the platform spatializer and applies the stored parameters
59 * when the spatializer engine is created and enabled.
60 * Based on the requested spatializer level, it will request the creation of a specialized output
61 * mixer to the audio policy service which will in turn notify the Spatializer of the output
62 * stream on which a spatializer engine should be created, configured and enabled.
63 * The spatializer also hosts the head tracking management logic. This logic receives the
64 * desired head tracking mode and selected head tracking sensor, registers a sensor event listener
65 * and derives the compounded head pose information to the spatializer engine.
66 *
67 * Workflow:
68 * - Initialization: when the audio policy service starts, it checks if a spatializer effect
69 * engine exists and if the audio policy manager reports a dedicated spatializer output profile.
70 * If both conditions are met, a Spatializer object is created
71 * - Capabilities discovery: AudioService will call AudioSystem::canBeSpatialized() and if true,
72 * acquire an ISpatializer interface with AudioSystem::getSpatializer(). This interface
73 * will be used to query the implementation capabilities and configure the spatializer.
74 * - Enabling: when ISpatializer::setLevel() sets a level different from NONE the spatializer
75 * is considered enabled. The audio policy callback onCheckSpatializer() is called. This
76 * triggers a request to audio policy manager to open a spatialization output stream and a
77 * spatializer mixer is created in audio flinger. When an output is returned by audio policy
78 * manager, Spatializer::attachOutput() is called which creates and enables the spatializer
79 * stage engine on the specified output.
80 * - Disabling: when the spatialization level is set to NONE, the spatializer is considered
81 * disabled. The audio policy callback onCheckSpatializer() is called. This triggers a call
82 * to Spatializer::detachOutput() and the spatializer engine is released. Then a request is
83 * made to audio policy manager to release and close the spatializer output stream and the
84 * spatializer mixer thread is destroyed.
85 */
Eric Laurent2be8b292021-08-23 09:44:33 -070086class Spatializer : public media::BnSpatializer,
Atneya Nair20e6cc82022-05-17 20:12:37 -040087 public AudioEffect::IAudioEffectCallback,
Eric Laurent2be8b292021-08-23 09:44:33 -070088 public IBinder::DeathRecipient,
Eric Laurentee398ad2022-05-03 18:19:35 +020089 private SpatializerPoseController::Listener,
90 public virtual AudioSystem::SupportedLatencyModesCallback {
Eric Laurent2be8b292021-08-23 09:44:33 -070091 public:
Eric Laurent6d607012021-07-05 11:54:40 +020092 static sp<Spatializer> create(SpatializerPolicyCallback *callback);
93
94 ~Spatializer() override;
95
Eric Laurent8a4259f2021-09-14 16:04:00 +020096 /** RefBase */
97 void onFirstRef();
98
Eric Laurent6d607012021-07-05 11:54:40 +020099 /** ISpatializer, see ISpatializer.aidl */
100 binder::Status release() override;
101 binder::Status getSupportedLevels(std::vector<media::SpatializationLevel>* levels) override;
102 binder::Status setLevel(media::SpatializationLevel level) override;
103 binder::Status getLevel(media::SpatializationLevel *level) override;
Eric Laurentc87402b2021-09-17 16:49:42 +0200104 binder::Status isHeadTrackingSupported(bool *supports);
Eric Laurent6d607012021-07-05 11:54:40 +0200105 binder::Status getSupportedHeadTrackingModes(
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700106 std::vector<media::SpatializerHeadTrackingMode>* modes) override;
107 binder::Status setDesiredHeadTrackingMode(
108 media::SpatializerHeadTrackingMode mode) override;
109 binder::Status getActualHeadTrackingMode(
110 media::SpatializerHeadTrackingMode* mode) override;
111 binder::Status recenterHeadTracker() override;
Eric Laurent6d607012021-07-05 11:54:40 +0200112 binder::Status setGlobalTransform(const std::vector<float>& screenToStage) override;
Eric Laurent2be8b292021-08-23 09:44:33 -0700113 binder::Status setHeadSensor(int sensorHandle) override;
114 binder::Status setScreenSensor(int sensorHandle) override;
115 binder::Status setDisplayOrientation(float physicalToLogicalAngle) override;
116 binder::Status setHingeAngle(float hingeAngle) override;
117 binder::Status getSupportedModes(std::vector<media::SpatializationMode>* modes) override;
Eric Laurent67816e32021-09-16 15:18:40 +0200118 binder::Status registerHeadTrackingCallback(
119 const sp<media::ISpatializerHeadTrackingCallback>& callback) override;
Eric Laurentc87402b2021-09-17 16:49:42 +0200120 binder::Status setParameter(int key, const std::vector<unsigned char>& value) override;
121 binder::Status getParameter(int key, std::vector<unsigned char> *value) override;
122 binder::Status getOutput(int *output);
Eric Laurent6d607012021-07-05 11:54:40 +0200123
124 /** IBinder::DeathRecipient. Listen to the death of the INativeSpatializerCallback. */
125 virtual void binderDied(const wp<IBinder>& who);
126
Eric Laurentee398ad2022-05-03 18:19:35 +0200127 /** SupportedLatencyModesCallback */
128 void onSupportedLatencyModesChanged(
129 audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) override;
130
Eric Laurent6d607012021-07-05 11:54:40 +0200131 /** Registers a INativeSpatializerCallback when a client is attached to this Spatializer
132 * by audio policy service.
133 */
134 status_t registerCallback(const sp<media::INativeSpatializerCallback>& callback);
135
Eric Laurent2be8b292021-08-23 09:44:33 -0700136 status_t loadEngineConfiguration(sp<EffectHalInterface> effect);
137
Eric Laurent6d607012021-07-05 11:54:40 +0200138 /** Level getter for use by local classes. */
Eric Laurent2be8b292021-08-23 09:44:33 -0700139 media::SpatializationLevel getLevel() const { std::lock_guard lock(mLock); return mLevel; }
Eric Laurent6d607012021-07-05 11:54:40 +0200140
141 /** Called by audio policy service when the special output mixer dedicated to spatialization
142 * is opened and the spatializer engine must be created.
143 */
Eric Laurent15903592022-02-24 20:44:36 +0100144 status_t attachOutput(audio_io_handle_t output, size_t numActiveTracks);
Eric Laurent6d607012021-07-05 11:54:40 +0200145 /** Called by audio policy service when the special output mixer dedicated to spatialization
146 * is closed and the spatializer engine must be release.
147 */
148 audio_io_handle_t detachOutput();
149 /** Returns the output stream the spatializer is attached to. */
Eric Laurent2be8b292021-08-23 09:44:33 -0700150 audio_io_handle_t getOutput() const { std::lock_guard lock(mLock); return mOutput; }
Eric Laurent6d607012021-07-05 11:54:40 +0200151
Eric Laurent15903592022-02-24 20:44:36 +0100152 void updateActiveTracks(size_t numActiveTracks);
153
Eric Laurent6d607012021-07-05 11:54:40 +0200154 /** Gets the channel mask, sampling rate and format set for the spatializer input. */
Eric Laurent2be8b292021-08-23 09:44:33 -0700155 audio_config_base_t getAudioInConfig() const;
Eric Laurent6d607012021-07-05 11:54:40 +0200156
Eric Laurent8a4259f2021-09-14 16:04:00 +0200157 void calculateHeadPose();
158
Eric Laurent6d607012021-07-05 11:54:40 +0200159private:
Eric Laurent6d607012021-07-05 11:54:40 +0200160 Spatializer(effect_descriptor_t engineDescriptor,
161 SpatializerPolicyCallback *callback);
162
Eric Laurent6d607012021-07-05 11:54:40 +0200163 static void engineCallback(int32_t event, void* user, void *info);
164
Eric Laurent2be8b292021-08-23 09:44:33 -0700165 // From VirtualizerStageController::Listener
166 void onHeadToStagePose(const media::Pose3f& headToStage) override;
167 void onActualModeChange(media::HeadTrackingMode mode) override;
168
Eric Laurent8a4259f2021-09-14 16:04:00 +0200169 void onHeadToStagePoseMsg(const std::vector<float>& headToStage);
170 void onActualModeChangeMsg(media::HeadTrackingMode mode);
Eric Laurent9c04de92022-07-20 13:49:47 +0200171 void onSupportedLatencyModesChangedMsg(
172 audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes);
Eric Laurent8a4259f2021-09-14 16:04:00 +0200173
Eric Laurent2be8b292021-08-23 09:44:33 -0700174 static constexpr int kMaxEffectParamValues = 10;
175 /**
176 * Get a parameter from spatializer engine by calling the effect HAL command method directly.
177 * To be used when the engine instance mEngine is not yet created in the effect framework.
178 * When MULTI_VALUES is false, the expected reply is only one value of type T.
179 * When MULTI_VALUES is true, the expected reply is made of a number (of type T) indicating
180 * how many values are returned, followed by this number for values of type T.
181 */
182 template<bool MULTI_VALUES, typename T>
183 status_t getHalParameter(sp<EffectHalInterface> effect, uint32_t type,
184 std::vector<T> *values) {
185 static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
186
187 uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1];
188 uint32_t reply[sizeof(effect_param_t) / sizeof(uint32_t) + 2 + kMaxEffectParamValues];
189
190 effect_param_t *p = (effect_param_t *)cmd;
191 p->psize = sizeof(uint32_t);
192 if (MULTI_VALUES) {
193 p->vsize = (kMaxEffectParamValues + 1) * sizeof(T);
194 } else {
195 p->vsize = sizeof(T);
196 }
197 *(uint32_t *)p->data = type;
198 uint32_t replySize = sizeof(effect_param_t) + p->psize + p->vsize;
199
200 status_t status = effect->command(EFFECT_CMD_GET_PARAM,
201 sizeof(effect_param_t) + sizeof(uint32_t), cmd,
202 &replySize, reply);
203 if (status != NO_ERROR) {
204 return status;
205 }
206 if (p->status != NO_ERROR) {
207 return p->status;
208 }
209 if (replySize <
210 sizeof(effect_param_t) + sizeof(uint32_t) + (MULTI_VALUES ? 2 : 1) * sizeof(T)) {
211 return BAD_VALUE;
212 }
213
214 T *params = (T *)((uint8_t *)reply + sizeof(effect_param_t) + sizeof(uint32_t));
215 int numParams = 1;
216 if (MULTI_VALUES) {
217 numParams = (int)*params++;
218 }
219 if (numParams > kMaxEffectParamValues) {
220 return BAD_VALUE;
221 }
Eric Laurentc87402b2021-09-17 16:49:42 +0200222 (*values).clear();
Eric Laurent2be8b292021-08-23 09:44:33 -0700223 std::copy(&params[0], &params[numParams], back_inserter(*values));
224 return NO_ERROR;
225 }
226
227 /**
228 * Set a parameter to spatializer engine by calling setParameter on mEngine AudioEffect object.
229 * It is possible to pass more than one value of type T according to the parameter type
230 * according to values vector size.
231 */
232 template<typename T>
233 status_t setEffectParameter_l(uint32_t type, const std::vector<T>& values) REQUIRES(mLock) {
234 static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
235
236 uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values.size()];
237 effect_param_t *p = (effect_param_t *)cmd;
238 p->psize = sizeof(uint32_t);
239 p->vsize = sizeof(T) * values.size();
240 *(uint32_t *)p->data = type;
241 memcpy((uint32_t *)p->data + 1, values.data(), sizeof(T) * values.size());
242
Eric Laurentc87402b2021-09-17 16:49:42 +0200243 status_t status = mEngine->setParameter(p);
244 if (status != NO_ERROR) {
245 return status;
246 }
247 if (p->status != NO_ERROR) {
248 return p->status;
249 }
250 return NO_ERROR;
251 }
252
253 /**
254 * Get a parameter from spatializer engine by calling getParameter on AudioEffect object.
255 * It is possible to read more than one value of type T according to the parameter type
256 * by specifying values vector size.
257 */
258 template<typename T>
259 status_t getEffectParameter_l(uint32_t type, std::vector<T> *values) REQUIRES(mLock) {
260 static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
261
262 uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values->size()];
263 effect_param_t *p = (effect_param_t *)cmd;
264 p->psize = sizeof(uint32_t);
265 p->vsize = sizeof(T) * values->size();
266 *(uint32_t *)p->data = type;
267
268 status_t status = mEngine->getParameter(p);
269
270 if (status != NO_ERROR) {
271 return status;
272 }
273 if (p->status != NO_ERROR) {
274 return p->status;
275 }
276
277 int numValues = std::min(p->vsize / sizeof(T), values->size());
278 (*values).clear();
279 T *retValues = (T *)((uint8_t *)p->data + sizeof(uint32_t));
280 std::copy(&retValues[0], &retValues[numValues], back_inserter(*values));
281
282 return NO_ERROR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700283 }
284
Atneya Nair20e6cc82022-05-17 20:12:37 -0400285 virtual void onFramesProcessed(int32_t framesProcessed) override;
Eric Laurent8a4259f2021-09-14 16:04:00 +0200286
Eric Laurent9249d342022-03-18 11:55:56 +0100287 /**
288 * Checks if head and screen sensors must be actively monitored based on
289 * spatializer state and playback activity and configures the pose controller
290 * accordingly.
291 */
292 void checkSensorsState_l() REQUIRES(mLock);
Eric Laurent15903592022-02-24 20:44:36 +0100293
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200294 /**
Eric Laurent11094172022-04-05 18:27:42 +0200295 * Checks if the head pose controller should be created or destroyed according
296 * to desired head tracking mode.
297 */
298 void checkPoseController_l() REQUIRES(mLock);
299
300 /**
Eric Laurent7ea0d1b2022-04-01 14:23:44 +0200301 * Checks if the spatializer effect should be enabled based on
302 * playback activity and requested level.
303 */
304 void checkEngineState_l() REQUIRES(mLock);
305
Eric Laurent6d607012021-07-05 11:54:40 +0200306 /** Effect engine descriptor */
307 const effect_descriptor_t mEngineDescriptor;
308 /** Callback interface to parent audio policy service */
Andy Hunga461a002022-05-17 10:36:02 -0700309 SpatializerPolicyCallback* const mPolicyCallback;
310
311 /** Currently there is only one version of the spatializer running */
312 const std::string mMetricsId = AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER "0";
Eric Laurent6d607012021-07-05 11:54:40 +0200313
314 /** Mutex protecting internal state */
Eric Laurent2be8b292021-08-23 09:44:33 -0700315 mutable std::mutex mLock;
Eric Laurent6d607012021-07-05 11:54:40 +0200316
317 /** Client AudioEffect for the engine */
318 sp<AudioEffect> mEngine GUARDED_BY(mLock);
319 /** Output stream the spatializer mixer thread is attached to */
320 audio_io_handle_t mOutput GUARDED_BY(mLock) = AUDIO_IO_HANDLE_NONE;
Eric Laurent6d607012021-07-05 11:54:40 +0200321
322 /** Callback interface to the client (AudioService) controlling this`Spatializer */
323 sp<media::INativeSpatializerCallback> mSpatializerCallback GUARDED_BY(mLock);
324
Eric Laurent67816e32021-09-16 15:18:40 +0200325 /** Callback interface for head tracking */
326 sp<media::ISpatializerHeadTrackingCallback> mHeadTrackingCallback GUARDED_BY(mLock);
327
Eric Laurent6d607012021-07-05 11:54:40 +0200328 /** Requested spatialization level */
329 media::SpatializationLevel mLevel GUARDED_BY(mLock) = media::SpatializationLevel::NONE;
Eric Laurent6d607012021-07-05 11:54:40 +0200330
Eric Laurent2be8b292021-08-23 09:44:33 -0700331 /** Control logic for head-tracking, etc. */
332 std::shared_ptr<SpatializerPoseController> mPoseController GUARDED_BY(mLock);
333
334 /** Last requested head tracking mode */
335 media::HeadTrackingMode mDesiredHeadTrackingMode GUARDED_BY(mLock)
336 = media::HeadTrackingMode::STATIC;
337
338 /** Last-reported actual head-tracking mode. */
339 media::SpatializerHeadTrackingMode mActualHeadTrackingMode GUARDED_BY(mLock)
340 = media::SpatializerHeadTrackingMode::DISABLED;
341
342 /** Selected Head pose sensor */
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700343 int32_t mHeadSensor GUARDED_BY(mLock) = SpatializerPoseController::INVALID_SENSOR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700344
345 /** Selected Screen pose sensor */
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700346 int32_t mScreenSensor GUARDED_BY(mLock) = SpatializerPoseController::INVALID_SENSOR;
Eric Laurent2be8b292021-08-23 09:44:33 -0700347
348 /** Last display orientation received */
349 static constexpr float kDisplayOrientationInvalid = 1000;
350 float mDisplayOrientation GUARDED_BY(mLock) = kDisplayOrientationInvalid;
351
352 std::vector<media::SpatializationLevel> mLevels;
Andy Hunga461a002022-05-17 10:36:02 -0700353 std::vector<media::SpatializerHeadTrackingMode> mHeadTrackingModes;
Eric Laurent2be8b292021-08-23 09:44:33 -0700354 std::vector<media::SpatializationMode> mSpatializationModes;
355 std::vector<audio_channel_mask_t> mChannelMasks;
356 bool mSupportsHeadTracking;
Eric Laurent8a4259f2021-09-14 16:04:00 +0200357
358 // Looper thread for mEngine callbacks
359 class EngineCallbackHandler;
360
361 sp<ALooper> mLooper;
362 sp<EngineCallbackHandler> mHandler;
363
Eric Laurent15903592022-02-24 20:44:36 +0100364 size_t mNumActiveTracks GUARDED_BY(mLock) = 0;
Eric Laurentee398ad2022-05-03 18:19:35 +0200365 std::vector<audio_latency_mode_t> mSupportedLatencyModes GUARDED_BY(mLock);
Eric Laurent15903592022-02-24 20:44:36 +0100366
Eric Laurent8a4259f2021-09-14 16:04:00 +0200367 static const std::vector<const char *> sHeadPoseKeys;
Eric Laurent6d607012021-07-05 11:54:40 +0200368};
369
370
371}; // namespace android
372
373#endif // ANDROID_MEDIA_SPATIALIZER_H