blob: 63f53b7ffdb51530f6441c5220b3c47e91cc59f3 [file] [log] [blame]
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -07001/*
2 * Copyright 2021, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Andy Hung78f13d12023-01-30 11:58:44 -080016
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070017#include "SpatializerPoseController.h"
Shunkai Yao59b27bc2022-07-22 18:42:27 +000018#include <android-base/stringprintf.h>
19#include <chrono>
20#include <cstdint>
21#include <string>
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070022
Ytai Ben-Tsvie9b34952021-09-10 12:48:27 -070023#define LOG_TAG "SpatializerPoseController"
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070024//#define LOG_NDEBUG 0
Andy Hung79ccfda2023-01-30 11:58:44 -080025#include <cutils/properties.h>
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -070026#include <sensor/Sensor.h>
Andy Hunga461a002022-05-17 10:36:02 -070027#include <media/MediaMetricsItem.h>
Andy Hung78f13d12023-01-30 11:58:44 -080028#include <media/QuaternionUtil.h>
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070029#include <utils/Log.h>
30#include <utils/SystemClock.h>
31
32namespace android {
33
34using media::createHeadTrackingProcessor;
35using media::HeadTrackingMode;
36using media::HeadTrackingProcessor;
37using media::Pose3f;
38using media::SensorPoseProvider;
39using media::Twist3f;
40
41using namespace std::chrono_literals;
42
43namespace {
44
45// This is how fast, in m/s, we allow position to shift during rate-limiting.
Ytai Ben-Tsvic2d28402022-01-14 14:55:16 -080046constexpr float kMaxTranslationalVelocity = 2;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070047
48// This is how fast, in rad/s, we allow rotation angle to shift during rate-limiting.
Nikhil Bhanub6618712022-09-19 16:31:35 -070049constexpr float kMaxRotationalVelocity = 0.8f;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070050
Andy Hung79ccfda2023-01-30 11:58:44 -080051// This is how far into the future we predict the head pose.
52// The prediction duration should be based on the actual latency from
53// head-tracker to audio output, though setting the prediction duration too
54// high may result in higher prediction errors when the head accelerates or
55// decelerates (changes velocity).
56//
57// The head tracking predictor will do a best effort to achieve the requested
58// prediction duration. If the duration is too far in the future based on
59// current sensor variance, the predictor may internally restrict duration to what
60// is achievable with reasonable confidence as the "best prediction".
61constexpr auto kPredictionDuration = 120ms;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070062
Ytai Ben-Tsvie2356842022-04-14 11:30:32 -070063// After not getting a pose sample for this long, we would treat the measurement as stale.
Shunkai Yao66b4eb72022-08-31 19:22:06 +000064// The max connection interval is 50ms, and HT sensor event interval can differ depending on the
65// sampling rate, scheduling, sensor eventQ FIFO etc. 120 (2 * 50 + 20) ms seems reasonable for now.
66constexpr auto kFreshnessTimeout = 120ms;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070067
Ytai Ben-Tsvi44e7c3d2021-12-15 16:04:01 -080068// Auto-recenter kicks in after the head has been still for this long.
Ytai Ben-Tsvicdc03062022-01-10 15:57:52 -080069constexpr auto kAutoRecenterWindowDuration = 6s;
Ytai Ben-Tsvi44e7c3d2021-12-15 16:04:01 -080070
71// Auto-recenter considers head not still if translated by this much (in meters, approx).
72constexpr float kAutoRecenterTranslationThreshold = 0.1f;
73
74// Auto-recenter considers head not still if rotated by this much (in radians, approx).
Ytai Ben-Tsvi237012c2022-02-16 15:54:31 -080075constexpr float kAutoRecenterRotationThreshold = 10.5f / 180 * M_PI;
Ytai Ben-Tsvi44e7c3d2021-12-15 16:04:01 -080076
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -080077// Screen is considered to be unstable (not still) if it has moved significantly within the last
78// time window of this duration.
Robert Daltonec0c3282022-08-26 10:33:34 +000079constexpr auto kScreenStillnessWindowDuration = 750ms;
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -080080
81// Screen is considered to have moved significantly if translated by this much (in meter, approx).
82constexpr float kScreenStillnessTranslationThreshold = 0.1f;
83
84// Screen is considered to have moved significantly if rotated by this much (in radians, approx).
Robert Daltonec0c3282022-08-26 10:33:34 +000085constexpr float kScreenStillnessRotationThreshold = 15.0f / 180 * M_PI;
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -080086
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070087// Time units for system clock ticks. This is what the Sensor Framework timestamps represent and
88// what we use for pose filtering.
89using Ticks = std::chrono::nanoseconds;
90
91// How many ticks in a second.
92constexpr auto kTicksPerSecond = Ticks::period::den;
93
Andy Hunga461a002022-05-17 10:36:02 -070094std::string getSensorMetricsId(int32_t sensorId) {
95 return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_SENSOR).append(std::to_string(sensorId));
96}
97
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070098} // namespace
99
100SpatializerPoseController::SpatializerPoseController(Listener* listener,
Eric Laurente51f80e2022-04-14 10:20:38 +0200101 std::chrono::microseconds sensorPeriod,
102 std::optional<std::chrono::microseconds> maxUpdatePeriod)
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700103 : mListener(listener),
104 mSensorPeriod(sensorPeriod),
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700105 mProcessor(createHeadTrackingProcessor(HeadTrackingProcessor::Options{
106 .maxTranslationalVelocity = kMaxTranslationalVelocity / kTicksPerSecond,
107 .maxRotationalVelocity = kMaxRotationalVelocity / kTicksPerSecond,
Ytai Ben-Tsvie2356842022-04-14 11:30:32 -0700108 .freshnessTimeout = Ticks(kFreshnessTimeout).count(),
Andy Hung79ccfda2023-01-30 11:58:44 -0800109 .predictionDuration = []() -> float {
110 const int duration_ms =
111 property_get_int32("audio.spatializer.prediction_duration_ms", 0);
112 if (duration_ms > 0) {
113 return duration_ms * 1'000'000LL;
114 } else {
115 return Ticks(kPredictionDuration).count();
116 }
117 }(),
Ytai Ben-Tsvi44e7c3d2021-12-15 16:04:01 -0800118 .autoRecenterWindowDuration = Ticks(kAutoRecenterWindowDuration).count(),
119 .autoRecenterTranslationalThreshold = kAutoRecenterTranslationThreshold,
120 .autoRecenterRotationalThreshold = kAutoRecenterRotationThreshold,
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -0800121 .screenStillnessWindowDuration = Ticks(kScreenStillnessWindowDuration).count(),
122 .screenStillnessTranslationalThreshold = kScreenStillnessTranslationThreshold,
123 .screenStillnessRotationalThreshold = kScreenStillnessRotationThreshold,
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700124 })),
Ytai Ben-Tsvi8b6fe3a2021-09-13 15:55:44 -0700125 mPoseProvider(SensorPoseProvider::create("headtracker", this)),
Keith Mok30099472022-06-06 21:40:11 +0000126 mThread([this, maxUpdatePeriod] { // It's important that mThread is initialized after
127 // everything else because it runs a member
128 // function that may use any member
129 // of this class.
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700130 while (true) {
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700131 Pose3f headToStage;
132 std::optional<HeadTrackingMode> modeIfChanged;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700133 {
134 std::unique_lock lock(mMutex);
Eric Laurente51f80e2022-04-14 10:20:38 +0200135 if (maxUpdatePeriod.has_value()) {
136 mCondVar.wait_for(lock, maxUpdatePeriod.value(),
137 [this] { return mShouldExit || mShouldCalculate; });
138 } else {
139 mCondVar.wait(lock, [this] { return mShouldExit || mShouldCalculate; });
140 }
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700141 if (mShouldExit) {
142 ALOGV("Exiting thread");
143 return;
144 }
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700145
146 // Calculate.
147 std::tie(headToStage, modeIfChanged) = calculate_l();
148 }
149
150 // Invoke the callbacks outside the lock.
151 mListener->onHeadToStagePose(headToStage);
152 if (modeIfChanged) {
153 mListener->onActualModeChange(modeIfChanged.value());
154 }
155
156 {
157 std::lock_guard lock(mMutex);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700158 if (!mCalculated) {
159 mCalculated = true;
160 mCondVar.notify_all();
161 }
162 mShouldCalculate = false;
163 }
164 }
Andy Hung79ccfda2023-01-30 11:58:44 -0800165 }) {
166 const media::PosePredictorType posePredictorType =
167 (media::PosePredictorType)
168 property_get_int32("audio.spatializer.pose_predictor_type", -1);
169 if (isValidPosePredictorType(posePredictorType)) {
170 mProcessor->setPosePredictorType(posePredictorType);
171 }
172 }
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700173
174SpatializerPoseController::~SpatializerPoseController() {
175 {
176 std::unique_lock lock(mMutex);
177 mShouldExit = true;
178 mCondVar.notify_all();
179 }
180 mThread.join();
181}
182
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700183void SpatializerPoseController::setHeadSensor(int32_t sensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700184 std::lock_guard lock(mMutex);
Andy Hungba2a61a2022-05-20 12:00:28 -0700185 if (sensor == mHeadSensor) return;
186 ALOGV("%s: new sensor:%d mHeadSensor:%d mScreenSensor:%d",
187 __func__, sensor, mHeadSensor, mScreenSensor);
188
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700189 // Stop current sensor, if valid and different from the other sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700190 if (mHeadSensor != INVALID_SENSOR && mHeadSensor != mScreenSensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700191 mPoseProvider->stopSensor(mHeadSensor);
Andy Hunga461a002022-05-17 10:36:02 -0700192 mediametrics::LogItem(getSensorMetricsId(mHeadSensor))
193 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
194 .record();
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700195 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700196
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700197 if (sensor != INVALID_SENSOR) {
198 if (sensor != mScreenSensor) {
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700199 // Start new sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700200 mHeadSensor =
201 mPoseProvider->startSensor(sensor, mSensorPeriod) ? sensor : INVALID_SENSOR;
Andy Hunga461a002022-05-17 10:36:02 -0700202 if (mHeadSensor != INVALID_SENSOR) {
203 auto sensor = mPoseProvider->getSensorByHandle(mHeadSensor);
204 std::string stringType = sensor ? sensor->getStringType().c_str() : "";
205 mediametrics::LogItem(getSensorMetricsId(mHeadSensor))
206 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
207 .set(AMEDIAMETRICS_PROP_MODE, AMEDIAMETRICS_PROP_MODE_VALUE_HEAD)
208 .set(AMEDIAMETRICS_PROP_TYPE, stringType)
209 .record();
210 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700211 } else {
212 // Sensor is already enabled.
213 mHeadSensor = mScreenSensor;
214 }
215 } else {
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700216 mHeadSensor = INVALID_SENSOR;
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700217 }
218
Andy Hungba2a61a2022-05-20 12:00:28 -0700219 mProcessor->recenter(true /* recenterHead */, false /* recenterScreen */);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700220}
221
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700222void SpatializerPoseController::setScreenSensor(int32_t sensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700223 std::lock_guard lock(mMutex);
Andy Hungba2a61a2022-05-20 12:00:28 -0700224 if (sensor == mScreenSensor) return;
225 ALOGV("%s: new sensor:%d mHeadSensor:%d mScreenSensor:%d",
226 __func__, sensor, mHeadSensor, mScreenSensor);
227
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700228 // Stop current sensor, if valid and different from the other sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700229 if (mScreenSensor != INVALID_SENSOR && mScreenSensor != mHeadSensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700230 mPoseProvider->stopSensor(mScreenSensor);
Andy Hunga461a002022-05-17 10:36:02 -0700231 mediametrics::LogItem(getSensorMetricsId(mScreenSensor))
232 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
233 .record();
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700234 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700235
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700236 if (sensor != INVALID_SENSOR) {
237 if (sensor != mHeadSensor) {
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700238 // Start new sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700239 mScreenSensor =
240 mPoseProvider->startSensor(sensor, mSensorPeriod) ? sensor : INVALID_SENSOR;
Andy Hunga461a002022-05-17 10:36:02 -0700241 auto sensor = mPoseProvider->getSensorByHandle(mScreenSensor);
242 std::string stringType = sensor ? sensor->getStringType().c_str() : "";
243 mediametrics::LogItem(getSensorMetricsId(mScreenSensor))
244 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
245 .set(AMEDIAMETRICS_PROP_MODE, AMEDIAMETRICS_PROP_MODE_VALUE_SCREEN)
246 .set(AMEDIAMETRICS_PROP_TYPE, stringType)
247 .record();
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700248 } else {
249 // Sensor is already enabled.
250 mScreenSensor = mHeadSensor;
251 }
252 } else {
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700253 mScreenSensor = INVALID_SENSOR;
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700254 }
255
Andy Hungba2a61a2022-05-20 12:00:28 -0700256 mProcessor->recenter(false /* recenterHead */, true /* recenterScreen */);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700257}
258
259void SpatializerPoseController::setDesiredMode(HeadTrackingMode mode) {
260 std::lock_guard lock(mMutex);
261 mProcessor->setDesiredMode(mode);
262}
263
264void SpatializerPoseController::setScreenToStagePose(const Pose3f& screenToStage) {
265 std::lock_guard lock(mMutex);
266 mProcessor->setScreenToStagePose(screenToStage);
267}
268
269void SpatializerPoseController::setDisplayOrientation(float physicalToLogicalAngle) {
270 std::lock_guard lock(mMutex);
271 mProcessor->setDisplayOrientation(physicalToLogicalAngle);
272}
273
274void SpatializerPoseController::calculateAsync() {
275 std::lock_guard lock(mMutex);
276 mShouldCalculate = true;
277 mCondVar.notify_all();
278}
279
280void SpatializerPoseController::waitUntilCalculated() {
281 std::unique_lock lock(mMutex);
282 mCondVar.wait(lock, [this] { return mCalculated; });
283}
284
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700285std::tuple<media::Pose3f, std::optional<media::HeadTrackingMode>>
286SpatializerPoseController::calculate_l() {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700287 Pose3f headToStage;
288 HeadTrackingMode mode;
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700289 std::optional<media::HeadTrackingMode> modeIfChanged;
290
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700291 mProcessor->calculate(elapsedRealtimeNano());
292 headToStage = mProcessor->getHeadToStagePose();
293 mode = mProcessor->getActualMode();
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700294 if (!mActualMode.has_value() || mActualMode.value() != mode) {
295 mActualMode = mode;
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700296 modeIfChanged = mode;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700297 }
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700298 return std::make_tuple(headToStage, modeIfChanged);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700299}
300
301void SpatializerPoseController::recenter() {
302 std::lock_guard lock(mMutex);
303 mProcessor->recenter();
304}
305
306void SpatializerPoseController::onPose(int64_t timestamp, int32_t sensor, const Pose3f& pose,
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700307 const std::optional<Twist3f>& twist, bool isNewReference) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700308 std::lock_guard lock(mMutex);
Andy Hung78f13d12023-01-30 11:58:44 -0800309 constexpr float NANOS_TO_MILLIS = 1e-6;
310 constexpr float RAD_TO_DEGREE = 180.f / M_PI;
311
312 const float delayMs = (elapsedRealtimeNano() - timestamp) * NANOS_TO_MILLIS; // CLOCK_BOOTTIME
313
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700314 if (sensor == mHeadSensor) {
Andy Hung9bcf4252023-02-27 13:36:23 -0800315 std::vector<float> pryprydt(8); // pitch, roll, yaw, d_pitch, d_roll, d_yaw,
Andy Hung78f13d12023-01-30 11:58:44 -0800316 // discontinuity, timestamp_delay
Andy Hung9bcf4252023-02-27 13:36:23 -0800317 media::quaternionToAngles(pose.rotation(), &pryprydt[0], &pryprydt[1], &pryprydt[2]);
Andy Hung78f13d12023-01-30 11:58:44 -0800318 if (twist) {
319 const auto rotationalVelocity = twist->rotationalVelocity();
Andy Hung9bcf4252023-02-27 13:36:23 -0800320 // The rotational velocity is an intrinsic transform (i.e. based on the head
321 // coordinate system, not the world coordinate system). It is a 3 element vector:
322 // axis (d theta / dt).
323 //
324 // We leave rotational velocity relative to the head coordinate system,
325 // as the initial head tracking sensor's world frame is arbitrary.
326 media::quaternionToAngles(media::rotationVectorToQuaternion(rotationalVelocity),
327 &pryprydt[3], &pryprydt[4], &pryprydt[5]);
Andy Hung78f13d12023-01-30 11:58:44 -0800328 }
Andy Hung9bcf4252023-02-27 13:36:23 -0800329 pryprydt[6] = isNewReference;
330 pryprydt[7] = delayMs;
331 for (size_t i = 0; i < 6; ++i) {
332 // pitch, roll, yaw in degrees, referenced in degrees on the world frame.
333 // d_pitch, d_roll, d_yaw rotational velocity in degrees/s, based on the world frame.
334 pryprydt[i] *= RAD_TO_DEGREE;
Andy Hung78f13d12023-01-30 11:58:44 -0800335 }
Andy Hung9bcf4252023-02-27 13:36:23 -0800336 mHeadSensorRecorder.record(pryprydt);
337 mHeadSensorDurableRecorder.record(pryprydt);
Andy Hung78f13d12023-01-30 11:58:44 -0800338
Ytai Ben-Tsvi3c234b12022-01-31 11:15:17 -0800339 mProcessor->setWorldToHeadPose(timestamp, pose,
340 twist.value_or(Twist3f()) / kTicksPerSecond);
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700341 if (isNewReference) {
342 mProcessor->recenter(true, false);
343 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700344 }
345 if (sensor == mScreenSensor) {
Andy Hung78f13d12023-01-30 11:58:44 -0800346 std::vector<float> pryt{ 0.f, 0.f, 0.f, delayMs}; // pitch, roll, yaw, timestamp_delay
347 media::quaternionToAngles(pose.rotation(), &pryt[0], &pryt[1], &pryt[2]);
348 for (size_t i = 0; i < 3; ++i) {
349 pryt[i] *= RAD_TO_DEGREE;
350 }
351 mScreenSensorRecorder.record(pryt);
352 mScreenSensorDurableRecorder.record(pryt);
353
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700354 mProcessor->setWorldToScreenPose(timestamp, pose);
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700355 if (isNewReference) {
356 mProcessor->recenter(false, true);
357 }
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700358 }
359}
360
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000361std::string SpatializerPoseController::toString(unsigned level) const {
Andy Hung78f13d12023-01-30 11:58:44 -0800362 std::string prefixSpace(level, ' ');
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000363 std::string ss = prefixSpace + "SpatializerPoseController:\n";
364 bool needUnlock = false;
365
366 prefixSpace += ' ';
367 auto now = std::chrono::steady_clock::now();
368 if (!mMutex.try_lock_until(now + media::kSpatializerDumpSysTimeOutInSecond)) {
369 ss.append(prefixSpace).append("try_lock failed, dumpsys maybe INACCURATE!\n");
370 } else {
371 needUnlock = true;
372 }
373
374 ss += prefixSpace;
Shunkai Yao0324a392022-08-30 03:14:50 +0000375 if (mHeadSensor == INVALID_SENSOR) {
376 ss += "HeadSensor: INVALID\n";
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000377 } else {
Andy Hung9bcf4252023-02-27 13:36:23 -0800378 base::StringAppendF(&ss, "HeadSensor: 0x%08x "
379 "(active world-to-head : head-relative velocity) "
380 "[ pitch, roll, yaw : d_pitch, d_roll, d_yaw : disc : delay ] "
381 "(degrees, degrees/s, bool, ms)\n", mHeadSensor);
Andy Hung78f13d12023-01-30 11:58:44 -0800382 ss.append(prefixSpace)
383 .append(" PerMinuteHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -0800384 .append(mHeadSensorDurableRecorder.toString(level + 3))
Andy Hung78f13d12023-01-30 11:58:44 -0800385 .append(prefixSpace)
386 .append(" PerSecondHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -0800387 .append(mHeadSensorRecorder.toString(level + 3));
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000388 }
389
390 ss += prefixSpace;
Shunkai Yao0324a392022-08-30 03:14:50 +0000391 if (mScreenSensor == INVALID_SENSOR) {
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000392 ss += "ScreenSensor: INVALID\n";
393 } else {
Andy Hung78f13d12023-01-30 11:58:44 -0800394 base::StringAppendF(&ss, "ScreenSensor: 0x%08x (active world-to-screen) "
Andy Hung9bcf4252023-02-27 13:36:23 -0800395 "[ pitch, roll, yaw : delay ] "
Andy Hung78f13d12023-01-30 11:58:44 -0800396 "(degrees, ms)\n", mScreenSensor);
397 ss.append(prefixSpace)
398 .append(" PerMinuteHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -0800399 .append(mScreenSensorDurableRecorder.toString(level + 3))
Andy Hung78f13d12023-01-30 11:58:44 -0800400 .append(prefixSpace)
401 .append(" PerSecondHistory:\n")
Andy Hung9bcf4252023-02-27 13:36:23 -0800402 .append(mScreenSensorRecorder.toString(level + 3));
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000403 }
404
405 ss += prefixSpace;
406 if (mActualMode.has_value()) {
Shunkai Yao0324a392022-08-30 03:14:50 +0000407 base::StringAppendF(&ss, "ActualMode: %s\n", media::toString(mActualMode.value()).c_str());
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000408 } else {
409 ss += "ActualMode NOTEXIST\n";
410 }
411
412 if (mProcessor) {
413 ss += mProcessor->toString_l(level + 1);
414 } else {
415 ss.append(prefixSpace.c_str()).append("HeadTrackingProcessor not exist\n");
416 }
417
418 if (mPoseProvider) {
419 ss += mPoseProvider->toString(level + 1);
420 } else {
421 ss.append(prefixSpace.c_str()).append("SensorPoseProvider not exist\n");
422 }
423
424 if (needUnlock) {
425 mMutex.unlock();
426 }
427 // TODO: 233092747 add history sensor info with SimpleLog.
428 return ss;
429}
430
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700431} // namespace android