blob: 2ac2af79b5089139a4eba4d36cc3bd02dd6ed120 [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 Hung49798b22023-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
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -070025#include <sensor/Sensor.h>
Andy Hunga461a002022-05-17 10:36:02 -070026#include <media/MediaMetricsItem.h>
Andy Hung49798b22023-01-30 11:58:44 -080027#include <media/QuaternionUtil.h>
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070028#include <utils/Log.h>
29#include <utils/SystemClock.h>
30
31namespace android {
32
33using media::createHeadTrackingProcessor;
34using media::HeadTrackingMode;
35using media::HeadTrackingProcessor;
36using media::Pose3f;
37using media::SensorPoseProvider;
38using media::Twist3f;
39
40using namespace std::chrono_literals;
41
42namespace {
43
44// This is how fast, in m/s, we allow position to shift during rate-limiting.
Ytai Ben-Tsvic2d28402022-01-14 14:55:16 -080045constexpr float kMaxTranslationalVelocity = 2;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070046
47// This is how fast, in rad/s, we allow rotation angle to shift during rate-limiting.
Nikhil Bhanub6618712022-09-19 16:31:35 -070048constexpr float kMaxRotationalVelocity = 0.8f;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070049
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070050// This is how far into the future we predict the head pose, using linear extrapolation based on
51// twist (velocity). It should be set to a value that matches the characteristic durations of moving
52// one's head. The higher we set this, the more latency we are able to reduce, but setting this too
53// high will result in high prediction errors whenever the head accelerates (changes velocity).
Ytai Ben-Tsvi3c234b12022-01-31 11:15:17 -080054constexpr auto kPredictionDuration = 50ms;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070055
Ytai Ben-Tsvie2356842022-04-14 11:30:32 -070056// After not getting a pose sample for this long, we would treat the measurement as stale.
Shunkai Yao66b4eb72022-08-31 19:22:06 +000057// The max connection interval is 50ms, and HT sensor event interval can differ depending on the
58// sampling rate, scheduling, sensor eventQ FIFO etc. 120 (2 * 50 + 20) ms seems reasonable for now.
59constexpr auto kFreshnessTimeout = 120ms;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070060
Ytai Ben-Tsvi44e7c3d2021-12-15 16:04:01 -080061// Auto-recenter kicks in after the head has been still for this long.
Ytai Ben-Tsvicdc03062022-01-10 15:57:52 -080062constexpr auto kAutoRecenterWindowDuration = 6s;
Ytai Ben-Tsvi44e7c3d2021-12-15 16:04:01 -080063
64// Auto-recenter considers head not still if translated by this much (in meters, approx).
65constexpr float kAutoRecenterTranslationThreshold = 0.1f;
66
67// Auto-recenter considers head not still if rotated by this much (in radians, approx).
Ytai Ben-Tsvi237012c2022-02-16 15:54:31 -080068constexpr float kAutoRecenterRotationThreshold = 10.5f / 180 * M_PI;
Ytai Ben-Tsvi44e7c3d2021-12-15 16:04:01 -080069
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -080070// Screen is considered to be unstable (not still) if it has moved significantly within the last
71// time window of this duration.
Robert Daltonec0c3282022-08-26 10:33:34 +000072constexpr auto kScreenStillnessWindowDuration = 750ms;
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -080073
74// Screen is considered to have moved significantly if translated by this much (in meter, approx).
75constexpr float kScreenStillnessTranslationThreshold = 0.1f;
76
77// Screen is considered to have moved significantly if rotated by this much (in radians, approx).
Robert Daltonec0c3282022-08-26 10:33:34 +000078constexpr float kScreenStillnessRotationThreshold = 15.0f / 180 * M_PI;
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -080079
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070080// Time units for system clock ticks. This is what the Sensor Framework timestamps represent and
81// what we use for pose filtering.
82using Ticks = std::chrono::nanoseconds;
83
84// How many ticks in a second.
85constexpr auto kTicksPerSecond = Ticks::period::den;
86
Andy Hunga461a002022-05-17 10:36:02 -070087std::string getSensorMetricsId(int32_t sensorId) {
88 return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_SENSOR).append(std::to_string(sensorId));
89}
90
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070091} // namespace
92
93SpatializerPoseController::SpatializerPoseController(Listener* listener,
Eric Laurente51f80e2022-04-14 10:20:38 +020094 std::chrono::microseconds sensorPeriod,
95 std::optional<std::chrono::microseconds> maxUpdatePeriod)
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070096 : mListener(listener),
97 mSensorPeriod(sensorPeriod),
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070098 mProcessor(createHeadTrackingProcessor(HeadTrackingProcessor::Options{
99 .maxTranslationalVelocity = kMaxTranslationalVelocity / kTicksPerSecond,
100 .maxRotationalVelocity = kMaxRotationalVelocity / kTicksPerSecond,
Ytai Ben-Tsvie2356842022-04-14 11:30:32 -0700101 .freshnessTimeout = Ticks(kFreshnessTimeout).count(),
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700102 .predictionDuration = Ticks(kPredictionDuration).count(),
Ytai Ben-Tsvi44e7c3d2021-12-15 16:04:01 -0800103 .autoRecenterWindowDuration = Ticks(kAutoRecenterWindowDuration).count(),
104 .autoRecenterTranslationalThreshold = kAutoRecenterTranslationThreshold,
105 .autoRecenterRotationalThreshold = kAutoRecenterRotationThreshold,
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -0800106 .screenStillnessWindowDuration = Ticks(kScreenStillnessWindowDuration).count(),
107 .screenStillnessTranslationalThreshold = kScreenStillnessTranslationThreshold,
108 .screenStillnessRotationalThreshold = kScreenStillnessRotationThreshold,
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700109 })),
Ytai Ben-Tsvi8b6fe3a2021-09-13 15:55:44 -0700110 mPoseProvider(SensorPoseProvider::create("headtracker", this)),
Keith Mok30099472022-06-06 21:40:11 +0000111 mThread([this, maxUpdatePeriod] { // It's important that mThread is initialized after
112 // everything else because it runs a member
113 // function that may use any member
114 // of this class.
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700115 while (true) {
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700116 Pose3f headToStage;
117 std::optional<HeadTrackingMode> modeIfChanged;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700118 {
119 std::unique_lock lock(mMutex);
Eric Laurente51f80e2022-04-14 10:20:38 +0200120 if (maxUpdatePeriod.has_value()) {
121 mCondVar.wait_for(lock, maxUpdatePeriod.value(),
122 [this] { return mShouldExit || mShouldCalculate; });
123 } else {
124 mCondVar.wait(lock, [this] { return mShouldExit || mShouldCalculate; });
125 }
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700126 if (mShouldExit) {
127 ALOGV("Exiting thread");
128 return;
129 }
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700130
131 // Calculate.
132 std::tie(headToStage, modeIfChanged) = calculate_l();
133 }
134
135 // Invoke the callbacks outside the lock.
136 mListener->onHeadToStagePose(headToStage);
137 if (modeIfChanged) {
138 mListener->onActualModeChange(modeIfChanged.value());
139 }
140
141 {
142 std::lock_guard lock(mMutex);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700143 if (!mCalculated) {
144 mCalculated = true;
145 mCondVar.notify_all();
146 }
147 mShouldCalculate = false;
148 }
149 }
150 }) {}
151
152SpatializerPoseController::~SpatializerPoseController() {
153 {
154 std::unique_lock lock(mMutex);
155 mShouldExit = true;
156 mCondVar.notify_all();
157 }
158 mThread.join();
159}
160
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700161void SpatializerPoseController::setHeadSensor(int32_t sensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700162 std::lock_guard lock(mMutex);
Andy Hungba2a61a2022-05-20 12:00:28 -0700163 if (sensor == mHeadSensor) return;
164 ALOGV("%s: new sensor:%d mHeadSensor:%d mScreenSensor:%d",
165 __func__, sensor, mHeadSensor, mScreenSensor);
166
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700167 // Stop current sensor, if valid and different from the other sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700168 if (mHeadSensor != INVALID_SENSOR && mHeadSensor != mScreenSensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700169 mPoseProvider->stopSensor(mHeadSensor);
Andy Hunga461a002022-05-17 10:36:02 -0700170 mediametrics::LogItem(getSensorMetricsId(mHeadSensor))
171 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
172 .record();
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700173 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700174
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700175 if (sensor != INVALID_SENSOR) {
176 if (sensor != mScreenSensor) {
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700177 // Start new sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700178 mHeadSensor =
179 mPoseProvider->startSensor(sensor, mSensorPeriod) ? sensor : INVALID_SENSOR;
Andy Hunga461a002022-05-17 10:36:02 -0700180 if (mHeadSensor != INVALID_SENSOR) {
181 auto sensor = mPoseProvider->getSensorByHandle(mHeadSensor);
182 std::string stringType = sensor ? sensor->getStringType().c_str() : "";
183 mediametrics::LogItem(getSensorMetricsId(mHeadSensor))
184 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
185 .set(AMEDIAMETRICS_PROP_MODE, AMEDIAMETRICS_PROP_MODE_VALUE_HEAD)
186 .set(AMEDIAMETRICS_PROP_TYPE, stringType)
187 .record();
188 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700189 } else {
190 // Sensor is already enabled.
191 mHeadSensor = mScreenSensor;
192 }
193 } else {
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700194 mHeadSensor = INVALID_SENSOR;
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700195 }
196
Eric Laurentf8a85262023-01-23 17:49:04 +0100197 mProcessor->recenter(true /* recenterHead */, false /* recenterScreen */, __func__);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700198}
199
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700200void SpatializerPoseController::setScreenSensor(int32_t sensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700201 std::lock_guard lock(mMutex);
Andy Hungba2a61a2022-05-20 12:00:28 -0700202 if (sensor == mScreenSensor) return;
203 ALOGV("%s: new sensor:%d mHeadSensor:%d mScreenSensor:%d",
204 __func__, sensor, mHeadSensor, mScreenSensor);
205
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700206 // Stop current sensor, if valid and different from the other sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700207 if (mScreenSensor != INVALID_SENSOR && mScreenSensor != mHeadSensor) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700208 mPoseProvider->stopSensor(mScreenSensor);
Andy Hunga461a002022-05-17 10:36:02 -0700209 mediametrics::LogItem(getSensorMetricsId(mScreenSensor))
210 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
211 .record();
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700212 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700213
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700214 if (sensor != INVALID_SENSOR) {
215 if (sensor != mHeadSensor) {
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700216 // Start new sensor.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700217 mScreenSensor =
218 mPoseProvider->startSensor(sensor, mSensorPeriod) ? sensor : INVALID_SENSOR;
Andy Hunga461a002022-05-17 10:36:02 -0700219 auto sensor = mPoseProvider->getSensorByHandle(mScreenSensor);
220 std::string stringType = sensor ? sensor->getStringType().c_str() : "";
221 mediametrics::LogItem(getSensorMetricsId(mScreenSensor))
222 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
223 .set(AMEDIAMETRICS_PROP_MODE, AMEDIAMETRICS_PROP_MODE_VALUE_SCREEN)
224 .set(AMEDIAMETRICS_PROP_TYPE, stringType)
225 .record();
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700226 } else {
227 // Sensor is already enabled.
228 mScreenSensor = mHeadSensor;
229 }
230 } else {
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -0700231 mScreenSensor = INVALID_SENSOR;
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700232 }
233
Eric Laurentf8a85262023-01-23 17:49:04 +0100234 mProcessor->recenter(false /* recenterHead */, true /* recenterScreen */, __func__);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700235}
236
237void SpatializerPoseController::setDesiredMode(HeadTrackingMode mode) {
238 std::lock_guard lock(mMutex);
239 mProcessor->setDesiredMode(mode);
240}
241
242void SpatializerPoseController::setScreenToStagePose(const Pose3f& screenToStage) {
243 std::lock_guard lock(mMutex);
244 mProcessor->setScreenToStagePose(screenToStage);
245}
246
247void SpatializerPoseController::setDisplayOrientation(float physicalToLogicalAngle) {
248 std::lock_guard lock(mMutex);
249 mProcessor->setDisplayOrientation(physicalToLogicalAngle);
250}
251
252void SpatializerPoseController::calculateAsync() {
253 std::lock_guard lock(mMutex);
254 mShouldCalculate = true;
255 mCondVar.notify_all();
256}
257
258void SpatializerPoseController::waitUntilCalculated() {
259 std::unique_lock lock(mMutex);
260 mCondVar.wait(lock, [this] { return mCalculated; });
261}
262
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700263std::tuple<media::Pose3f, std::optional<media::HeadTrackingMode>>
264SpatializerPoseController::calculate_l() {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700265 Pose3f headToStage;
266 HeadTrackingMode mode;
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700267 std::optional<media::HeadTrackingMode> modeIfChanged;
268
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700269 mProcessor->calculate(elapsedRealtimeNano());
270 headToStage = mProcessor->getHeadToStagePose();
271 mode = mProcessor->getActualMode();
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700272 if (!mActualMode.has_value() || mActualMode.value() != mode) {
273 mActualMode = mode;
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700274 modeIfChanged = mode;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700275 }
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700276 return std::make_tuple(headToStage, modeIfChanged);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700277}
278
279void SpatializerPoseController::recenter() {
280 std::lock_guard lock(mMutex);
Eric Laurentf8a85262023-01-23 17:49:04 +0100281 mProcessor->recenter(true /* recenterHead */, true /* recenterScreen */, __func__);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700282}
283
284void SpatializerPoseController::onPose(int64_t timestamp, int32_t sensor, const Pose3f& pose,
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700285 const std::optional<Twist3f>& twist, bool isNewReference) {
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700286 std::lock_guard lock(mMutex);
Andy Hung49798b22023-01-30 11:58:44 -0800287 constexpr float NANOS_TO_MILLIS = 1e-6;
288 constexpr float RAD_TO_DEGREE = 180.f / M_PI;
289
290 const float delayMs = (elapsedRealtimeNano() - timestamp) * NANOS_TO_MILLIS; // CLOCK_BOOTTIME
291
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700292 if (sensor == mHeadSensor) {
Andy Hung49798b22023-01-30 11:58:44 -0800293 std::vector<float> pryxyzdt(8); // pitch, roll, yaw, rot_vel_x, rot_vel_y, rot_vel_z,
294 // discontinuity, timestamp_delay
295 media::quaternionToAngles(pose.rotation(), &pryxyzdt[0], &pryxyzdt[1], &pryxyzdt[2]);
296 if (twist) {
297 const auto rotationalVelocity = twist->rotationalVelocity();
298 for (size_t i = 0; i < 3; ++i) {
299 pryxyzdt[i + 3] = rotationalVelocity[i];
300 }
301 }
302 pryxyzdt[6] = isNewReference;
303 pryxyzdt[7] = delayMs;
304 for (size_t i = 0; i < 3; ++i) { // pitch, roll, yaw only. rotational velocity in rad/s.
305 pryxyzdt[i] *= RAD_TO_DEGREE;
306 }
307 mHeadSensorRecorder.record(pryxyzdt);
308 mHeadSensorDurableRecorder.record(pryxyzdt);
309
Ytai Ben-Tsvi3c234b12022-01-31 11:15:17 -0800310 mProcessor->setWorldToHeadPose(timestamp, pose,
311 twist.value_or(Twist3f()) / kTicksPerSecond);
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700312 if (isNewReference) {
Eric Laurentf8a85262023-01-23 17:49:04 +0100313 mProcessor->recenter(true, false, __func__);
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700314 }
Ytai Ben-Tsvi9bae7422021-08-27 16:13:19 -0700315 }
316 if (sensor == mScreenSensor) {
Andy Hung49798b22023-01-30 11:58:44 -0800317 std::vector<float> pryt{ 0.f, 0.f, 0.f, delayMs}; // pitch, roll, yaw, timestamp_delay
318 media::quaternionToAngles(pose.rotation(), &pryt[0], &pryt[1], &pryt[2]);
319 for (size_t i = 0; i < 3; ++i) {
320 pryt[i] *= RAD_TO_DEGREE;
321 }
322 mScreenSensorRecorder.record(pryt);
323 mScreenSensorDurableRecorder.record(pryt);
324
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700325 mProcessor->setWorldToScreenPose(timestamp, pose);
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700326 if (isNewReference) {
Eric Laurentf8a85262023-01-23 17:49:04 +0100327 mProcessor->recenter(false, true, __func__);
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700328 }
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700329 }
330}
331
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000332std::string SpatializerPoseController::toString(unsigned level) const {
Andy Hung49798b22023-01-30 11:58:44 -0800333 std::string prefixSpace(level, ' ');
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000334 std::string ss = prefixSpace + "SpatializerPoseController:\n";
335 bool needUnlock = false;
336
337 prefixSpace += ' ';
338 auto now = std::chrono::steady_clock::now();
339 if (!mMutex.try_lock_until(now + media::kSpatializerDumpSysTimeOutInSecond)) {
340 ss.append(prefixSpace).append("try_lock failed, dumpsys maybe INACCURATE!\n");
341 } else {
342 needUnlock = true;
343 }
344
345 ss += prefixSpace;
Shunkai Yao0324a392022-08-30 03:14:50 +0000346 if (mHeadSensor == INVALID_SENSOR) {
347 ss += "HeadSensor: INVALID\n";
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000348 } else {
Andy Hung49798b22023-01-30 11:58:44 -0800349 base::StringAppendF(&ss, "HeadSensor: 0x%08x (active world-to-head) "
350 "[ pitch, roll, yaw, vx, vy, vz, disc, delay ] "
351 "(degrees, rad/s, bool, ms)\n", mHeadSensor);
352 ss.append(prefixSpace)
353 .append(" PerMinuteHistory:\n")
354 .append(mHeadSensorDurableRecorder.toString(level + 2))
355 .append(prefixSpace)
356 .append(" PerSecondHistory:\n")
357 .append(mHeadSensorRecorder.toString(level + 2));
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000358 }
359
360 ss += prefixSpace;
Shunkai Yao0324a392022-08-30 03:14:50 +0000361 if (mScreenSensor == INVALID_SENSOR) {
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000362 ss += "ScreenSensor: INVALID\n";
363 } else {
Andy Hung49798b22023-01-30 11:58:44 -0800364 base::StringAppendF(&ss, "ScreenSensor: 0x%08x (active world-to-screen) "
365 "[ pitch, roll, yaw, delay ] "
366 "(degrees, ms)\n", mScreenSensor);
367 ss.append(prefixSpace)
368 .append(" PerMinuteHistory:\n")
369 .append(mScreenSensorDurableRecorder.toString(level + 2))
370 .append(prefixSpace)
371 .append(" PerSecondHistory:\n")
372 .append(mScreenSensorRecorder.toString(level + 2));
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000373 }
374
375 ss += prefixSpace;
376 if (mActualMode.has_value()) {
Shunkai Yao0324a392022-08-30 03:14:50 +0000377 base::StringAppendF(&ss, "ActualMode: %s\n", media::toString(mActualMode.value()).c_str());
Shunkai Yao59b27bc2022-07-22 18:42:27 +0000378 } else {
379 ss += "ActualMode NOTEXIST\n";
380 }
381
382 if (mProcessor) {
383 ss += mProcessor->toString_l(level + 1);
384 } else {
385 ss.append(prefixSpace.c_str()).append("HeadTrackingProcessor not exist\n");
386 }
387
388 if (mPoseProvider) {
389 ss += mPoseProvider->toString(level + 1);
390 } else {
391 ss.append(prefixSpace.c_str()).append("SensorPoseProvider not exist\n");
392 }
393
394 if (needUnlock) {
395 mMutex.unlock();
396 }
397 // TODO: 233092747 add history sensor info with SimpleLog.
398 return ss;
399}
400
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700401} // namespace android