1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker **
3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2021, The Android Open Source Project
4*ec779b8eSAndroid Build Coastguard Worker **
5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*ec779b8eSAndroid Build Coastguard Worker **
9*ec779b8eSAndroid Build Coastguard Worker ** http://www.apache.org/licenses/LICENSE-2.0
10*ec779b8eSAndroid Build Coastguard Worker **
11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License.
16*ec779b8eSAndroid Build Coastguard Worker */
17*ec779b8eSAndroid Build Coastguard Worker
18*ec779b8eSAndroid Build Coastguard Worker #include <string>
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "Spatializer"
20*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
21*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
22*ec779b8eSAndroid Build Coastguard Worker
23*ec779b8eSAndroid Build Coastguard Worker #include <algorithm>
24*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <limits.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <stdint.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h>
28*ec779b8eSAndroid Build Coastguard Worker
29*ec779b8eSAndroid Build Coastguard Worker #include <android/content/AttributionSourceState.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <android/sysprop/BluetoothProperties.sysprop.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/fixedfft.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <cutils/bitops.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <hardware/sensors.h>
34*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AHandler.h>
35*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AMessage.h>
36*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaMetricsItem.h>
37*ec779b8eSAndroid Build Coastguard Worker #include <media/QuaternionUtil.h>
38*ec779b8eSAndroid Build Coastguard Worker #include <media/ShmemCompat.h>
39*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/SchedulingPolicyService.h>
40*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/ServiceUtilities.h>
41*ec779b8eSAndroid Build Coastguard Worker #include <utils/Thread.h>
42*ec779b8eSAndroid Build Coastguard Worker
43*ec779b8eSAndroid Build Coastguard Worker #include "Spatializer.h"
44*ec779b8eSAndroid Build Coastguard Worker #include "SpatializerHelper.h"
45*ec779b8eSAndroid Build Coastguard Worker
46*ec779b8eSAndroid Build Coastguard Worker namespace android {
47*ec779b8eSAndroid Build Coastguard Worker
48*ec779b8eSAndroid Build Coastguard Worker using aidl_utils::binderStatusFromStatusT;
49*ec779b8eSAndroid Build Coastguard Worker using aidl_utils::statusTFromBinderStatus;
50*ec779b8eSAndroid Build Coastguard Worker using android::content::AttributionSourceState;
51*ec779b8eSAndroid Build Coastguard Worker using binder::Status;
52*ec779b8eSAndroid Build Coastguard Worker using internal::ToString;
53*ec779b8eSAndroid Build Coastguard Worker using media::HeadTrackingMode;
54*ec779b8eSAndroid Build Coastguard Worker using media::Pose3f;
55*ec779b8eSAndroid Build Coastguard Worker using media::SensorPoseProvider;
56*ec779b8eSAndroid Build Coastguard Worker using media::audio::common::HeadTracking;
57*ec779b8eSAndroid Build Coastguard Worker using media::audio::common::Spatialization;
58*ec779b8eSAndroid Build Coastguard Worker
59*ec779b8eSAndroid Build Coastguard Worker using namespace std::chrono_literals;
60*ec779b8eSAndroid Build Coastguard Worker
61*ec779b8eSAndroid Build Coastguard Worker #define VALUE_OR_RETURN_BINDER_STATUS(x) \
62*ec779b8eSAndroid Build Coastguard Worker ({ auto _tmp = (x); \
63*ec779b8eSAndroid Build Coastguard Worker if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
64*ec779b8eSAndroid Build Coastguard Worker std::move(_tmp.value()); })
65*ec779b8eSAndroid Build Coastguard Worker
getMaxChannelMask(const std::vector<audio_channel_mask_t> & masks,size_t channelLimit=SIZE_MAX)66*ec779b8eSAndroid Build Coastguard Worker static audio_channel_mask_t getMaxChannelMask(
67*ec779b8eSAndroid Build Coastguard Worker const std::vector<audio_channel_mask_t>& masks, size_t channelLimit = SIZE_MAX) {
68*ec779b8eSAndroid Build Coastguard Worker uint32_t maxCount = 0;
69*ec779b8eSAndroid Build Coastguard Worker audio_channel_mask_t maxMask = AUDIO_CHANNEL_NONE;
70*ec779b8eSAndroid Build Coastguard Worker for (auto mask : masks) {
71*ec779b8eSAndroid Build Coastguard Worker const size_t count = audio_channel_count_from_out_mask(mask);
72*ec779b8eSAndroid Build Coastguard Worker if (count > channelLimit) continue; // ignore masks greater than channelLimit
73*ec779b8eSAndroid Build Coastguard Worker if (count > maxCount) {
74*ec779b8eSAndroid Build Coastguard Worker maxMask = mask;
75*ec779b8eSAndroid Build Coastguard Worker maxCount = count;
76*ec779b8eSAndroid Build Coastguard Worker }
77*ec779b8eSAndroid Build Coastguard Worker }
78*ec779b8eSAndroid Build Coastguard Worker return maxMask;
79*ec779b8eSAndroid Build Coastguard Worker }
80*ec779b8eSAndroid Build Coastguard Worker
recordFromTranslationRotationVector(const std::vector<float> & trVector)81*ec779b8eSAndroid Build Coastguard Worker static std::vector<float> recordFromTranslationRotationVector(
82*ec779b8eSAndroid Build Coastguard Worker const std::vector<float>& trVector) {
83*ec779b8eSAndroid Build Coastguard Worker auto headToStageOpt = Pose3f::fromVector(trVector);
84*ec779b8eSAndroid Build Coastguard Worker if (!headToStageOpt) return {};
85*ec779b8eSAndroid Build Coastguard Worker
86*ec779b8eSAndroid Build Coastguard Worker const auto stageToHead = headToStageOpt.value().inverse();
87*ec779b8eSAndroid Build Coastguard Worker const auto stageToHeadTranslation = stageToHead.translation();
88*ec779b8eSAndroid Build Coastguard Worker constexpr float RAD_TO_DEGREE = 180.f / M_PI;
89*ec779b8eSAndroid Build Coastguard Worker std::vector<float> record{
90*ec779b8eSAndroid Build Coastguard Worker stageToHeadTranslation[0], stageToHeadTranslation[1], stageToHeadTranslation[2],
91*ec779b8eSAndroid Build Coastguard Worker 0.f, 0.f, 0.f};
92*ec779b8eSAndroid Build Coastguard Worker media::quaternionToAngles(stageToHead.rotation(), &record[3], &record[4], &record[5]);
93*ec779b8eSAndroid Build Coastguard Worker record[3] *= RAD_TO_DEGREE;
94*ec779b8eSAndroid Build Coastguard Worker record[4] *= RAD_TO_DEGREE;
95*ec779b8eSAndroid Build Coastguard Worker record[5] *= RAD_TO_DEGREE;
96*ec779b8eSAndroid Build Coastguard Worker return record;
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker
99*ec779b8eSAndroid Build Coastguard Worker template<typename T>
safe_clamp(const T & value,const T & low,const T & high)100*ec779b8eSAndroid Build Coastguard Worker static constexpr const T& safe_clamp(const T& value, const T& low, const T& high) {
101*ec779b8eSAndroid Build Coastguard Worker if constexpr (std::is_floating_point_v<T>) {
102*ec779b8eSAndroid Build Coastguard Worker return value != value /* constexpr isnan */
103*ec779b8eSAndroid Build Coastguard Worker ? low : std::clamp(value, low, high);
104*ec779b8eSAndroid Build Coastguard Worker } else /* constexpr */ {
105*ec779b8eSAndroid Build Coastguard Worker return std::clamp(value, low, high);
106*ec779b8eSAndroid Build Coastguard Worker }
107*ec779b8eSAndroid Build Coastguard Worker }
108*ec779b8eSAndroid Build Coastguard Worker
109*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------
110*ec779b8eSAndroid Build Coastguard Worker
111*ec779b8eSAndroid Build Coastguard Worker class Spatializer::EngineCallbackHandler : public AHandler {
112*ec779b8eSAndroid Build Coastguard Worker public:
EngineCallbackHandler(wp<Spatializer> spatializer)113*ec779b8eSAndroid Build Coastguard Worker EngineCallbackHandler(wp<Spatializer> spatializer)
114*ec779b8eSAndroid Build Coastguard Worker : mSpatializer(spatializer) {
115*ec779b8eSAndroid Build Coastguard Worker }
116*ec779b8eSAndroid Build Coastguard Worker
117*ec779b8eSAndroid Build Coastguard Worker enum {
118*ec779b8eSAndroid Build Coastguard Worker // Device state callbacks
119*ec779b8eSAndroid Build Coastguard Worker kWhatOnFramesProcessed, // AudioEffect::EVENT_FRAMES_PROCESSED
120*ec779b8eSAndroid Build Coastguard Worker kWhatOnHeadToStagePose, // SpatializerPoseController::Listener::onHeadToStagePose
121*ec779b8eSAndroid Build Coastguard Worker kWhatOnActualModeChange, // SpatializerPoseController::Listener::onActualModeChange
122*ec779b8eSAndroid Build Coastguard Worker kWhatOnLatencyModesChanged, // Spatializer::onSupportedLatencyModesChanged
123*ec779b8eSAndroid Build Coastguard Worker };
124*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kNumFramesKey = "numFrames";
125*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kModeKey = "mode";
126*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kTranslation0Key = "translation0";
127*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kTranslation1Key = "translation1";
128*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kTranslation2Key = "translation2";
129*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kRotation0Key = "rotation0";
130*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kRotation1Key = "rotation1";
131*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kRotation2Key = "rotation2";
132*ec779b8eSAndroid Build Coastguard Worker static constexpr const char *kLatencyModesKey = "latencyModes";
133*ec779b8eSAndroid Build Coastguard Worker
134*ec779b8eSAndroid Build Coastguard Worker class LatencyModes : public RefBase {
135*ec779b8eSAndroid Build Coastguard Worker public:
LatencyModes(audio_io_handle_t output,const std::vector<audio_latency_mode_t> & latencyModes)136*ec779b8eSAndroid Build Coastguard Worker LatencyModes(audio_io_handle_t output,
137*ec779b8eSAndroid Build Coastguard Worker const std::vector<audio_latency_mode_t>& latencyModes)
138*ec779b8eSAndroid Build Coastguard Worker : mOutput(output), mLatencyModes(latencyModes) {}
139*ec779b8eSAndroid Build Coastguard Worker ~LatencyModes() = default;
140*ec779b8eSAndroid Build Coastguard Worker
141*ec779b8eSAndroid Build Coastguard Worker audio_io_handle_t mOutput;
142*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_latency_mode_t> mLatencyModes;
143*ec779b8eSAndroid Build Coastguard Worker };
144*ec779b8eSAndroid Build Coastguard Worker
onMessageReceived(const sp<AMessage> & msg)145*ec779b8eSAndroid Build Coastguard Worker void onMessageReceived(const sp<AMessage> &msg) override {
146*ec779b8eSAndroid Build Coastguard Worker // No ALooper method to get the tid so update
147*ec779b8eSAndroid Build Coastguard Worker // Spatializer priority on the first message received.
148*ec779b8eSAndroid Build Coastguard Worker std::call_once(mPrioritySetFlag, [](){
149*ec779b8eSAndroid Build Coastguard Worker const pid_t pid = getpid();
150*ec779b8eSAndroid Build Coastguard Worker const pid_t tid = gettid();
151*ec779b8eSAndroid Build Coastguard Worker (void)requestSpatializerPriority(pid, tid);
152*ec779b8eSAndroid Build Coastguard Worker });
153*ec779b8eSAndroid Build Coastguard Worker
154*ec779b8eSAndroid Build Coastguard Worker sp<Spatializer> spatializer = mSpatializer.promote();
155*ec779b8eSAndroid Build Coastguard Worker if (spatializer == nullptr) {
156*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: Cannot promote spatializer", __func__);
157*ec779b8eSAndroid Build Coastguard Worker return;
158*ec779b8eSAndroid Build Coastguard Worker }
159*ec779b8eSAndroid Build Coastguard Worker switch (msg->what()) {
160*ec779b8eSAndroid Build Coastguard Worker case kWhatOnFramesProcessed: {
161*ec779b8eSAndroid Build Coastguard Worker int numFrames;
162*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt32(kNumFramesKey, &numFrames)) {
163*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Cannot find num frames!", __func__);
164*ec779b8eSAndroid Build Coastguard Worker return;
165*ec779b8eSAndroid Build Coastguard Worker }
166*ec779b8eSAndroid Build Coastguard Worker if (numFrames > 0) {
167*ec779b8eSAndroid Build Coastguard Worker spatializer->calculateHeadPose();
168*ec779b8eSAndroid Build Coastguard Worker }
169*ec779b8eSAndroid Build Coastguard Worker } break;
170*ec779b8eSAndroid Build Coastguard Worker case kWhatOnHeadToStagePose: {
171*ec779b8eSAndroid Build Coastguard Worker std::vector<float> headToStage(sHeadPoseKeys.size());
172*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
173*ec779b8eSAndroid Build Coastguard Worker if (!msg->findFloat(sHeadPoseKeys[i], &headToStage[i])) {
174*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Cannot find kTranslation0Key!", __func__);
175*ec779b8eSAndroid Build Coastguard Worker return;
176*ec779b8eSAndroid Build Coastguard Worker }
177*ec779b8eSAndroid Build Coastguard Worker }
178*ec779b8eSAndroid Build Coastguard Worker spatializer->onHeadToStagePoseMsg(headToStage);
179*ec779b8eSAndroid Build Coastguard Worker } break;
180*ec779b8eSAndroid Build Coastguard Worker case kWhatOnActualModeChange: {
181*ec779b8eSAndroid Build Coastguard Worker int mode;
182*ec779b8eSAndroid Build Coastguard Worker if (!msg->findInt32(kModeKey, &mode)) {
183*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Cannot find actualMode!", __func__);
184*ec779b8eSAndroid Build Coastguard Worker return;
185*ec779b8eSAndroid Build Coastguard Worker }
186*ec779b8eSAndroid Build Coastguard Worker spatializer->onActualModeChangeMsg(static_cast<HeadTrackingMode>(mode));
187*ec779b8eSAndroid Build Coastguard Worker } break;
188*ec779b8eSAndroid Build Coastguard Worker
189*ec779b8eSAndroid Build Coastguard Worker case kWhatOnLatencyModesChanged: {
190*ec779b8eSAndroid Build Coastguard Worker sp<RefBase> object;
191*ec779b8eSAndroid Build Coastguard Worker if (!msg->findObject(kLatencyModesKey, &object)) {
192*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Cannot find latency modes!", __func__);
193*ec779b8eSAndroid Build Coastguard Worker return;
194*ec779b8eSAndroid Build Coastguard Worker }
195*ec779b8eSAndroid Build Coastguard Worker sp<LatencyModes> latencyModes = static_cast<LatencyModes*>(object.get());
196*ec779b8eSAndroid Build Coastguard Worker spatializer->onSupportedLatencyModesChangedMsg(
197*ec779b8eSAndroid Build Coastguard Worker latencyModes->mOutput, std::move(latencyModes->mLatencyModes));
198*ec779b8eSAndroid Build Coastguard Worker } break;
199*ec779b8eSAndroid Build Coastguard Worker
200*ec779b8eSAndroid Build Coastguard Worker default:
201*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Invalid callback message %d", msg->what());
202*ec779b8eSAndroid Build Coastguard Worker }
203*ec779b8eSAndroid Build Coastguard Worker }
204*ec779b8eSAndroid Build Coastguard Worker private:
205*ec779b8eSAndroid Build Coastguard Worker wp<Spatializer> mSpatializer;
206*ec779b8eSAndroid Build Coastguard Worker std::once_flag mPrioritySetFlag;
207*ec779b8eSAndroid Build Coastguard Worker };
208*ec779b8eSAndroid Build Coastguard Worker
209*ec779b8eSAndroid Build Coastguard Worker const std::vector<const char *> Spatializer::sHeadPoseKeys = {
210*ec779b8eSAndroid Build Coastguard Worker Spatializer::EngineCallbackHandler::kTranslation0Key,
211*ec779b8eSAndroid Build Coastguard Worker Spatializer::EngineCallbackHandler::kTranslation1Key,
212*ec779b8eSAndroid Build Coastguard Worker Spatializer::EngineCallbackHandler::kTranslation2Key,
213*ec779b8eSAndroid Build Coastguard Worker Spatializer::EngineCallbackHandler::kRotation0Key,
214*ec779b8eSAndroid Build Coastguard Worker Spatializer::EngineCallbackHandler::kRotation1Key,
215*ec779b8eSAndroid Build Coastguard Worker Spatializer::EngineCallbackHandler::kRotation2Key,
216*ec779b8eSAndroid Build Coastguard Worker };
217*ec779b8eSAndroid Build Coastguard Worker
218*ec779b8eSAndroid Build Coastguard Worker // Mapping table between strings read form property bluetooth.core.le.dsa_transport_preference
219*ec779b8eSAndroid Build Coastguard Worker // and low latency modes emums.
220*ec779b8eSAndroid Build Coastguard Worker //TODO b/273373363: use AIDL enum when available
221*ec779b8eSAndroid Build Coastguard Worker const std::map<std::string, audio_latency_mode_t> Spatializer::sStringToLatencyModeMap = {
222*ec779b8eSAndroid Build Coastguard Worker {"le-acl", AUDIO_LATENCY_MODE_LOW},
223*ec779b8eSAndroid Build Coastguard Worker {"iso-sw", AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE},
224*ec779b8eSAndroid Build Coastguard Worker {"iso-hw", AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE},
225*ec779b8eSAndroid Build Coastguard Worker };
226*ec779b8eSAndroid Build Coastguard Worker
loadOrderedLowLatencyModes()227*ec779b8eSAndroid Build Coastguard Worker void Spatializer::loadOrderedLowLatencyModes() {
228*ec779b8eSAndroid Build Coastguard Worker if (!com::android::media::audio::dsa_over_bt_le_audio()) {
229*ec779b8eSAndroid Build Coastguard Worker return;
230*ec779b8eSAndroid Build Coastguard Worker }
231*ec779b8eSAndroid Build Coastguard Worker auto latencyModesStrs = android::sysprop::BluetoothProperties::dsa_transport_preference();
232*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
233*ec779b8eSAndroid Build Coastguard Worker // First load preferred low latency modes ordered from the property
234*ec779b8eSAndroid Build Coastguard Worker for (auto str : latencyModesStrs) {
235*ec779b8eSAndroid Build Coastguard Worker if (!str.has_value()) continue;
236*ec779b8eSAndroid Build Coastguard Worker if (auto it = sStringToLatencyModeMap.find(str.value());
237*ec779b8eSAndroid Build Coastguard Worker it != sStringToLatencyModeMap.end()) {
238*ec779b8eSAndroid Build Coastguard Worker mOrderedLowLatencyModes.push_back(it->second);
239*ec779b8eSAndroid Build Coastguard Worker }
240*ec779b8eSAndroid Build Coastguard Worker }
241*ec779b8eSAndroid Build Coastguard Worker // Then add unlisted latency modes at the end of the ordered list
242*ec779b8eSAndroid Build Coastguard Worker for (auto it : sStringToLatencyModeMap) {
243*ec779b8eSAndroid Build Coastguard Worker if (std::find(mOrderedLowLatencyModes.begin(), mOrderedLowLatencyModes.end(), it.second)
244*ec779b8eSAndroid Build Coastguard Worker == mOrderedLowLatencyModes.end()) {
245*ec779b8eSAndroid Build Coastguard Worker mOrderedLowLatencyModes.push_back(it.second);
246*ec779b8eSAndroid Build Coastguard Worker }
247*ec779b8eSAndroid Build Coastguard Worker }
248*ec779b8eSAndroid Build Coastguard Worker }
249*ec779b8eSAndroid Build Coastguard Worker
250*ec779b8eSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------
create(SpatializerPolicyCallback * callback,const sp<EffectsFactoryHalInterface> & effectsFactoryHal)251*ec779b8eSAndroid Build Coastguard Worker sp<Spatializer> Spatializer::create(SpatializerPolicyCallback* callback,
252*ec779b8eSAndroid Build Coastguard Worker const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
253*ec779b8eSAndroid Build Coastguard Worker sp<Spatializer> spatializer;
254*ec779b8eSAndroid Build Coastguard Worker
255*ec779b8eSAndroid Build Coastguard Worker if (effectsFactoryHal == nullptr) {
256*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s failed to create effect factory interface", __func__);
257*ec779b8eSAndroid Build Coastguard Worker return spatializer;
258*ec779b8eSAndroid Build Coastguard Worker }
259*ec779b8eSAndroid Build Coastguard Worker
260*ec779b8eSAndroid Build Coastguard Worker std::vector<effect_descriptor_t> descriptors;
261*ec779b8eSAndroid Build Coastguard Worker status_t status = effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
262*ec779b8eSAndroid Build Coastguard Worker if (status != NO_ERROR) {
263*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
264*ec779b8eSAndroid Build Coastguard Worker return spatializer;
265*ec779b8eSAndroid Build Coastguard Worker }
266*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT(!descriptors.empty(),
267*ec779b8eSAndroid Build Coastguard Worker "%s getDescriptors() returned no error but empty list", __func__);
268*ec779b8eSAndroid Build Coastguard Worker
269*ec779b8eSAndroid Build Coastguard Worker // TODO: get supported spatialization modes from FX engine or descriptor
270*ec779b8eSAndroid Build Coastguard Worker sp<EffectHalInterface> effect;
271*ec779b8eSAndroid Build Coastguard Worker status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE,
272*ec779b8eSAndroid Build Coastguard Worker AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect);
273*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s FX create status %d effect %p", __func__, status, effect.get());
274*ec779b8eSAndroid Build Coastguard Worker
275*ec779b8eSAndroid Build Coastguard Worker if (status == NO_ERROR && effect != nullptr) {
276*ec779b8eSAndroid Build Coastguard Worker spatializer = new Spatializer(descriptors[0], callback);
277*ec779b8eSAndroid Build Coastguard Worker if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) {
278*ec779b8eSAndroid Build Coastguard Worker spatializer.clear();
279*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s loadEngine error: %d effect %p", __func__, status, effect.get());
280*ec779b8eSAndroid Build Coastguard Worker } else {
281*ec779b8eSAndroid Build Coastguard Worker spatializer->loadOrderedLowLatencyModes();
282*ec779b8eSAndroid Build Coastguard Worker spatializer->mLocalLog.log("%s with effect Id %p", __func__, effect.get());
283*ec779b8eSAndroid Build Coastguard Worker }
284*ec779b8eSAndroid Build Coastguard Worker }
285*ec779b8eSAndroid Build Coastguard Worker
286*ec779b8eSAndroid Build Coastguard Worker return spatializer;
287*ec779b8eSAndroid Build Coastguard Worker }
288*ec779b8eSAndroid Build Coastguard Worker
Spatializer(effect_descriptor_t engineDescriptor,SpatializerPolicyCallback * callback)289*ec779b8eSAndroid Build Coastguard Worker Spatializer::Spatializer(effect_descriptor_t engineDescriptor, SpatializerPolicyCallback* callback)
290*ec779b8eSAndroid Build Coastguard Worker : mEngineDescriptor(engineDescriptor),
291*ec779b8eSAndroid Build Coastguard Worker mPolicyCallback(callback) {
292*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
293*ec779b8eSAndroid Build Coastguard Worker setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
294*ec779b8eSAndroid Build Coastguard Worker setInheritRt(true);
295*ec779b8eSAndroid Build Coastguard Worker }
296*ec779b8eSAndroid Build Coastguard Worker
onFirstRef()297*ec779b8eSAndroid Build Coastguard Worker void Spatializer::onFirstRef() {
298*ec779b8eSAndroid Build Coastguard Worker mLooper = new ALooper;
299*ec779b8eSAndroid Build Coastguard Worker mLooper->setName("Spatializer-looper");
300*ec779b8eSAndroid Build Coastguard Worker mLooper->start(
301*ec779b8eSAndroid Build Coastguard Worker /*runOnCallingThread*/false,
302*ec779b8eSAndroid Build Coastguard Worker /*canCallJava*/ false,
303*ec779b8eSAndroid Build Coastguard Worker PRIORITY_URGENT_AUDIO);
304*ec779b8eSAndroid Build Coastguard Worker
305*ec779b8eSAndroid Build Coastguard Worker mHandler = new EngineCallbackHandler(this);
306*ec779b8eSAndroid Build Coastguard Worker mLooper->registerHandler(mHandler);
307*ec779b8eSAndroid Build Coastguard Worker }
308*ec779b8eSAndroid Build Coastguard Worker
~Spatializer()309*ec779b8eSAndroid Build Coastguard Worker Spatializer::~Spatializer() {
310*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
311*ec779b8eSAndroid Build Coastguard Worker if (mLooper != nullptr) {
312*ec779b8eSAndroid Build Coastguard Worker mLooper->stop();
313*ec779b8eSAndroid Build Coastguard Worker mLooper->unregisterHandler(mHandler->id());
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker mLooper.clear();
316*ec779b8eSAndroid Build Coastguard Worker mHandler.clear();
317*ec779b8eSAndroid Build Coastguard Worker }
318*ec779b8eSAndroid Build Coastguard Worker
channelMaskVectorToString(const std::vector<audio_channel_mask_t> & masks)319*ec779b8eSAndroid Build Coastguard Worker static std::string channelMaskVectorToString(
320*ec779b8eSAndroid Build Coastguard Worker const std::vector<audio_channel_mask_t>& masks) {
321*ec779b8eSAndroid Build Coastguard Worker std::stringstream ss;
322*ec779b8eSAndroid Build Coastguard Worker for (const auto &mask : masks) {
323*ec779b8eSAndroid Build Coastguard Worker if (ss.tellp() != 0) ss << "|";
324*ec779b8eSAndroid Build Coastguard Worker ss << mask;
325*ec779b8eSAndroid Build Coastguard Worker }
326*ec779b8eSAndroid Build Coastguard Worker return ss.str();
327*ec779b8eSAndroid Build Coastguard Worker }
328*ec779b8eSAndroid Build Coastguard Worker
loadEngineConfiguration(sp<EffectHalInterface> effect)329*ec779b8eSAndroid Build Coastguard Worker status_t Spatializer::loadEngineConfiguration(sp<EffectHalInterface> effect) {
330*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
331*ec779b8eSAndroid Build Coastguard Worker
332*ec779b8eSAndroid Build Coastguard Worker std::vector<bool> supportsHeadTracking;
333*ec779b8eSAndroid Build Coastguard Worker status_t status = getHalParameter<false>(effect, SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED,
334*ec779b8eSAndroid Build Coastguard Worker &supportsHeadTracking);
335*ec779b8eSAndroid Build Coastguard Worker if (status != NO_ERROR) {
336*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: cannot get SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED", __func__);
337*ec779b8eSAndroid Build Coastguard Worker return status;
338*ec779b8eSAndroid Build Coastguard Worker }
339*ec779b8eSAndroid Build Coastguard Worker mSupportsHeadTracking = supportsHeadTracking[0];
340*ec779b8eSAndroid Build Coastguard Worker
341*ec779b8eSAndroid Build Coastguard Worker std::vector<Spatialization::Level> spatializationLevels;
342*ec779b8eSAndroid Build Coastguard Worker status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_LEVELS,
343*ec779b8eSAndroid Build Coastguard Worker &spatializationLevels);
344*ec779b8eSAndroid Build Coastguard Worker if (status != NO_ERROR) {
345*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_LEVELS", __func__);
346*ec779b8eSAndroid Build Coastguard Worker return status;
347*ec779b8eSAndroid Build Coastguard Worker }
348*ec779b8eSAndroid Build Coastguard Worker bool noneLevelFound = false;
349*ec779b8eSAndroid Build Coastguard Worker bool activeLevelFound = false;
350*ec779b8eSAndroid Build Coastguard Worker for (const auto spatializationLevel : spatializationLevels) {
351*ec779b8eSAndroid Build Coastguard Worker if (!aidl_utils::isValidEnum(spatializationLevel)) {
352*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: ignoring spatializationLevel:%s", __func__,
353*ec779b8eSAndroid Build Coastguard Worker ToString(spatializationLevel).c_str());
354*ec779b8eSAndroid Build Coastguard Worker continue;
355*ec779b8eSAndroid Build Coastguard Worker }
356*ec779b8eSAndroid Build Coastguard Worker if (spatializationLevel == Spatialization::Level::NONE) {
357*ec779b8eSAndroid Build Coastguard Worker noneLevelFound = true;
358*ec779b8eSAndroid Build Coastguard Worker } else {
359*ec779b8eSAndroid Build Coastguard Worker activeLevelFound = true;
360*ec779b8eSAndroid Build Coastguard Worker }
361*ec779b8eSAndroid Build Coastguard Worker // we don't detect duplicates.
362*ec779b8eSAndroid Build Coastguard Worker mLevels.emplace_back(spatializationLevel);
363*ec779b8eSAndroid Build Coastguard Worker }
364*ec779b8eSAndroid Build Coastguard Worker if (!noneLevelFound || !activeLevelFound) {
365*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_LEVELS must include NONE"
366*ec779b8eSAndroid Build Coastguard Worker " and another valid level", __func__);
367*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
368*ec779b8eSAndroid Build Coastguard Worker }
369*ec779b8eSAndroid Build Coastguard Worker
370*ec779b8eSAndroid Build Coastguard Worker std::vector<Spatialization::Mode> spatializationModes;
371*ec779b8eSAndroid Build Coastguard Worker status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
372*ec779b8eSAndroid Build Coastguard Worker &spatializationModes);
373*ec779b8eSAndroid Build Coastguard Worker if (status != NO_ERROR) {
374*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES", __func__);
375*ec779b8eSAndroid Build Coastguard Worker return status;
376*ec779b8eSAndroid Build Coastguard Worker }
377*ec779b8eSAndroid Build Coastguard Worker
378*ec779b8eSAndroid Build Coastguard Worker for (const auto spatializationMode : spatializationModes) {
379*ec779b8eSAndroid Build Coastguard Worker if (!aidl_utils::isValidEnum(spatializationMode)) {
380*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: ignoring spatializationMode:%s", __func__,
381*ec779b8eSAndroid Build Coastguard Worker ToString(spatializationMode).c_str());
382*ec779b8eSAndroid Build Coastguard Worker continue;
383*ec779b8eSAndroid Build Coastguard Worker }
384*ec779b8eSAndroid Build Coastguard Worker // we don't detect duplicates.
385*ec779b8eSAndroid Build Coastguard Worker mSpatializationModes.emplace_back(spatializationMode);
386*ec779b8eSAndroid Build Coastguard Worker }
387*ec779b8eSAndroid Build Coastguard Worker if (mSpatializationModes.empty()) {
388*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES reports empty", __func__);
389*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
390*ec779b8eSAndroid Build Coastguard Worker }
391*ec779b8eSAndroid Build Coastguard Worker
392*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_channel_mask_t> channelMasks;
393*ec779b8eSAndroid Build Coastguard Worker status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
394*ec779b8eSAndroid Build Coastguard Worker &channelMasks);
395*ec779b8eSAndroid Build Coastguard Worker if (status != NO_ERROR) {
396*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: cannot get SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS", __func__);
397*ec779b8eSAndroid Build Coastguard Worker return status;
398*ec779b8eSAndroid Build Coastguard Worker }
399*ec779b8eSAndroid Build Coastguard Worker for (const auto channelMask : channelMasks) {
400*ec779b8eSAndroid Build Coastguard Worker const bool channel_mask_spatialized =
401*ec779b8eSAndroid Build Coastguard Worker SpatializerHelper::isStereoSpatializationFeatureEnabled()
402*ec779b8eSAndroid Build Coastguard Worker ? audio_channel_mask_contains_stereo(channelMask)
403*ec779b8eSAndroid Build Coastguard Worker : audio_is_channel_mask_spatialized(channelMask);
404*ec779b8eSAndroid Build Coastguard Worker if (!channel_mask_spatialized) {
405*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
406*ec779b8eSAndroid Build Coastguard Worker continue;
407*ec779b8eSAndroid Build Coastguard Worker }
408*ec779b8eSAndroid Build Coastguard Worker // we don't detect duplicates.
409*ec779b8eSAndroid Build Coastguard Worker mChannelMasks.emplace_back(channelMask);
410*ec779b8eSAndroid Build Coastguard Worker }
411*ec779b8eSAndroid Build Coastguard Worker if (mChannelMasks.empty()) {
412*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS reports empty", __func__);
413*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
414*ec779b8eSAndroid Build Coastguard Worker }
415*ec779b8eSAndroid Build Coastguard Worker
416*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_channel_mask_t> spatializedChannelMasks;
417*ec779b8eSAndroid Build Coastguard Worker status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SPATIALIZED_CHANNEL_MASKS,
418*ec779b8eSAndroid Build Coastguard Worker &spatializedChannelMasks);
419*ec779b8eSAndroid Build Coastguard Worker if (status != NO_ERROR) {
420*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: cannot get SPATIALIZER_PARAM_SPATIALIZED_CHANNEL_MASKS", __func__);
421*ec779b8eSAndroid Build Coastguard Worker // do not return an error yet as spatializer implementations may not have been
422*ec779b8eSAndroid Build Coastguard Worker // updated yet to support this parameter
423*ec779b8eSAndroid Build Coastguard Worker }
424*ec779b8eSAndroid Build Coastguard Worker if (spatializedChannelMasks.empty()) {
425*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: SPATIALIZER_PARAM_SPATIALIZED_CHANNEL_MASKS reports empty", __func__);
426*ec779b8eSAndroid Build Coastguard Worker // do not return an error yet as spatializer implementations may not have been
427*ec779b8eSAndroid Build Coastguard Worker // updated yet to support this parameter
428*ec779b8eSAndroid Build Coastguard Worker }
429*ec779b8eSAndroid Build Coastguard Worker for (const audio_channel_mask_t spatializedMask : spatializedChannelMasks) {
430*ec779b8eSAndroid Build Coastguard Worker // spatialized masks must be contained in the supported input masks
431*ec779b8eSAndroid Build Coastguard Worker if (std::find(mChannelMasks.begin(), mChannelMasks.end(), spatializedMask)
432*ec779b8eSAndroid Build Coastguard Worker != mChannelMasks.end()) {
433*ec779b8eSAndroid Build Coastguard Worker mSpatializedChannelMasks.emplace_back(spatializedMask);
434*ec779b8eSAndroid Build Coastguard Worker } else {
435*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: spatialized mask %#x not in list reported by PARAM_SUPPORTED_CHANNEL_MASKS",
436*ec779b8eSAndroid Build Coastguard Worker __func__, spatializedMask);
437*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
438*ec779b8eSAndroid Build Coastguard Worker }
439*ec779b8eSAndroid Build Coastguard Worker }
440*ec779b8eSAndroid Build Coastguard Worker
441*ec779b8eSAndroid Build Coastguard Worker if (com::android::media::audio::dsa_over_bt_le_audio()
442*ec779b8eSAndroid Build Coastguard Worker && mSupportsHeadTracking) {
443*ec779b8eSAndroid Build Coastguard Worker mHeadtrackingConnectionMode = HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED;
444*ec779b8eSAndroid Build Coastguard Worker std::vector<HeadTracking::ConnectionMode> headtrackingConnectionModes;
445*ec779b8eSAndroid Build Coastguard Worker status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_HEADTRACKING_CONNECTION,
446*ec779b8eSAndroid Build Coastguard Worker &headtrackingConnectionModes);
447*ec779b8eSAndroid Build Coastguard Worker if (status == NO_ERROR) {
448*ec779b8eSAndroid Build Coastguard Worker for (const auto htConnectionMode : headtrackingConnectionModes) {
449*ec779b8eSAndroid Build Coastguard Worker if (htConnectionMode < HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED ||
450*ec779b8eSAndroid Build Coastguard Worker htConnectionMode > HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL) {
451*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: ignoring HT connection mode:%s", __func__,
452*ec779b8eSAndroid Build Coastguard Worker ToString(htConnectionMode).c_str());
453*ec779b8eSAndroid Build Coastguard Worker continue;
454*ec779b8eSAndroid Build Coastguard Worker }
455*ec779b8eSAndroid Build Coastguard Worker mSupportedHeadtrackingConnectionModes.insert(htConnectionMode);
456*ec779b8eSAndroid Build Coastguard Worker }
457*ec779b8eSAndroid Build Coastguard Worker ALOGW_IF(mSupportedHeadtrackingConnectionModes.find(
458*ec779b8eSAndroid Build Coastguard Worker HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED) ==
459*ec779b8eSAndroid Build Coastguard Worker mSupportedHeadtrackingConnectionModes.end(),
460*ec779b8eSAndroid Build Coastguard Worker "%s: Headtracking FRAMEWORK_PROCESSED not reported", __func__);
461*ec779b8eSAndroid Build Coastguard Worker }
462*ec779b8eSAndroid Build Coastguard Worker }
463*ec779b8eSAndroid Build Coastguard Worker
464*ec779b8eSAndroid Build Coastguard Worker // Currently we expose only RELATIVE_WORLD.
465*ec779b8eSAndroid Build Coastguard Worker // This is a limitation of the head tracking library based on a UX choice.
466*ec779b8eSAndroid Build Coastguard Worker mHeadTrackingModes.push_back(HeadTracking::Mode::DISABLED);
467*ec779b8eSAndroid Build Coastguard Worker if (mSupportsHeadTracking) {
468*ec779b8eSAndroid Build Coastguard Worker mHeadTrackingModes.push_back(HeadTracking::Mode::RELATIVE_WORLD);
469*ec779b8eSAndroid Build Coastguard Worker }
470*ec779b8eSAndroid Build Coastguard Worker mediametrics::LogItem(mMetricsId)
471*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
472*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_CHANNELMASKS, channelMaskVectorToString(mChannelMasks))
473*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_LEVELS, aidl_utils::enumsToString(mLevels))
474*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_MODES, aidl_utils::enumsToString(mSpatializationModes))
475*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, aidl_utils::enumsToString(mHeadTrackingModes))
476*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
477*ec779b8eSAndroid Build Coastguard Worker .record();
478*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
479*ec779b8eSAndroid Build Coastguard Worker }
480*ec779b8eSAndroid Build Coastguard Worker
481*ec779b8eSAndroid Build Coastguard Worker /* static */
sendEmptyCreateSpatializerMetricWithStatus(status_t status)482*ec779b8eSAndroid Build Coastguard Worker void Spatializer::sendEmptyCreateSpatializerMetricWithStatus(status_t status) {
483*ec779b8eSAndroid Build Coastguard Worker mediametrics::LogItem(kDefaultMetricsId)
484*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
485*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_CHANNELMASKS, "")
486*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_LEVELS, "")
487*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_MODES, "")
488*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_HEADTRACKINGMODES, "")
489*ec779b8eSAndroid Build Coastguard Worker .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
490*ec779b8eSAndroid Build Coastguard Worker .record();
491*ec779b8eSAndroid Build Coastguard Worker }
492*ec779b8eSAndroid Build Coastguard Worker
493*ec779b8eSAndroid Build Coastguard Worker /** Gets the channel mask, sampling rate and format set for the spatializer input. */
getAudioInConfig() const494*ec779b8eSAndroid Build Coastguard Worker audio_config_base_t Spatializer::getAudioInConfig() const {
495*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
496*ec779b8eSAndroid Build Coastguard Worker audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
497*ec779b8eSAndroid Build Coastguard Worker // For now use highest supported channel count
498*ec779b8eSAndroid Build Coastguard Worker config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
499*ec779b8eSAndroid Build Coastguard Worker return config;
500*ec779b8eSAndroid Build Coastguard Worker }
501*ec779b8eSAndroid Build Coastguard Worker
getSpatializedChannelMasks(std::vector<int> * masks)502*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::getSpatializedChannelMasks(std::vector<int>* masks) {
503*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
504*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
505*ec779b8eSAndroid Build Coastguard Worker if (masks == nullptr) {
506*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
507*ec779b8eSAndroid Build Coastguard Worker }
508*ec779b8eSAndroid Build Coastguard Worker masks->insert(masks->end(), mSpatializedChannelMasks.begin(),
509*ec779b8eSAndroid Build Coastguard Worker mSpatializedChannelMasks.end());
510*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
511*ec779b8eSAndroid Build Coastguard Worker }
512*ec779b8eSAndroid Build Coastguard Worker
registerCallback(const sp<media::INativeSpatializerCallback> & callback)513*ec779b8eSAndroid Build Coastguard Worker status_t Spatializer::registerCallback(
514*ec779b8eSAndroid Build Coastguard Worker const sp<media::INativeSpatializerCallback>& callback) {
515*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
516*ec779b8eSAndroid Build Coastguard Worker if (callback == nullptr) {
517*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
518*ec779b8eSAndroid Build Coastguard Worker }
519*ec779b8eSAndroid Build Coastguard Worker
520*ec779b8eSAndroid Build Coastguard Worker if (mSpatializerCallback != nullptr) {
521*ec779b8eSAndroid Build Coastguard Worker if (IInterface::asBinder(callback) == IInterface::asBinder(mSpatializerCallback)) {
522*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: Registering callback %p again",
523*ec779b8eSAndroid Build Coastguard Worker __func__, mSpatializerCallback.get());
524*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
525*ec779b8eSAndroid Build Coastguard Worker }
526*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Already one client registered with callback %p",
527*ec779b8eSAndroid Build Coastguard Worker __func__, mSpatializerCallback.get());
528*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
529*ec779b8eSAndroid Build Coastguard Worker }
530*ec779b8eSAndroid Build Coastguard Worker
531*ec779b8eSAndroid Build Coastguard Worker sp<IBinder> binder = IInterface::asBinder(callback);
532*ec779b8eSAndroid Build Coastguard Worker status_t status = binder->linkToDeath(this);
533*ec779b8eSAndroid Build Coastguard Worker if (status == NO_ERROR) {
534*ec779b8eSAndroid Build Coastguard Worker mSpatializerCallback = callback;
535*ec779b8eSAndroid Build Coastguard Worker }
536*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s status %d", __func__, status);
537*ec779b8eSAndroid Build Coastguard Worker return status;
538*ec779b8eSAndroid Build Coastguard Worker }
539*ec779b8eSAndroid Build Coastguard Worker
540*ec779b8eSAndroid Build Coastguard Worker // IBinder::DeathRecipient
binderDied(__unused const wp<IBinder> & who)541*ec779b8eSAndroid Build Coastguard Worker void Spatializer::binderDied(__unused const wp<IBinder> &who) {
542*ec779b8eSAndroid Build Coastguard Worker {
543*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
544*ec779b8eSAndroid Build Coastguard Worker mLevel = Spatialization::Level::NONE;
545*ec779b8eSAndroid Build Coastguard Worker mSpatializerCallback.clear();
546*ec779b8eSAndroid Build Coastguard Worker }
547*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
548*ec779b8eSAndroid Build Coastguard Worker mPolicyCallback->onCheckSpatializer();
549*ec779b8eSAndroid Build Coastguard Worker }
550*ec779b8eSAndroid Build Coastguard Worker
551*ec779b8eSAndroid Build Coastguard Worker // ISpatializer
getSupportedLevels(std::vector<Spatialization::Level> * levels)552*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::getSupportedLevels(std::vector<Spatialization::Level> *levels) {
553*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
554*ec779b8eSAndroid Build Coastguard Worker if (levels == nullptr) {
555*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
556*ec779b8eSAndroid Build Coastguard Worker }
557*ec779b8eSAndroid Build Coastguard Worker // Spatialization::Level::NONE is already required from the effect or we don't load it.
558*ec779b8eSAndroid Build Coastguard Worker levels->insert(levels->end(), mLevels.begin(), mLevels.end());
559*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
560*ec779b8eSAndroid Build Coastguard Worker }
561*ec779b8eSAndroid Build Coastguard Worker
setLevel(Spatialization::Level level)562*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setLevel(Spatialization::Level level) {
563*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s level %s", __func__, ToString(level).c_str());
564*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with %s", __func__, ToString(level).c_str());
565*ec779b8eSAndroid Build Coastguard Worker if (level != Spatialization::Level::NONE
566*ec779b8eSAndroid Build Coastguard Worker && std::find(mLevels.begin(), mLevels.end(), level) == mLevels.end()) {
567*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
568*ec779b8eSAndroid Build Coastguard Worker }
569*ec779b8eSAndroid Build Coastguard Worker sp<media::INativeSpatializerCallback> callback;
570*ec779b8eSAndroid Build Coastguard Worker bool levelChanged = false;
571*ec779b8eSAndroid Build Coastguard Worker {
572*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
573*ec779b8eSAndroid Build Coastguard Worker levelChanged = mLevel != level;
574*ec779b8eSAndroid Build Coastguard Worker mLevel = level;
575*ec779b8eSAndroid Build Coastguard Worker callback = mSpatializerCallback;
576*ec779b8eSAndroid Build Coastguard Worker
577*ec779b8eSAndroid Build Coastguard Worker if (levelChanged && mEngine != nullptr) {
578*ec779b8eSAndroid Build Coastguard Worker checkEngineState_l();
579*ec779b8eSAndroid Build Coastguard Worker }
580*ec779b8eSAndroid Build Coastguard Worker checkSensorsState_l();
581*ec779b8eSAndroid Build Coastguard Worker }
582*ec779b8eSAndroid Build Coastguard Worker
583*ec779b8eSAndroid Build Coastguard Worker if (levelChanged) {
584*ec779b8eSAndroid Build Coastguard Worker mPolicyCallback->onCheckSpatializer();
585*ec779b8eSAndroid Build Coastguard Worker if (callback != nullptr) {
586*ec779b8eSAndroid Build Coastguard Worker callback->onLevelChanged(level);
587*ec779b8eSAndroid Build Coastguard Worker }
588*ec779b8eSAndroid Build Coastguard Worker }
589*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
590*ec779b8eSAndroid Build Coastguard Worker }
591*ec779b8eSAndroid Build Coastguard Worker
getLevel(Spatialization::Level * level)592*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::getLevel(Spatialization::Level *level) {
593*ec779b8eSAndroid Build Coastguard Worker if (level == nullptr) {
594*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
595*ec779b8eSAndroid Build Coastguard Worker }
596*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
597*ec779b8eSAndroid Build Coastguard Worker *level = mLevel;
598*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s level %s", __func__, ToString(*level).c_str());
599*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
600*ec779b8eSAndroid Build Coastguard Worker }
601*ec779b8eSAndroid Build Coastguard Worker
isHeadTrackingSupported(bool * supports)602*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::isHeadTrackingSupported(bool *supports) {
603*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s mSupportsHeadTracking %s", __func__, ToString(mSupportsHeadTracking).c_str());
604*ec779b8eSAndroid Build Coastguard Worker if (supports == nullptr) {
605*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
606*ec779b8eSAndroid Build Coastguard Worker }
607*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
608*ec779b8eSAndroid Build Coastguard Worker *supports = mSupportsHeadTracking;
609*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
610*ec779b8eSAndroid Build Coastguard Worker }
611*ec779b8eSAndroid Build Coastguard Worker
getSupportedHeadTrackingModes(std::vector<HeadTracking::Mode> * modes)612*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::getSupportedHeadTrackingModes(
613*ec779b8eSAndroid Build Coastguard Worker std::vector<HeadTracking::Mode>* modes) {
614*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
615*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
616*ec779b8eSAndroid Build Coastguard Worker if (modes == nullptr) {
617*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
618*ec779b8eSAndroid Build Coastguard Worker }
619*ec779b8eSAndroid Build Coastguard Worker modes->insert(modes->end(), mHeadTrackingModes.begin(), mHeadTrackingModes.end());
620*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
621*ec779b8eSAndroid Build Coastguard Worker }
622*ec779b8eSAndroid Build Coastguard Worker
setDesiredHeadTrackingMode(HeadTracking::Mode mode)623*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setDesiredHeadTrackingMode(HeadTracking::Mode mode) {
624*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s mode %s", __func__, ToString(mode).c_str());
625*ec779b8eSAndroid Build Coastguard Worker
626*ec779b8eSAndroid Build Coastguard Worker if (!mSupportsHeadTracking) {
627*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(INVALID_OPERATION);
628*ec779b8eSAndroid Build Coastguard Worker }
629*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with %s", __func__, ToString(mode).c_str());
630*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
631*ec779b8eSAndroid Build Coastguard Worker switch (mode) {
632*ec779b8eSAndroid Build Coastguard Worker case HeadTracking::Mode::OTHER:
633*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
634*ec779b8eSAndroid Build Coastguard Worker case HeadTracking::Mode::DISABLED:
635*ec779b8eSAndroid Build Coastguard Worker mDesiredHeadTrackingMode = HeadTrackingMode::STATIC;
636*ec779b8eSAndroid Build Coastguard Worker break;
637*ec779b8eSAndroid Build Coastguard Worker case HeadTracking::Mode::RELATIVE_WORLD:
638*ec779b8eSAndroid Build Coastguard Worker mDesiredHeadTrackingMode = HeadTrackingMode::WORLD_RELATIVE;
639*ec779b8eSAndroid Build Coastguard Worker break;
640*ec779b8eSAndroid Build Coastguard Worker case HeadTracking::Mode::RELATIVE_SCREEN:
641*ec779b8eSAndroid Build Coastguard Worker mDesiredHeadTrackingMode = HeadTrackingMode::SCREEN_RELATIVE;
642*ec779b8eSAndroid Build Coastguard Worker break;
643*ec779b8eSAndroid Build Coastguard Worker }
644*ec779b8eSAndroid Build Coastguard Worker
645*ec779b8eSAndroid Build Coastguard Worker checkPoseController_l();
646*ec779b8eSAndroid Build Coastguard Worker checkSensorsState_l();
647*ec779b8eSAndroid Build Coastguard Worker
648*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
649*ec779b8eSAndroid Build Coastguard Worker }
650*ec779b8eSAndroid Build Coastguard Worker
getActualHeadTrackingMode(HeadTracking::Mode * mode)651*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::getActualHeadTrackingMode(HeadTracking::Mode *mode) {
652*ec779b8eSAndroid Build Coastguard Worker if (mode == nullptr) {
653*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
654*ec779b8eSAndroid Build Coastguard Worker }
655*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
656*ec779b8eSAndroid Build Coastguard Worker *mode = mActualHeadTrackingMode;
657*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s mode %d", __func__, (int)*mode);
658*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
659*ec779b8eSAndroid Build Coastguard Worker }
660*ec779b8eSAndroid Build Coastguard Worker
recenterHeadTracker()661*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::recenterHeadTracker() {
662*ec779b8eSAndroid Build Coastguard Worker if (!mSupportsHeadTracking) {
663*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(INVALID_OPERATION);
664*ec779b8eSAndroid Build Coastguard Worker }
665*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
666*ec779b8eSAndroid Build Coastguard Worker if (mPoseController != nullptr) {
667*ec779b8eSAndroid Build Coastguard Worker mPoseController->recenter();
668*ec779b8eSAndroid Build Coastguard Worker }
669*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
670*ec779b8eSAndroid Build Coastguard Worker }
671*ec779b8eSAndroid Build Coastguard Worker
setGlobalTransform(const std::vector<float> & screenToStage)672*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setGlobalTransform(const std::vector<float>& screenToStage) {
673*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
674*ec779b8eSAndroid Build Coastguard Worker if (!mSupportsHeadTracking) {
675*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(INVALID_OPERATION);
676*ec779b8eSAndroid Build Coastguard Worker }
677*ec779b8eSAndroid Build Coastguard Worker std::optional<Pose3f> maybePose = Pose3f::fromVector(screenToStage);
678*ec779b8eSAndroid Build Coastguard Worker if (!maybePose.has_value()) {
679*ec779b8eSAndroid Build Coastguard Worker ALOGW("Invalid screenToStage vector.");
680*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
681*ec779b8eSAndroid Build Coastguard Worker }
682*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
683*ec779b8eSAndroid Build Coastguard Worker if (mPoseController != nullptr) {
684*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with screenToStage %s", __func__,
685*ec779b8eSAndroid Build Coastguard Worker media::VectorRecorder::toString<float>(screenToStage).c_str());
686*ec779b8eSAndroid Build Coastguard Worker mPoseController->setScreenToStagePose(maybePose.value());
687*ec779b8eSAndroid Build Coastguard Worker }
688*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
689*ec779b8eSAndroid Build Coastguard Worker }
690*ec779b8eSAndroid Build Coastguard Worker
release()691*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::release() {
692*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
693*ec779b8eSAndroid Build Coastguard Worker bool levelChanged = false;
694*ec779b8eSAndroid Build Coastguard Worker {
695*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
696*ec779b8eSAndroid Build Coastguard Worker if (mSpatializerCallback == nullptr) {
697*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(INVALID_OPERATION);
698*ec779b8eSAndroid Build Coastguard Worker }
699*ec779b8eSAndroid Build Coastguard Worker
700*ec779b8eSAndroid Build Coastguard Worker sp<IBinder> binder = IInterface::asBinder(mSpatializerCallback);
701*ec779b8eSAndroid Build Coastguard Worker binder->unlinkToDeath(this);
702*ec779b8eSAndroid Build Coastguard Worker mSpatializerCallback.clear();
703*ec779b8eSAndroid Build Coastguard Worker
704*ec779b8eSAndroid Build Coastguard Worker levelChanged = mLevel != Spatialization::Level::NONE;
705*ec779b8eSAndroid Build Coastguard Worker mLevel = Spatialization::Level::NONE;
706*ec779b8eSAndroid Build Coastguard Worker }
707*ec779b8eSAndroid Build Coastguard Worker
708*ec779b8eSAndroid Build Coastguard Worker if (levelChanged) {
709*ec779b8eSAndroid Build Coastguard Worker mPolicyCallback->onCheckSpatializer();
710*ec779b8eSAndroid Build Coastguard Worker }
711*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
712*ec779b8eSAndroid Build Coastguard Worker }
713*ec779b8eSAndroid Build Coastguard Worker
setHeadSensor(int sensorHandle)714*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setHeadSensor(int sensorHandle) {
715*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s sensorHandle %d", __func__, sensorHandle);
716*ec779b8eSAndroid Build Coastguard Worker if (!mSupportsHeadTracking) {
717*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(INVALID_OPERATION);
718*ec779b8eSAndroid Build Coastguard Worker }
719*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
720*ec779b8eSAndroid Build Coastguard Worker if (mHeadSensor != sensorHandle) {
721*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
722*ec779b8eSAndroid Build Coastguard Worker mHeadSensor = sensorHandle;
723*ec779b8eSAndroid Build Coastguard Worker checkPoseController_l();
724*ec779b8eSAndroid Build Coastguard Worker checkSensorsState_l();
725*ec779b8eSAndroid Build Coastguard Worker }
726*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
727*ec779b8eSAndroid Build Coastguard Worker }
728*ec779b8eSAndroid Build Coastguard Worker
setScreenSensor(int sensorHandle)729*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setScreenSensor(int sensorHandle) {
730*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s sensorHandle %d", __func__, sensorHandle);
731*ec779b8eSAndroid Build Coastguard Worker if (!mSupportsHeadTracking) {
732*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(INVALID_OPERATION);
733*ec779b8eSAndroid Build Coastguard Worker }
734*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
735*ec779b8eSAndroid Build Coastguard Worker if (mScreenSensor != sensorHandle) {
736*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
737*ec779b8eSAndroid Build Coastguard Worker mScreenSensor = sensorHandle;
738*ec779b8eSAndroid Build Coastguard Worker // TODO: consider a new method setHeadAndScreenSensor()
739*ec779b8eSAndroid Build Coastguard Worker // because we generally set both at the same time.
740*ec779b8eSAndroid Build Coastguard Worker // This will avoid duplicated work and recentering.
741*ec779b8eSAndroid Build Coastguard Worker checkSensorsState_l();
742*ec779b8eSAndroid Build Coastguard Worker }
743*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
744*ec779b8eSAndroid Build Coastguard Worker }
745*ec779b8eSAndroid Build Coastguard Worker
setDisplayOrientation(float physicalToLogicalAngle)746*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setDisplayOrientation(float physicalToLogicalAngle) {
747*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s physicalToLogicalAngle %f", __func__, physicalToLogicalAngle);
748*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with %f", __func__, physicalToLogicalAngle);
749*ec779b8eSAndroid Build Coastguard Worker const float angle = safe_clamp(physicalToLogicalAngle, 0.f, (float)(2. * M_PI));
750*ec779b8eSAndroid Build Coastguard Worker // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
751*ec779b8eSAndroid Build Coastguard Worker ALOGI_IF(angle != physicalToLogicalAngle,
752*ec779b8eSAndroid Build Coastguard Worker "%s: clamping %f to %f", __func__, physicalToLogicalAngle, angle);
753*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
754*ec779b8eSAndroid Build Coastguard Worker mDisplayOrientation = angle;
755*ec779b8eSAndroid Build Coastguard Worker if (mPoseController != nullptr) {
756*ec779b8eSAndroid Build Coastguard Worker // This turns on the rate-limiter.
757*ec779b8eSAndroid Build Coastguard Worker mPoseController->setDisplayOrientation(angle);
758*ec779b8eSAndroid Build Coastguard Worker }
759*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
760*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(
761*ec779b8eSAndroid Build Coastguard Worker SPATIALIZER_PARAM_DISPLAY_ORIENTATION, std::vector<float>{angle});
762*ec779b8eSAndroid Build Coastguard Worker }
763*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
764*ec779b8eSAndroid Build Coastguard Worker }
765*ec779b8eSAndroid Build Coastguard Worker
setHingeAngle(float hingeAngle)766*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setHingeAngle(float hingeAngle) {
767*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s hingeAngle %f", __func__, hingeAngle);
768*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with %f", __func__, hingeAngle);
769*ec779b8eSAndroid Build Coastguard Worker const float angle = safe_clamp(hingeAngle, 0.f, (float)(2. * M_PI));
770*ec779b8eSAndroid Build Coastguard Worker // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
771*ec779b8eSAndroid Build Coastguard Worker ALOGI_IF(angle != hingeAngle,
772*ec779b8eSAndroid Build Coastguard Worker "%s: clamping %f to %f", __func__, hingeAngle, angle);
773*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
774*ec779b8eSAndroid Build Coastguard Worker mHingeAngle = angle;
775*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
776*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{angle});
777*ec779b8eSAndroid Build Coastguard Worker }
778*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
779*ec779b8eSAndroid Build Coastguard Worker }
780*ec779b8eSAndroid Build Coastguard Worker
setFoldState(bool folded)781*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setFoldState(bool folded) {
782*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s foldState %d", __func__, (int)folded);
783*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with %d", __func__, (int)folded);
784*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
785*ec779b8eSAndroid Build Coastguard Worker mFoldedState = folded;
786*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
787*ec779b8eSAndroid Build Coastguard Worker // we don't suppress multiple calls with the same folded state - that's
788*ec779b8eSAndroid Build Coastguard Worker // done at the caller.
789*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE, std::vector<uint8_t>{mFoldedState});
790*ec779b8eSAndroid Build Coastguard Worker }
791*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
792*ec779b8eSAndroid Build Coastguard Worker }
793*ec779b8eSAndroid Build Coastguard Worker
getSupportedModes(std::vector<Spatialization::Mode> * modes)794*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::getSupportedModes(std::vector<Spatialization::Mode> *modes) {
795*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
796*ec779b8eSAndroid Build Coastguard Worker if (modes == nullptr) {
797*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
798*ec779b8eSAndroid Build Coastguard Worker }
799*ec779b8eSAndroid Build Coastguard Worker *modes = mSpatializationModes;
800*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
801*ec779b8eSAndroid Build Coastguard Worker }
802*ec779b8eSAndroid Build Coastguard Worker
registerHeadTrackingCallback(const sp<media::ISpatializerHeadTrackingCallback> & callback)803*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::registerHeadTrackingCallback(
804*ec779b8eSAndroid Build Coastguard Worker const sp<media::ISpatializerHeadTrackingCallback>& callback) {
805*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s callback %p", __func__, callback.get());
806*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
807*ec779b8eSAndroid Build Coastguard Worker if (!mSupportsHeadTracking) {
808*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(INVALID_OPERATION);
809*ec779b8eSAndroid Build Coastguard Worker }
810*ec779b8eSAndroid Build Coastguard Worker mHeadTrackingCallback = callback;
811*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
812*ec779b8eSAndroid Build Coastguard Worker }
813*ec779b8eSAndroid Build Coastguard Worker
setParameter(int key,const std::vector<unsigned char> & value)814*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
815*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s key %d", __func__, key);
816*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
817*ec779b8eSAndroid Build Coastguard Worker status_t status = INVALID_OPERATION;
818*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
819*ec779b8eSAndroid Build Coastguard Worker status = setEffectParameter_l(key, value);
820*ec779b8eSAndroid Build Coastguard Worker }
821*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(status);
822*ec779b8eSAndroid Build Coastguard Worker }
823*ec779b8eSAndroid Build Coastguard Worker
getParameter(int key,std::vector<unsigned char> * value)824*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::getParameter(int key, std::vector<unsigned char> *value) {
825*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s key %d value size %d", __func__, key,
826*ec779b8eSAndroid Build Coastguard Worker (value != nullptr ? (int)value->size() : -1));
827*ec779b8eSAndroid Build Coastguard Worker if (value == nullptr) {
828*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(BAD_VALUE);
829*ec779b8eSAndroid Build Coastguard Worker }
830*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
831*ec779b8eSAndroid Build Coastguard Worker status_t status = INVALID_OPERATION;
832*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
833*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
834*ec779b8eSAndroid Build Coastguard Worker status = getEffectParameter_l(key, value);
835*ec779b8eSAndroid Build Coastguard Worker }
836*ec779b8eSAndroid Build Coastguard Worker return binderStatusFromStatusT(status);
837*ec779b8eSAndroid Build Coastguard Worker }
838*ec779b8eSAndroid Build Coastguard Worker
getOutput(int * output)839*ec779b8eSAndroid Build Coastguard Worker Status Spatializer::getOutput(int *output) {
840*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
841*ec779b8eSAndroid Build Coastguard Worker if (output == nullptr) {
842*ec779b8eSAndroid Build Coastguard Worker binderStatusFromStatusT(BAD_VALUE);
843*ec779b8eSAndroid Build Coastguard Worker }
844*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
845*ec779b8eSAndroid Build Coastguard Worker *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
846*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s got output %d", __func__, *output);
847*ec779b8eSAndroid Build Coastguard Worker return Status::ok();
848*ec779b8eSAndroid Build Coastguard Worker }
849*ec779b8eSAndroid Build Coastguard Worker
850*ec779b8eSAndroid Build Coastguard Worker // SpatializerPoseController::Listener
onHeadToStagePose(const Pose3f & headToStage)851*ec779b8eSAndroid Build Coastguard Worker void Spatializer::onHeadToStagePose(const Pose3f& headToStage) {
852*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
853*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!mSupportsHeadTracking,
854*ec779b8eSAndroid Build Coastguard Worker "onHeadToStagePose() called with no head tracking support!");
855*ec779b8eSAndroid Build Coastguard Worker
856*ec779b8eSAndroid Build Coastguard Worker auto vec = headToStage.toVector();
857*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(vec.size() != sHeadPoseKeys.size(),
858*ec779b8eSAndroid Build Coastguard Worker "%s invalid head to stage vector size %zu", __func__, vec.size());
859*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg =
860*ec779b8eSAndroid Build Coastguard Worker new AMessage(EngineCallbackHandler::kWhatOnHeadToStagePose, mHandler);
861*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0 ; i < sHeadPoseKeys.size(); i++) {
862*ec779b8eSAndroid Build Coastguard Worker msg->setFloat(sHeadPoseKeys[i], vec[i]);
863*ec779b8eSAndroid Build Coastguard Worker }
864*ec779b8eSAndroid Build Coastguard Worker msg->post();
865*ec779b8eSAndroid Build Coastguard Worker }
866*ec779b8eSAndroid Build Coastguard Worker
resetEngineHeadPose_l()867*ec779b8eSAndroid Build Coastguard Worker void Spatializer::resetEngineHeadPose_l() {
868*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s mEngine %p", __func__, mEngine.get());
869*ec779b8eSAndroid Build Coastguard Worker if (mEngine == nullptr) {
870*ec779b8eSAndroid Build Coastguard Worker return;
871*ec779b8eSAndroid Build Coastguard Worker }
872*ec779b8eSAndroid Build Coastguard Worker const std::vector<float> headToStage(6, 0.0);
873*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
874*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
875*ec779b8eSAndroid Build Coastguard Worker std::vector<HeadTracking::Mode>{HeadTracking::Mode::DISABLED});
876*ec779b8eSAndroid Build Coastguard Worker }
877*ec779b8eSAndroid Build Coastguard Worker
onHeadToStagePoseMsg(const std::vector<float> & headToStage)878*ec779b8eSAndroid Build Coastguard Worker void Spatializer::onHeadToStagePoseMsg(const std::vector<float>& headToStage) {
879*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
880*ec779b8eSAndroid Build Coastguard Worker sp<media::ISpatializerHeadTrackingCallback> callback;
881*ec779b8eSAndroid Build Coastguard Worker {
882*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
883*ec779b8eSAndroid Build Coastguard Worker callback = mHeadTrackingCallback;
884*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
885*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
886*ec779b8eSAndroid Build Coastguard Worker const auto record = recordFromTranslationRotationVector(headToStage);
887*ec779b8eSAndroid Build Coastguard Worker mPoseRecorder.record(record);
888*ec779b8eSAndroid Build Coastguard Worker mPoseDurableRecorder.record(record);
889*ec779b8eSAndroid Build Coastguard Worker }
890*ec779b8eSAndroid Build Coastguard Worker }
891*ec779b8eSAndroid Build Coastguard Worker
892*ec779b8eSAndroid Build Coastguard Worker if (callback != nullptr) {
893*ec779b8eSAndroid Build Coastguard Worker callback->onHeadToSoundStagePoseUpdated(headToStage);
894*ec779b8eSAndroid Build Coastguard Worker }
895*ec779b8eSAndroid Build Coastguard Worker }
896*ec779b8eSAndroid Build Coastguard Worker
onActualModeChange(HeadTrackingMode mode)897*ec779b8eSAndroid Build Coastguard Worker void Spatializer::onActualModeChange(HeadTrackingMode mode) {
898*ec779b8eSAndroid Build Coastguard Worker std::string modeStr = ToString(mode);
899*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s(%s)", __func__, modeStr.c_str());
900*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
901*ec779b8eSAndroid Build Coastguard Worker msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
902*ec779b8eSAndroid Build Coastguard Worker msg->post();
903*ec779b8eSAndroid Build Coastguard Worker }
904*ec779b8eSAndroid Build Coastguard Worker
onActualModeChangeMsg(HeadTrackingMode mode)905*ec779b8eSAndroid Build Coastguard Worker void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
906*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s(%s)", __func__, ToString(mode).c_str());
907*ec779b8eSAndroid Build Coastguard Worker sp<media::ISpatializerHeadTrackingCallback> callback;
908*ec779b8eSAndroid Build Coastguard Worker HeadTracking::Mode spatializerMode;
909*ec779b8eSAndroid Build Coastguard Worker {
910*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
911*ec779b8eSAndroid Build Coastguard Worker if (!mSupportsHeadTracking) {
912*ec779b8eSAndroid Build Coastguard Worker spatializerMode = HeadTracking::Mode::DISABLED;
913*ec779b8eSAndroid Build Coastguard Worker } else {
914*ec779b8eSAndroid Build Coastguard Worker switch (mode) {
915*ec779b8eSAndroid Build Coastguard Worker case HeadTrackingMode::STATIC:
916*ec779b8eSAndroid Build Coastguard Worker spatializerMode = HeadTracking::Mode::DISABLED;
917*ec779b8eSAndroid Build Coastguard Worker break;
918*ec779b8eSAndroid Build Coastguard Worker case HeadTrackingMode::WORLD_RELATIVE:
919*ec779b8eSAndroid Build Coastguard Worker spatializerMode = HeadTracking::Mode::RELATIVE_WORLD;
920*ec779b8eSAndroid Build Coastguard Worker break;
921*ec779b8eSAndroid Build Coastguard Worker case HeadTrackingMode::SCREEN_RELATIVE:
922*ec779b8eSAndroid Build Coastguard Worker spatializerMode = HeadTracking::Mode::RELATIVE_SCREEN;
923*ec779b8eSAndroid Build Coastguard Worker break;
924*ec779b8eSAndroid Build Coastguard Worker default:
925*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Unknown mode: %s", ToString(mode).c_str());
926*ec779b8eSAndroid Build Coastguard Worker }
927*ec779b8eSAndroid Build Coastguard Worker }
928*ec779b8eSAndroid Build Coastguard Worker mActualHeadTrackingMode = spatializerMode;
929*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
930*ec779b8eSAndroid Build Coastguard Worker if (spatializerMode == HeadTracking::Mode::DISABLED) {
931*ec779b8eSAndroid Build Coastguard Worker resetEngineHeadPose_l();
932*ec779b8eSAndroid Build Coastguard Worker } else {
933*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
934*ec779b8eSAndroid Build Coastguard Worker std::vector<HeadTracking::Mode>{spatializerMode});
935*ec779b8eSAndroid Build Coastguard Worker setEngineHeadtrackingConnectionMode_l();
936*ec779b8eSAndroid Build Coastguard Worker }
937*ec779b8eSAndroid Build Coastguard Worker }
938*ec779b8eSAndroid Build Coastguard Worker callback = mHeadTrackingCallback;
939*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s: updating mode to %s", __func__, ToString(mode).c_str());
940*ec779b8eSAndroid Build Coastguard Worker }
941*ec779b8eSAndroid Build Coastguard Worker if (callback != nullptr) {
942*ec779b8eSAndroid Build Coastguard Worker callback->onHeadTrackingModeChanged(spatializerMode);
943*ec779b8eSAndroid Build Coastguard Worker }
944*ec779b8eSAndroid Build Coastguard Worker }
945*ec779b8eSAndroid Build Coastguard Worker
setEngineHeadtrackingConnectionMode_l()946*ec779b8eSAndroid Build Coastguard Worker void Spatializer::setEngineHeadtrackingConnectionMode_l() {
947*ec779b8eSAndroid Build Coastguard Worker if (!com::android::media::audio::dsa_over_bt_le_audio()) {
948*ec779b8eSAndroid Build Coastguard Worker return;
949*ec779b8eSAndroid Build Coastguard Worker }
950*ec779b8eSAndroid Build Coastguard Worker if (mActualHeadTrackingMode != HeadTracking::Mode::DISABLED
951*ec779b8eSAndroid Build Coastguard Worker && !mSupportedHeadtrackingConnectionModes.empty()) {
952*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_CONNECTION,
953*ec779b8eSAndroid Build Coastguard Worker static_cast<uint8_t>(mHeadtrackingConnectionMode),
954*ec779b8eSAndroid Build Coastguard Worker static_cast<uint32_t>(mHeadSensor));
955*ec779b8eSAndroid Build Coastguard Worker }
956*ec779b8eSAndroid Build Coastguard Worker }
957*ec779b8eSAndroid Build Coastguard Worker
sortSupportedLatencyModes_l()958*ec779b8eSAndroid Build Coastguard Worker void Spatializer::sortSupportedLatencyModes_l() {
959*ec779b8eSAndroid Build Coastguard Worker if (!com::android::media::audio::dsa_over_bt_le_audio()) {
960*ec779b8eSAndroid Build Coastguard Worker return;
961*ec779b8eSAndroid Build Coastguard Worker }
962*ec779b8eSAndroid Build Coastguard Worker std::sort(mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
963*ec779b8eSAndroid Build Coastguard Worker [this](audio_latency_mode_t x, audio_latency_mode_t y) {
964*ec779b8eSAndroid Build Coastguard Worker auto itX = std::find(mOrderedLowLatencyModes.begin(),
965*ec779b8eSAndroid Build Coastguard Worker mOrderedLowLatencyModes.end(), x);
966*ec779b8eSAndroid Build Coastguard Worker auto itY = std::find(mOrderedLowLatencyModes.begin(),
967*ec779b8eSAndroid Build Coastguard Worker mOrderedLowLatencyModes.end(), y);
968*ec779b8eSAndroid Build Coastguard Worker return itX < itY;
969*ec779b8eSAndroid Build Coastguard Worker });
970*ec779b8eSAndroid Build Coastguard Worker }
971*ec779b8eSAndroid Build Coastguard Worker
attachOutput(audio_io_handle_t output,const std::vector<audio_channel_mask_t> & activeTracksMasks)972*ec779b8eSAndroid Build Coastguard Worker status_t Spatializer::attachOutput(audio_io_handle_t output,
973*ec779b8eSAndroid Build Coastguard Worker const std::vector<audio_channel_mask_t>& activeTracksMasks) {
974*ec779b8eSAndroid Build Coastguard Worker bool outputChanged = false;
975*ec779b8eSAndroid Build Coastguard Worker sp<media::INativeSpatializerCallback> callback;
976*ec779b8eSAndroid Build Coastguard Worker
977*ec779b8eSAndroid Build Coastguard Worker {
978*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
979*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
980*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
981*ec779b8eSAndroid Build Coastguard Worker activeTracksMasks.size(), (int)mOutput);
982*ec779b8eSAndroid Build Coastguard Worker if (mOutput != AUDIO_IO_HANDLE_NONE) {
983*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mEngine == nullptr, "%s output set without FX engine", __func__);
984*ec779b8eSAndroid Build Coastguard Worker // remove FX instance
985*ec779b8eSAndroid Build Coastguard Worker mEngine->setEnabled(false);
986*ec779b8eSAndroid Build Coastguard Worker mEngine.clear();
987*ec779b8eSAndroid Build Coastguard Worker mPoseController.reset();
988*ec779b8eSAndroid Build Coastguard Worker AudioSystem::removeSupportedLatencyModesCallback(this);
989*ec779b8eSAndroid Build Coastguard Worker }
990*ec779b8eSAndroid Build Coastguard Worker
991*ec779b8eSAndroid Build Coastguard Worker // create FX instance on output
992*ec779b8eSAndroid Build Coastguard Worker AttributionSourceState attributionSource = AttributionSourceState();
993*ec779b8eSAndroid Build Coastguard Worker mEngine = new AudioEffect(attributionSource);
994*ec779b8eSAndroid Build Coastguard Worker mEngine->set(nullptr /* type */, &mEngineDescriptor.uuid, 0 /* priority */,
995*ec779b8eSAndroid Build Coastguard Worker wp<AudioEffect::IAudioEffectCallback>::fromExisting(this),
996*ec779b8eSAndroid Build Coastguard Worker AUDIO_SESSION_OUTPUT_STAGE, output, {} /* device */, false /* probe */,
997*ec779b8eSAndroid Build Coastguard Worker true /* notifyFramesProcessed */);
998*ec779b8eSAndroid Build Coastguard Worker status_t status = mEngine->initCheck();
999*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s mEngine create status %d", __func__, (int)status);
1000*ec779b8eSAndroid Build Coastguard Worker if (status != NO_ERROR) {
1001*ec779b8eSAndroid Build Coastguard Worker return status;
1002*ec779b8eSAndroid Build Coastguard Worker }
1003*ec779b8eSAndroid Build Coastguard Worker
1004*ec779b8eSAndroid Build Coastguard Worker outputChanged = mOutput != output;
1005*ec779b8eSAndroid Build Coastguard Worker mOutput = output;
1006*ec779b8eSAndroid Build Coastguard Worker mActiveTracksMasks = activeTracksMasks;
1007*ec779b8eSAndroid Build Coastguard Worker AudioSystem::addSupportedLatencyModesCallback(this);
1008*ec779b8eSAndroid Build Coastguard Worker
1009*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_latency_mode_t> latencyModes;
1010*ec779b8eSAndroid Build Coastguard Worker status = AudioSystem::getSupportedLatencyModes(mOutput, &latencyModes);
1011*ec779b8eSAndroid Build Coastguard Worker if (status == OK) {
1012*ec779b8eSAndroid Build Coastguard Worker mSupportedLatencyModes = latencyModes;
1013*ec779b8eSAndroid Build Coastguard Worker sortSupportedLatencyModes_l();
1014*ec779b8eSAndroid Build Coastguard Worker }
1015*ec779b8eSAndroid Build Coastguard Worker
1016*ec779b8eSAndroid Build Coastguard Worker checkEngineState_l();
1017*ec779b8eSAndroid Build Coastguard Worker if (mSupportsHeadTracking) {
1018*ec779b8eSAndroid Build Coastguard Worker checkPoseController_l();
1019*ec779b8eSAndroid Build Coastguard Worker checkSensorsState_l();
1020*ec779b8eSAndroid Build Coastguard Worker }
1021*ec779b8eSAndroid Build Coastguard Worker callback = mSpatializerCallback;
1022*ec779b8eSAndroid Build Coastguard Worker
1023*ec779b8eSAndroid Build Coastguard Worker // Restore common effect state.
1024*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_DISPLAY_ORIENTATION,
1025*ec779b8eSAndroid Build Coastguard Worker std::vector<float>{mDisplayOrientation});
1026*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_FOLD_STATE,
1027*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t>{mFoldedState});
1028*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE,
1029*ec779b8eSAndroid Build Coastguard Worker std::vector<float>{mHingeAngle});
1030*ec779b8eSAndroid Build Coastguard Worker }
1031*ec779b8eSAndroid Build Coastguard Worker
1032*ec779b8eSAndroid Build Coastguard Worker if (outputChanged && callback != nullptr) {
1033*ec779b8eSAndroid Build Coastguard Worker callback->onOutputChanged(output);
1034*ec779b8eSAndroid Build Coastguard Worker }
1035*ec779b8eSAndroid Build Coastguard Worker
1036*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
1037*ec779b8eSAndroid Build Coastguard Worker }
1038*ec779b8eSAndroid Build Coastguard Worker
detachOutput()1039*ec779b8eSAndroid Build Coastguard Worker audio_io_handle_t Spatializer::detachOutput() {
1040*ec779b8eSAndroid Build Coastguard Worker audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
1041*ec779b8eSAndroid Build Coastguard Worker sp<media::INativeSpatializerCallback> callback;
1042*ec779b8eSAndroid Build Coastguard Worker
1043*ec779b8eSAndroid Build Coastguard Worker {
1044*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
1045*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s with output %d num tracks %zu",
1046*ec779b8eSAndroid Build Coastguard Worker __func__, (int)mOutput, mActiveTracksMasks.size());
1047*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s mOutput %d", __func__, (int)mOutput);
1048*ec779b8eSAndroid Build Coastguard Worker if (mOutput == AUDIO_IO_HANDLE_NONE) {
1049*ec779b8eSAndroid Build Coastguard Worker return output;
1050*ec779b8eSAndroid Build Coastguard Worker }
1051*ec779b8eSAndroid Build Coastguard Worker // remove FX instance
1052*ec779b8eSAndroid Build Coastguard Worker mEngine->setEnabled(false);
1053*ec779b8eSAndroid Build Coastguard Worker mEngine.clear();
1054*ec779b8eSAndroid Build Coastguard Worker AudioSystem::removeSupportedLatencyModesCallback(this);
1055*ec779b8eSAndroid Build Coastguard Worker output = mOutput;
1056*ec779b8eSAndroid Build Coastguard Worker mOutput = AUDIO_IO_HANDLE_NONE;
1057*ec779b8eSAndroid Build Coastguard Worker mPoseController.reset();
1058*ec779b8eSAndroid Build Coastguard Worker callback = mSpatializerCallback;
1059*ec779b8eSAndroid Build Coastguard Worker }
1060*ec779b8eSAndroid Build Coastguard Worker
1061*ec779b8eSAndroid Build Coastguard Worker if (callback != nullptr) {
1062*ec779b8eSAndroid Build Coastguard Worker callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
1063*ec779b8eSAndroid Build Coastguard Worker }
1064*ec779b8eSAndroid Build Coastguard Worker return output;
1065*ec779b8eSAndroid Build Coastguard Worker }
1066*ec779b8eSAndroid Build Coastguard Worker
onSupportedLatencyModesChanged(audio_io_handle_t output,const std::vector<audio_latency_mode_t> & modes)1067*ec779b8eSAndroid Build Coastguard Worker void Spatializer::onSupportedLatencyModesChanged(
1068*ec779b8eSAndroid Build Coastguard Worker audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
1069*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s output %d num modes %zu", __func__, (int)output, modes.size());
1070*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg =
1071*ec779b8eSAndroid Build Coastguard Worker new AMessage(EngineCallbackHandler::kWhatOnLatencyModesChanged, mHandler);
1072*ec779b8eSAndroid Build Coastguard Worker msg->setObject(EngineCallbackHandler::kLatencyModesKey,
1073*ec779b8eSAndroid Build Coastguard Worker sp<EngineCallbackHandler::LatencyModes>::make(output, modes));
1074*ec779b8eSAndroid Build Coastguard Worker msg->post();
1075*ec779b8eSAndroid Build Coastguard Worker }
1076*ec779b8eSAndroid Build Coastguard Worker
onSupportedLatencyModesChangedMsg(audio_io_handle_t output,std::vector<audio_latency_mode_t> && modes)1077*ec779b8eSAndroid Build Coastguard Worker void Spatializer::onSupportedLatencyModesChangedMsg(
1078*ec779b8eSAndroid Build Coastguard Worker audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
1079*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
1080*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s output %d mOutput %d num modes %zu",
1081*ec779b8eSAndroid Build Coastguard Worker __func__, (int)output, (int)mOutput, modes.size());
1082*ec779b8eSAndroid Build Coastguard Worker if (output == mOutput) {
1083*ec779b8eSAndroid Build Coastguard Worker mSupportedLatencyModes = std::move(modes);
1084*ec779b8eSAndroid Build Coastguard Worker sortSupportedLatencyModes_l();
1085*ec779b8eSAndroid Build Coastguard Worker checkSensorsState_l();
1086*ec779b8eSAndroid Build Coastguard Worker }
1087*ec779b8eSAndroid Build Coastguard Worker }
1088*ec779b8eSAndroid Build Coastguard Worker
updateActiveTracks(const std::vector<audio_channel_mask_t> & activeTracksMasks)1089*ec779b8eSAndroid Build Coastguard Worker void Spatializer::updateActiveTracks(
1090*ec779b8eSAndroid Build Coastguard Worker const std::vector<audio_channel_mask_t>& activeTracksMasks) {
1091*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
1092*ec779b8eSAndroid Build Coastguard Worker if (mActiveTracksMasks != activeTracksMasks) {
1093*ec779b8eSAndroid Build Coastguard Worker mLocalLog.log("%s from %zu to %zu",
1094*ec779b8eSAndroid Build Coastguard Worker __func__, mActiveTracksMasks.size(), activeTracksMasks.size());
1095*ec779b8eSAndroid Build Coastguard Worker mActiveTracksMasks = activeTracksMasks;
1096*ec779b8eSAndroid Build Coastguard Worker checkEngineState_l();
1097*ec779b8eSAndroid Build Coastguard Worker checkSensorsState_l();
1098*ec779b8eSAndroid Build Coastguard Worker }
1099*ec779b8eSAndroid Build Coastguard Worker }
1100*ec779b8eSAndroid Build Coastguard Worker
selectHeadtrackingConnectionMode_l()1101*ec779b8eSAndroid Build Coastguard Worker audio_latency_mode_t Spatializer::selectHeadtrackingConnectionMode_l() {
1102*ec779b8eSAndroid Build Coastguard Worker if (!com::android::media::audio::dsa_over_bt_le_audio()) {
1103*ec779b8eSAndroid Build Coastguard Worker return AUDIO_LATENCY_MODE_LOW;
1104*ec779b8eSAndroid Build Coastguard Worker }
1105*ec779b8eSAndroid Build Coastguard Worker // mSupportedLatencyModes is ordered according to system preferences loaded in
1106*ec779b8eSAndroid Build Coastguard Worker // mOrderedLowLatencyModes
1107*ec779b8eSAndroid Build Coastguard Worker mHeadtrackingConnectionMode = HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED;
1108*ec779b8eSAndroid Build Coastguard Worker audio_latency_mode_t requestedLatencyMode = mSupportedLatencyModes[0];
1109*ec779b8eSAndroid Build Coastguard Worker if (requestedLatencyMode == AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
1110*ec779b8eSAndroid Build Coastguard Worker if (mSupportedHeadtrackingConnectionModes.find(
1111*ec779b8eSAndroid Build Coastguard Worker HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL)
1112*ec779b8eSAndroid Build Coastguard Worker != mSupportedHeadtrackingConnectionModes.end()) {
1113*ec779b8eSAndroid Build Coastguard Worker mHeadtrackingConnectionMode = HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL;
1114*ec779b8eSAndroid Build Coastguard Worker } else if (mSupportedHeadtrackingConnectionModes.find(
1115*ec779b8eSAndroid Build Coastguard Worker HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_SW)
1116*ec779b8eSAndroid Build Coastguard Worker != mSupportedHeadtrackingConnectionModes.end()) {
1117*ec779b8eSAndroid Build Coastguard Worker mHeadtrackingConnectionMode = HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_SW;
1118*ec779b8eSAndroid Build Coastguard Worker } else {
1119*ec779b8eSAndroid Build Coastguard Worker // if the engine does not support direct reading of IMU data, do not allow
1120*ec779b8eSAndroid Build Coastguard Worker // DYNAMIC_SPATIAL_AUDIO_HARDWARE mode and fallback to next mode
1121*ec779b8eSAndroid Build Coastguard Worker if (mSupportedLatencyModes.size() > 1) {
1122*ec779b8eSAndroid Build Coastguard Worker requestedLatencyMode = mSupportedLatencyModes[1];
1123*ec779b8eSAndroid Build Coastguard Worker } else {
1124*ec779b8eSAndroid Build Coastguard Worker // If only DYNAMIC_SPATIAL_AUDIO_HARDWARE mode is reported by the
1125*ec779b8eSAndroid Build Coastguard Worker // HAL and the engine does not support it, assert as this is a
1126*ec779b8eSAndroid Build Coastguard Worker // product configuration error
1127*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("%s: the audio HAL reported only low latency with"
1128*ec779b8eSAndroid Build Coastguard Worker "HW HID tunneling but the spatializer does not support it",
1129*ec779b8eSAndroid Build Coastguard Worker __func__);
1130*ec779b8eSAndroid Build Coastguard Worker }
1131*ec779b8eSAndroid Build Coastguard Worker }
1132*ec779b8eSAndroid Build Coastguard Worker }
1133*ec779b8eSAndroid Build Coastguard Worker return requestedLatencyMode;
1134*ec779b8eSAndroid Build Coastguard Worker }
1135*ec779b8eSAndroid Build Coastguard Worker
checkSensorsState_l()1136*ec779b8eSAndroid Build Coastguard Worker void Spatializer::checkSensorsState_l() {
1137*ec779b8eSAndroid Build Coastguard Worker mRequestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
1138*ec779b8eSAndroid Build Coastguard Worker const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
1139*ec779b8eSAndroid Build Coastguard Worker bool supportsLowLatencyMode;
1140*ec779b8eSAndroid Build Coastguard Worker if (com::android::media::audio::dsa_over_bt_le_audio()) {
1141*ec779b8eSAndroid Build Coastguard Worker // mSupportedLatencyModes is ordered with MODE_FREE always at the end:
1142*ec779b8eSAndroid Build Coastguard Worker // the first entry is never MODE_FREE if at least one low ltency mode is supported.
1143*ec779b8eSAndroid Build Coastguard Worker supportsLowLatencyMode = supportsSetLatencyMode
1144*ec779b8eSAndroid Build Coastguard Worker && mSupportedLatencyModes[0] != AUDIO_LATENCY_MODE_FREE;
1145*ec779b8eSAndroid Build Coastguard Worker } else {
1146*ec779b8eSAndroid Build Coastguard Worker supportsLowLatencyMode = supportsSetLatencyMode && std::find(
1147*ec779b8eSAndroid Build Coastguard Worker mSupportedLatencyModes.begin(), mSupportedLatencyModes.end(),
1148*ec779b8eSAndroid Build Coastguard Worker AUDIO_LATENCY_MODE_LOW) != mSupportedLatencyModes.end();
1149*ec779b8eSAndroid Build Coastguard Worker }
1150*ec779b8eSAndroid Build Coastguard Worker if (mSupportsHeadTracking) {
1151*ec779b8eSAndroid Build Coastguard Worker if (mPoseController != nullptr) {
1152*ec779b8eSAndroid Build Coastguard Worker // TODO(b/253297301, b/255433067) reenable low latency condition check
1153*ec779b8eSAndroid Build Coastguard Worker // for Head Tracking after Bluetooth HAL supports it correctly.
1154*ec779b8eSAndroid Build Coastguard Worker if (shouldUseHeadTracking_l() && mLevel != Spatialization::Level::NONE
1155*ec779b8eSAndroid Build Coastguard Worker && mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
1156*ec779b8eSAndroid Build Coastguard Worker && mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
1157*ec779b8eSAndroid Build Coastguard Worker if (supportsLowLatencyMode) {
1158*ec779b8eSAndroid Build Coastguard Worker mRequestedLatencyMode = selectHeadtrackingConnectionMode_l();
1159*ec779b8eSAndroid Build Coastguard Worker }
1160*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
1161*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
1162*ec779b8eSAndroid Build Coastguard Worker std::vector<HeadTracking::Mode>{mActualHeadTrackingMode});
1163*ec779b8eSAndroid Build Coastguard Worker setEngineHeadtrackingConnectionMode_l();
1164*ec779b8eSAndroid Build Coastguard Worker }
1165*ec779b8eSAndroid Build Coastguard Worker // TODO: b/307588546: configure mPoseController according to selected
1166*ec779b8eSAndroid Build Coastguard Worker // mHeadtrackingConnectionMode
1167*ec779b8eSAndroid Build Coastguard Worker mPoseController->setHeadSensor(mHeadSensor);
1168*ec779b8eSAndroid Build Coastguard Worker mPoseController->setScreenSensor(mScreenSensor);
1169*ec779b8eSAndroid Build Coastguard Worker } else {
1170*ec779b8eSAndroid Build Coastguard Worker mPoseController->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
1171*ec779b8eSAndroid Build Coastguard Worker mPoseController->setScreenSensor(SpatializerPoseController::INVALID_SENSOR);
1172*ec779b8eSAndroid Build Coastguard Worker resetEngineHeadPose_l();
1173*ec779b8eSAndroid Build Coastguard Worker }
1174*ec779b8eSAndroid Build Coastguard Worker } else {
1175*ec779b8eSAndroid Build Coastguard Worker resetEngineHeadPose_l();
1176*ec779b8eSAndroid Build Coastguard Worker }
1177*ec779b8eSAndroid Build Coastguard Worker }
1178*ec779b8eSAndroid Build Coastguard Worker if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
1179*ec779b8eSAndroid Build Coastguard Worker const status_t status =
1180*ec779b8eSAndroid Build Coastguard Worker AudioSystem::setRequestedLatencyMode(mOutput, mRequestedLatencyMode);
1181*ec779b8eSAndroid Build Coastguard Worker ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d", __func__,
1182*ec779b8eSAndroid Build Coastguard Worker mOutput, toString(mRequestedLatencyMode).c_str(), status);
1183*ec779b8eSAndroid Build Coastguard Worker }
1184*ec779b8eSAndroid Build Coastguard Worker }
1185*ec779b8eSAndroid Build Coastguard Worker
1186*ec779b8eSAndroid Build Coastguard Worker
1187*ec779b8eSAndroid Build Coastguard Worker /* static */
containsImmersiveChannelMask(const std::vector<audio_channel_mask_t> & masks)1188*ec779b8eSAndroid Build Coastguard Worker bool Spatializer::containsImmersiveChannelMask(
1189*ec779b8eSAndroid Build Coastguard Worker const std::vector<audio_channel_mask_t>& masks)
1190*ec779b8eSAndroid Build Coastguard Worker {
1191*ec779b8eSAndroid Build Coastguard Worker for (auto mask : masks) {
1192*ec779b8eSAndroid Build Coastguard Worker if (audio_is_channel_mask_spatialized(mask)) {
1193*ec779b8eSAndroid Build Coastguard Worker return true;
1194*ec779b8eSAndroid Build Coastguard Worker }
1195*ec779b8eSAndroid Build Coastguard Worker }
1196*ec779b8eSAndroid Build Coastguard Worker // Only non-immersive channel masks, e.g. AUDIO_CHANNEL_OUT_STEREO, are present.
1197*ec779b8eSAndroid Build Coastguard Worker return false;
1198*ec779b8eSAndroid Build Coastguard Worker }
1199*ec779b8eSAndroid Build Coastguard Worker
shouldUseHeadTracking_l() const1200*ec779b8eSAndroid Build Coastguard Worker bool Spatializer::shouldUseHeadTracking_l() const {
1201*ec779b8eSAndroid Build Coastguard Worker // Headtracking only available on immersive channel masks.
1202*ec779b8eSAndroid Build Coastguard Worker return containsImmersiveChannelMask(mActiveTracksMasks);
1203*ec779b8eSAndroid Build Coastguard Worker }
1204*ec779b8eSAndroid Build Coastguard Worker
checkEngineState_l()1205*ec779b8eSAndroid Build Coastguard Worker void Spatializer::checkEngineState_l() {
1206*ec779b8eSAndroid Build Coastguard Worker if (mEngine != nullptr) {
1207*ec779b8eSAndroid Build Coastguard Worker if (mLevel != Spatialization::Level::NONE && mActiveTracksMasks.size() > 0) {
1208*ec779b8eSAndroid Build Coastguard Worker mEngine->setEnabled(true);
1209*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
1210*ec779b8eSAndroid Build Coastguard Worker std::vector<Spatialization::Level>{mLevel});
1211*ec779b8eSAndroid Build Coastguard Worker } else {
1212*ec779b8eSAndroid Build Coastguard Worker setEffectParameter_l(SPATIALIZER_PARAM_LEVEL,
1213*ec779b8eSAndroid Build Coastguard Worker std::vector<Spatialization::Level>{Spatialization::Level::NONE});
1214*ec779b8eSAndroid Build Coastguard Worker mEngine->setEnabled(false);
1215*ec779b8eSAndroid Build Coastguard Worker }
1216*ec779b8eSAndroid Build Coastguard Worker }
1217*ec779b8eSAndroid Build Coastguard Worker }
1218*ec779b8eSAndroid Build Coastguard Worker
checkPoseController_l()1219*ec779b8eSAndroid Build Coastguard Worker void Spatializer::checkPoseController_l() {
1220*ec779b8eSAndroid Build Coastguard Worker bool isControllerNeeded = mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
1221*ec779b8eSAndroid Build Coastguard Worker && mHeadSensor != SpatializerPoseController::INVALID_SENSOR;
1222*ec779b8eSAndroid Build Coastguard Worker
1223*ec779b8eSAndroid Build Coastguard Worker if (isControllerNeeded && mPoseController == nullptr) {
1224*ec779b8eSAndroid Build Coastguard Worker mPoseController = std::make_shared<SpatializerPoseController>(
1225*ec779b8eSAndroid Build Coastguard Worker static_cast<SpatializerPoseController::Listener*>(this),
1226*ec779b8eSAndroid Build Coastguard Worker 10ms, std::nullopt);
1227*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
1228*ec779b8eSAndroid Build Coastguard Worker "%s could not allocate pose controller", __func__);
1229*ec779b8eSAndroid Build Coastguard Worker mPoseController->setDisplayOrientation(mDisplayOrientation);
1230*ec779b8eSAndroid Build Coastguard Worker } else if (!isControllerNeeded && mPoseController != nullptr) {
1231*ec779b8eSAndroid Build Coastguard Worker mPoseController.reset();
1232*ec779b8eSAndroid Build Coastguard Worker resetEngineHeadPose_l();
1233*ec779b8eSAndroid Build Coastguard Worker }
1234*ec779b8eSAndroid Build Coastguard Worker if (mPoseController != nullptr) {
1235*ec779b8eSAndroid Build Coastguard Worker mPoseController->setDesiredMode(mDesiredHeadTrackingMode);
1236*ec779b8eSAndroid Build Coastguard Worker }
1237*ec779b8eSAndroid Build Coastguard Worker }
1238*ec779b8eSAndroid Build Coastguard Worker
calculateHeadPose()1239*ec779b8eSAndroid Build Coastguard Worker void Spatializer::calculateHeadPose() {
1240*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
1241*ec779b8eSAndroid Build Coastguard Worker audio_utils::lock_guard lock(mMutex);
1242*ec779b8eSAndroid Build Coastguard Worker if (mPoseController != nullptr) {
1243*ec779b8eSAndroid Build Coastguard Worker mPoseController->calculateAsync();
1244*ec779b8eSAndroid Build Coastguard Worker }
1245*ec779b8eSAndroid Build Coastguard Worker }
1246*ec779b8eSAndroid Build Coastguard Worker
onFramesProcessed(int32_t framesProcessed)1247*ec779b8eSAndroid Build Coastguard Worker void Spatializer::onFramesProcessed(int32_t framesProcessed) {
1248*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg =
1249*ec779b8eSAndroid Build Coastguard Worker new AMessage(EngineCallbackHandler::kWhatOnFramesProcessed, mHandler);
1250*ec779b8eSAndroid Build Coastguard Worker msg->setInt32(EngineCallbackHandler::kNumFramesKey, framesProcessed);
1251*ec779b8eSAndroid Build Coastguard Worker msg->post();
1252*ec779b8eSAndroid Build Coastguard Worker }
1253*ec779b8eSAndroid Build Coastguard Worker
toString(unsigned level) const1254*ec779b8eSAndroid Build Coastguard Worker std::string Spatializer::toString(unsigned level) const {
1255*ec779b8eSAndroid Build Coastguard Worker std::string prefixSpace(level, ' ');
1256*ec779b8eSAndroid Build Coastguard Worker std::string ss = prefixSpace + "Spatializer:\n";
1257*ec779b8eSAndroid Build Coastguard Worker bool needUnlock = false;
1258*ec779b8eSAndroid Build Coastguard Worker
1259*ec779b8eSAndroid Build Coastguard Worker prefixSpace += ' ';
1260*ec779b8eSAndroid Build Coastguard Worker if (!mMutex.try_lock()) {
1261*ec779b8eSAndroid Build Coastguard Worker // dumpsys even try_lock failed, information dump can be useful although may not accurate
1262*ec779b8eSAndroid Build Coastguard Worker ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
1263*ec779b8eSAndroid Build Coastguard Worker } else {
1264*ec779b8eSAndroid Build Coastguard Worker needUnlock = true;
1265*ec779b8eSAndroid Build Coastguard Worker }
1266*ec779b8eSAndroid Build Coastguard Worker
1267*ec779b8eSAndroid Build Coastguard Worker // Spatializer class information.
1268*ec779b8eSAndroid Build Coastguard Worker // 1. Capabilities (mLevels, mHeadTrackingModes, mSpatializationModes, mChannelMasks, etc)
1269*ec779b8eSAndroid Build Coastguard Worker ss.append(prefixSpace).append("Supported levels: [");
1270*ec779b8eSAndroid Build Coastguard Worker for (auto& level : mLevels) {
1271*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, " %s", ToString(level).c_str());
1272*ec779b8eSAndroid Build Coastguard Worker }
1273*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "], mLevel: %s", ToString(mLevel).c_str());
1274*ec779b8eSAndroid Build Coastguard Worker
1275*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "\n%smHeadTrackingModes: [", prefixSpace.c_str());
1276*ec779b8eSAndroid Build Coastguard Worker for (auto& mode : mHeadTrackingModes) {
1277*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, " %s", ToString(mode).c_str());
1278*ec779b8eSAndroid Build Coastguard Worker }
1279*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
1280*ec779b8eSAndroid Build Coastguard Worker ToString(mDesiredHeadTrackingMode).c_str(),
1281*ec779b8eSAndroid Build Coastguard Worker ToString(mActualHeadTrackingMode).c_str());
1282*ec779b8eSAndroid Build Coastguard Worker
1283*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
1284*ec779b8eSAndroid Build Coastguard Worker for (auto& mode : mSpatializationModes) {
1285*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, " %s", ToString(mode).c_str());
1286*ec779b8eSAndroid Build Coastguard Worker }
1287*ec779b8eSAndroid Build Coastguard Worker ss += "]\n";
1288*ec779b8eSAndroid Build Coastguard Worker
1289*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%smChannelMasks: ", prefixSpace.c_str());
1290*ec779b8eSAndroid Build Coastguard Worker for (auto& mask : mChannelMasks) {
1291*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1292*ec779b8eSAndroid Build Coastguard Worker }
1293*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%smSpatializedChannelMasks: ", prefixSpace.c_str());
1294*ec779b8eSAndroid Build Coastguard Worker for (auto& mask : mSpatializedChannelMasks) {
1295*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%s", audio_channel_out_mask_to_string(mask));
1296*ec779b8eSAndroid Build Coastguard Worker }
1297*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "\n%smSupportsHeadTracking: %s\n", prefixSpace.c_str(),
1298*ec779b8eSAndroid Build Coastguard Worker mSupportsHeadTracking ? "true" : "false");
1299*ec779b8eSAndroid Build Coastguard Worker // 2. Settings (Output, tracks)
1300*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sNum Active Tracks: %zu\n",
1301*ec779b8eSAndroid Build Coastguard Worker prefixSpace.c_str(), mActiveTracksMasks.size());
1302*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sOutputStreamHandle: %d\n", prefixSpace.c_str(), (int)mOutput);
1303*ec779b8eSAndroid Build Coastguard Worker
1304*ec779b8eSAndroid Build Coastguard Worker // 3. Sensors, Effect information.
1305*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sHeadSensorHandle: 0x%08x\n", prefixSpace.c_str(), mHeadSensor);
1306*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sScreenSensorHandle: 0x%08x\n", prefixSpace.c_str(), mScreenSensor);
1307*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sEffectHandle: %p\n", prefixSpace.c_str(), mEngine.get());
1308*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
1309*ec779b8eSAndroid Build Coastguard Worker mDisplayOrientation);
1310*ec779b8eSAndroid Build Coastguard Worker
1311*ec779b8eSAndroid Build Coastguard Worker // 4. Show flag or property state.
1312*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(
1313*ec779b8eSAndroid Build Coastguard Worker &ss, "%sStereo Spatialization: %s\n", prefixSpace.c_str(),
1314*ec779b8eSAndroid Build Coastguard Worker SpatializerHelper::isStereoSpatializationFeatureEnabled() ? "true" : "false");
1315*ec779b8eSAndroid Build Coastguard Worker
1316*ec779b8eSAndroid Build Coastguard Worker ss.append(prefixSpace + "CommandLog:\n");
1317*ec779b8eSAndroid Build Coastguard Worker ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
1318*ec779b8eSAndroid Build Coastguard Worker
1319*ec779b8eSAndroid Build Coastguard Worker // PostController dump.
1320*ec779b8eSAndroid Build Coastguard Worker if (mPoseController != nullptr) {
1321*ec779b8eSAndroid Build Coastguard Worker ss.append(mPoseController->toString(level + 1))
1322*ec779b8eSAndroid Build Coastguard Worker .append(prefixSpace)
1323*ec779b8eSAndroid Build Coastguard Worker .append("Pose (active stage-to-head) [tx, ty, tz : pitch, roll, yaw]:\n")
1324*ec779b8eSAndroid Build Coastguard Worker .append(prefixSpace)
1325*ec779b8eSAndroid Build Coastguard Worker .append(" PerMinuteHistory:\n")
1326*ec779b8eSAndroid Build Coastguard Worker .append(mPoseDurableRecorder.toString(level + 3))
1327*ec779b8eSAndroid Build Coastguard Worker .append(prefixSpace)
1328*ec779b8eSAndroid Build Coastguard Worker .append(" PerSecondHistory:\n")
1329*ec779b8eSAndroid Build Coastguard Worker .append(mPoseRecorder.toString(level + 3));
1330*ec779b8eSAndroid Build Coastguard Worker } else {
1331*ec779b8eSAndroid Build Coastguard Worker ss.append(prefixSpace).append("SpatializerPoseController not exist\n");
1332*ec779b8eSAndroid Build Coastguard Worker }
1333*ec779b8eSAndroid Build Coastguard Worker
1334*ec779b8eSAndroid Build Coastguard Worker if (needUnlock) {
1335*ec779b8eSAndroid Build Coastguard Worker mMutex.unlock();
1336*ec779b8eSAndroid Build Coastguard Worker }
1337*ec779b8eSAndroid Build Coastguard Worker return ss;
1338*ec779b8eSAndroid Build Coastguard Worker }
1339*ec779b8eSAndroid Build Coastguard Worker
1340*ec779b8eSAndroid Build Coastguard Worker } // namespace android
1341