blob: f0ab6058b977e38668919249f7b78c684a591662 [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>
22#include <android/media/HeadTrackingMode.h>
23#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(
96 std::vector<media::HeadTrackingMode>* modes) override;
97 binder::Status setDesiredHeadTrackingMode(media::HeadTrackingMode mode) override;
98 binder::Status getActualHeadTrackingMode(media::HeadTrackingMode *mode) override;
99 binder::Status recenterHeadtracker() override;
100 binder::Status setGlobalTransform(const std::vector<float>& screenToStage) override;
101
102 /** IBinder::DeathRecipient. Listen to the death of the INativeSpatializerCallback. */
103 virtual void binderDied(const wp<IBinder>& who);
104
105 /** Registers a INativeSpatializerCallback when a client is attached to this Spatializer
106 * by audio policy service.
107 */
108 status_t registerCallback(const sp<media::INativeSpatializerCallback>& callback);
109
110 /** Level getter for use by local classes. */
111 media::SpatializationLevel getLevel() const { Mutex::Autolock _l(mLock); return mLevel; }
112
113 /** Called by audio policy service when the special output mixer dedicated to spatialization
114 * is opened and the spatializer engine must be created.
115 */
116 status_t attachOutput(audio_io_handle_t output);
117 /** Called by audio policy service when the special output mixer dedicated to spatialization
118 * is closed and the spatializer engine must be release.
119 */
120 audio_io_handle_t detachOutput();
121 /** Returns the output stream the spatializer is attached to. */
122 audio_io_handle_t getOutput() const { Mutex::Autolock _l(mLock); return mOutput; }
123
124 /** Sets the channel mask, sampling rate and format for the spatializer input. */
125 void setAudioInConfig(const audio_config_base_t& config) {
126 Mutex::Autolock _l(mLock);
127 mAudioInConfig = config;
128 }
129
130 /** Gets the channel mask, sampling rate and format set for the spatializer input. */
131 audio_config_base_t getAudioInConfig() const {
132 Mutex::Autolock _l(mLock);
133 return mAudioInConfig;
134 }
135
136 /** An implementation of an IEffect interface that can be used to pass advanced parameters to
137 * the spatializer engine. All APis are noop (i.e. the interface cannot be used to control
138 * the effect) except for passing parameters via the command() API. */
139 class EffectClient: public android::media::BnEffect {
140 public:
141
142 EffectClient(const sp<media::IEffectClient>& effectClient,
143 Spatializer& parent);
144 virtual ~EffectClient();
145
146 // IEffect
147 android::binder::Status enable(int32_t* _aidl_return) override;
148 android::binder::Status disable(int32_t* _aidl_return) override;
149 android::binder::Status command(int32_t cmdCode,
150 const std::vector<uint8_t>& cmdData,
151 int32_t maxResponseSize,
152 std::vector<uint8_t>* response,
153 int32_t* _aidl_return) override;
154 android::binder::Status disconnect() override;
155 android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) override;
156
157 private:
158 const sp<media::IEffectClient> mEffectClient;
159 sp<IMemory> mCblkMemory;
160 const Spatializer& mParent;
161 bool mDisconnected = false;
162 };
163
164private:
165
166 Spatializer(effect_descriptor_t engineDescriptor,
167 SpatializerPolicyCallback *callback);
168
169
170 static void engineCallback(int32_t event, void* user, void *info);
171
172 /** Effect engine descriptor */
173 const effect_descriptor_t mEngineDescriptor;
174 /** Callback interface to parent audio policy service */
175 SpatializerPolicyCallback* mPolicyCallback;
176
177 /** Mutex protecting internal state */
178 mutable Mutex mLock;
179
180 /** Client AudioEffect for the engine */
181 sp<AudioEffect> mEngine GUARDED_BY(mLock);
182 /** Output stream the spatializer mixer thread is attached to */
183 audio_io_handle_t mOutput GUARDED_BY(mLock) = AUDIO_IO_HANDLE_NONE;
184 /** Virtualizer engine input configuration */
185 audio_config_base_t mAudioInConfig GUARDED_BY(mLock) = AUDIO_CONFIG_BASE_INITIALIZER;
186
187 /** Callback interface to the client (AudioService) controlling this`Spatializer */
188 sp<media::INativeSpatializerCallback> mSpatializerCallback GUARDED_BY(mLock);
189
190 /** Requested spatialization level */
191 media::SpatializationLevel mLevel GUARDED_BY(mLock) = media::SpatializationLevel::NONE;
192 /** Requested head tracking mode */
193 media::HeadTrackingMode mHeadTrackingMode GUARDED_BY(mLock)
194 = media::HeadTrackingMode::DISABLED;
195 /** Configured screen to stage transform */
196 std::vector<float> mScreenToStageTransform GUARDED_BY(mLock);
197
198 /** Extended IEffect interface is one has been created */
199 sp<EffectClient> mEffectClient GUARDED_BY(mLock);
200};
201
202
203}; // namespace android
204
205#endif // ANDROID_MEDIA_SPATIALIZER_H