blob: 768170a397cff7a913b35d1336d8c8c6250127c0 [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>
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070022#include <android/media/SpatializerHeadTrackingMode.h>
Eric Laurent6d607012021-07-05 11:54:40 +020023#include <android/media/SpatializationLevel.h>
24
25#include <media/AudioEffect.h>
Eric Laurent1c5e2e32021-08-18 18:50:28 +020026#include <system/audio_effects/effect_spatializer.h>
Eric Laurent6d607012021-07-05 11:54:40 +020027
28
29namespace android {
30
31
32// ----------------------------------------------------------------------------
33
34/**
35 * A callback interface from the Spatializer object or its parent AudioPolicyService.
36 * This is implemented by the audio policy service hosting the Spatializer to perform
37 * actions needed when a state change inside the Spatializer requires some audio system
38 * changes that cannot be performed by the Spatializer. For instance opening or closing a
39 * spatializer output stream when the spatializer is enabled or disabled
40 */
41class SpatializerPolicyCallback {
42public:
43 /** Called when a stage change occurs that requires the parent audio policy service to take
44 * some action.
45 */
46 virtual void onCheckSpatializer() = 0;
47
48 virtual ~SpatializerPolicyCallback() = default;
49};
50/**
51 * The Spatializer class implements all functional controlling the multichannel spatializer
52 * with head tracking implementation in the native audio service: audio policy and audio flinger.
53 * It presents an AIDL interface available to the java audio service to discover the availability
54 * of the feature and options, control its state and register an active head tracking sensor.
55 * It maintains the current state of the platform spatializer and applies the stored parameters
56 * when the spatializer engine is created and enabled.
57 * Based on the requested spatializer level, it will request the creation of a specialized output
58 * mixer to the audio policy service which will in turn notify the Spatializer of the output
59 * stream on which a spatializer engine should be created, configured and enabled.
60 * The spatializer also hosts the head tracking management logic. This logic receives the
61 * desired head tracking mode and selected head tracking sensor, registers a sensor event listener
62 * and derives the compounded head pose information to the spatializer engine.
63 *
64 * Workflow:
65 * - Initialization: when the audio policy service starts, it checks if a spatializer effect
66 * engine exists and if the audio policy manager reports a dedicated spatializer output profile.
67 * If both conditions are met, a Spatializer object is created
68 * - Capabilities discovery: AudioService will call AudioSystem::canBeSpatialized() and if true,
69 * acquire an ISpatializer interface with AudioSystem::getSpatializer(). This interface
70 * will be used to query the implementation capabilities and configure the spatializer.
71 * - Enabling: when ISpatializer::setLevel() sets a level different from NONE the spatializer
72 * is considered enabled. The audio policy callback onCheckSpatializer() is called. This
73 * triggers a request to audio policy manager to open a spatialization output stream and a
74 * spatializer mixer is created in audio flinger. When an output is returned by audio policy
75 * manager, Spatializer::attachOutput() is called which creates and enables the spatializer
76 * stage engine on the specified output.
77 * - Disabling: when the spatialization level is set to NONE, the spatializer is considered
78 * disabled. The audio policy callback onCheckSpatializer() is called. This triggers a call
79 * to Spatializer::detachOutput() and the spatializer engine is released. Then a request is
80 * made to audio policy manager to release and close the spatializer output stream and the
81 * spatializer mixer thread is destroyed.
82 */
83class Spatializer : public media::BnSpatializer, public IBinder::DeathRecipient {
84public:
85
86 static sp<Spatializer> create(SpatializerPolicyCallback *callback);
87
88 ~Spatializer() override;
89
90 /** ISpatializer, see ISpatializer.aidl */
91 binder::Status release() override;
92 binder::Status getSupportedLevels(std::vector<media::SpatializationLevel>* levels) override;
93 binder::Status setLevel(media::SpatializationLevel level) override;
94 binder::Status getLevel(media::SpatializationLevel *level) override;
95 binder::Status getSupportedHeadTrackingModes(
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -070096 std::vector<media::SpatializerHeadTrackingMode>* modes) override;
97 binder::Status setDesiredHeadTrackingMode(
98 media::SpatializerHeadTrackingMode mode) override;
99 binder::Status getActualHeadTrackingMode(
100 media::SpatializerHeadTrackingMode* mode) override;
101 binder::Status recenterHeadTracker() override;
Eric Laurent6d607012021-07-05 11:54:40 +0200102 binder::Status setGlobalTransform(const std::vector<float>& screenToStage) override;
103
104 /** IBinder::DeathRecipient. Listen to the death of the INativeSpatializerCallback. */
105 virtual void binderDied(const wp<IBinder>& who);
106
107 /** Registers a INativeSpatializerCallback when a client is attached to this Spatializer
108 * by audio policy service.
109 */
110 status_t registerCallback(const sp<media::INativeSpatializerCallback>& callback);
111
112 /** Level getter for use by local classes. */
113 media::SpatializationLevel getLevel() const { Mutex::Autolock _l(mLock); return mLevel; }
114
115 /** Called by audio policy service when the special output mixer dedicated to spatialization
116 * is opened and the spatializer engine must be created.
117 */
118 status_t attachOutput(audio_io_handle_t output);
119 /** Called by audio policy service when the special output mixer dedicated to spatialization
120 * is closed and the spatializer engine must be release.
121 */
122 audio_io_handle_t detachOutput();
123 /** Returns the output stream the spatializer is attached to. */
124 audio_io_handle_t getOutput() const { Mutex::Autolock _l(mLock); return mOutput; }
125
126 /** Sets the channel mask, sampling rate and format for the spatializer input. */
127 void setAudioInConfig(const audio_config_base_t& config) {
128 Mutex::Autolock _l(mLock);
129 mAudioInConfig = config;
130 }
131
132 /** Gets the channel mask, sampling rate and format set for the spatializer input. */
133 audio_config_base_t getAudioInConfig() const {
134 Mutex::Autolock _l(mLock);
135 return mAudioInConfig;
136 }
137
138 /** An implementation of an IEffect interface that can be used to pass advanced parameters to
139 * the spatializer engine. All APis are noop (i.e. the interface cannot be used to control
140 * the effect) except for passing parameters via the command() API. */
141 class EffectClient: public android::media::BnEffect {
142 public:
143
144 EffectClient(const sp<media::IEffectClient>& effectClient,
145 Spatializer& parent);
146 virtual ~EffectClient();
147
148 // IEffect
149 android::binder::Status enable(int32_t* _aidl_return) override;
150 android::binder::Status disable(int32_t* _aidl_return) override;
151 android::binder::Status command(int32_t cmdCode,
152 const std::vector<uint8_t>& cmdData,
153 int32_t maxResponseSize,
154 std::vector<uint8_t>* response,
155 int32_t* _aidl_return) override;
156 android::binder::Status disconnect() override;
157 android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) override;
158
159 private:
160 const sp<media::IEffectClient> mEffectClient;
161 sp<IMemory> mCblkMemory;
162 const Spatializer& mParent;
163 bool mDisconnected = false;
164 };
165
166private:
167
168 Spatializer(effect_descriptor_t engineDescriptor,
169 SpatializerPolicyCallback *callback);
170
171
172 static void engineCallback(int32_t event, void* user, void *info);
173
174 /** Effect engine descriptor */
175 const effect_descriptor_t mEngineDescriptor;
176 /** Callback interface to parent audio policy service */
177 SpatializerPolicyCallback* mPolicyCallback;
178
179 /** Mutex protecting internal state */
180 mutable Mutex mLock;
181
182 /** Client AudioEffect for the engine */
183 sp<AudioEffect> mEngine GUARDED_BY(mLock);
184 /** Output stream the spatializer mixer thread is attached to */
185 audio_io_handle_t mOutput GUARDED_BY(mLock) = AUDIO_IO_HANDLE_NONE;
186 /** Virtualizer engine input configuration */
187 audio_config_base_t mAudioInConfig GUARDED_BY(mLock) = AUDIO_CONFIG_BASE_INITIALIZER;
188
189 /** Callback interface to the client (AudioService) controlling this`Spatializer */
190 sp<media::INativeSpatializerCallback> mSpatializerCallback GUARDED_BY(mLock);
191
192 /** Requested spatialization level */
193 media::SpatializationLevel mLevel GUARDED_BY(mLock) = media::SpatializationLevel::NONE;
194 /** Requested head tracking mode */
Ytai Ben-Tsvia16a9df2021-08-05 08:57:06 -0700195 media::SpatializerHeadTrackingMode mHeadTrackingMode GUARDED_BY(mLock)
196 = media::SpatializerHeadTrackingMode::DISABLED;
Eric Laurent6d607012021-07-05 11:54:40 +0200197 /** Configured screen to stage transform */
198 std::vector<float> mScreenToStageTransform GUARDED_BY(mLock);
199
200 /** Extended IEffect interface is one has been created */
201 sp<EffectClient> mEffectClient GUARDED_BY(mLock);
202};
203
204
205}; // namespace android
206
207#endif // ANDROID_MEDIA_SPATIALIZER_H