Merge changes Ie494e03f,Ia85d5699,I7f5a39a0

* changes:
  Tune head pose processing parameters
  Force "not still" for the duration of the window after motion
  Consider the screen still until proven otherwise
diff --git a/media/libheadtracking/HeadTrackingProcessor.cpp b/media/libheadtracking/HeadTrackingProcessor.cpp
index 257ee42..b2d2dbd 100644
--- a/media/libheadtracking/HeadTrackingProcessor.cpp
+++ b/media/libheadtracking/HeadTrackingProcessor.cpp
@@ -42,11 +42,13 @@
                   .rotationalDriftTimeConstant = options.rotationalDriftTimeConstant,
           }),
           mHeadStillnessDetector(StillnessDetector::Options{
+                  .defaultValue = false,
                   .windowDuration = options.autoRecenterWindowDuration,
                   .translationalThreshold = options.autoRecenterTranslationalThreshold,
                   .rotationalThreshold = options.autoRecenterRotationalThreshold,
           }),
           mScreenStillnessDetector(StillnessDetector::Options{
+                  .defaultValue = true,
                   .windowDuration = options.screenStillnessWindowDuration,
                   .translationalThreshold = options.screenStillnessTranslationalThreshold,
                   .rotationalThreshold = options.screenStillnessRotationalThreshold,
diff --git a/media/libheadtracking/StillnessDetector-test.cpp b/media/libheadtracking/StillnessDetector-test.cpp
index 29b036e..02f9d8a 100644
--- a/media/libheadtracking/StillnessDetector-test.cpp
+++ b/media/libheadtracking/StillnessDetector-test.cpp
@@ -28,101 +28,146 @@
 using Eigen::Vector3f;
 using Options = StillnessDetector::Options;
 
-TEST(StillnessDetectorTest, Still) {
-    StillnessDetector detector(Options{
-            .windowDuration = 1000, .translationalThreshold = 1, .rotationalThreshold = 0.05});
+class StillnessDetectorTest : public testing::TestWithParam<bool> {
+  public:
+    void SetUp() override { mDefaultValue = GetParam(); }
+
+  protected:
+    bool mDefaultValue;
+};
+
+TEST_P(StillnessDetectorTest, Still) {
+    StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+                                       .windowDuration = 1000,
+                                       .translationalThreshold = 1,
+                                       .rotationalThreshold = 0.05});
 
     const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
     const Pose3f withinThreshold =
             baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.01) * rotateY(-0.01));
 
-    EXPECT_FALSE(detector.calculate(0));
+    EXPECT_EQ(mDefaultValue, detector.calculate(0));
     detector.setInput(0, baseline);
-    EXPECT_FALSE(detector.calculate(0));
+    EXPECT_EQ(mDefaultValue, detector.calculate(0));
     detector.setInput(300, withinThreshold);
-    EXPECT_FALSE(detector.calculate(300));
+    EXPECT_EQ(mDefaultValue, detector.calculate(300));
     detector.setInput(600, baseline);
-    EXPECT_FALSE(detector.calculate(600));
+    EXPECT_EQ(mDefaultValue, detector.calculate(600));
     detector.setInput(999, withinThreshold);
-    EXPECT_FALSE(detector.calculate(999));
+    EXPECT_EQ(mDefaultValue, detector.calculate(999));
     detector.setInput(1000, baseline);
     EXPECT_TRUE(detector.calculate(1000));
 }
 
-TEST(StillnessDetectorTest, ZeroDuration) {
-    StillnessDetector detector(Options{.windowDuration = 0});
+TEST_P(StillnessDetectorTest, ZeroDuration) {
+    StillnessDetector detector(Options{.defaultValue = mDefaultValue, .windowDuration = 0});
     EXPECT_TRUE(detector.calculate(0));
     EXPECT_TRUE(detector.calculate(1000));
 }
 
-TEST(StillnessDetectorTest, NotStillTranslation) {
-    StillnessDetector detector(Options{
-            .windowDuration = 1000, .translationalThreshold = 1, .rotationalThreshold = 0.05});
+TEST_P(StillnessDetectorTest, NotStillTranslation) {
+    StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+                                       .windowDuration = 1000,
+                                       .translationalThreshold = 1,
+                                       .rotationalThreshold = 0.05});
 
     const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
     const Pose3f withinThreshold =
             baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.01) * rotateY(-0.01));
     const Pose3f outsideThreshold = baseline * Pose3f(Vector3f(1, 1, 0));
 
-    EXPECT_FALSE(detector.calculate(0));
+    EXPECT_EQ(mDefaultValue, detector.calculate(0));
     detector.setInput(0, baseline);
-    EXPECT_FALSE(detector.calculate(0));
+    EXPECT_EQ(mDefaultValue, detector.calculate(0));
     detector.setInput(300, outsideThreshold);
-    EXPECT_FALSE(detector.calculate(300));
+    EXPECT_EQ(mDefaultValue, detector.calculate(300));
     detector.setInput(600, baseline);
-    EXPECT_FALSE(detector.calculate(600));
+    EXPECT_EQ(mDefaultValue, detector.calculate(600));
     detector.setInput(900, withinThreshold);
-    EXPECT_FALSE(detector.calculate(900));
-    detector.setInput(1299, baseline);
-    EXPECT_FALSE(detector.calculate(1299));
-    EXPECT_TRUE(detector.calculate(1300));
+    EXPECT_EQ(mDefaultValue, detector.calculate(900));
+    detector.setInput(1300, baseline);
+    EXPECT_FALSE(detector.calculate(1300));
+    detector.setInput(1500, baseline);
+    EXPECT_FALSE(detector.calculate(1899));
+    EXPECT_TRUE(detector.calculate(1900));
 }
 
-TEST(StillnessDetectorTest, NotStillRotation) {
-    StillnessDetector detector(Options{
-            .windowDuration = 1000, .translationalThreshold = 1, .rotationalThreshold = 0.05});
+TEST_P(StillnessDetectorTest, NotStillRotation) {
+    StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+                                       .windowDuration = 1000,
+                                       .translationalThreshold = 1,
+                                       .rotationalThreshold = 0.05});
 
     const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
     const Pose3f withinThreshold =
             baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.03) * rotateY(-0.03));
     const Pose3f outsideThreshold = baseline * Pose3f(rotateZ(0.06));
-    EXPECT_FALSE(detector.calculate(0));
+
+    EXPECT_EQ(mDefaultValue, detector.calculate(0));
     detector.setInput(0, baseline);
-    EXPECT_FALSE(detector.calculate(0));
+    EXPECT_EQ(mDefaultValue, detector.calculate(0));
     detector.setInput(300, outsideThreshold);
-    EXPECT_FALSE(detector.calculate(300));
+    EXPECT_EQ(mDefaultValue, detector.calculate(300));
     detector.setInput(600, baseline);
-    EXPECT_FALSE(detector.calculate(600));
+    EXPECT_EQ(mDefaultValue, detector.calculate(600));
     detector.setInput(900, withinThreshold);
-    EXPECT_FALSE(detector.calculate(900));
-    detector.setInput(1299, baseline);
-    EXPECT_FALSE(detector.calculate(1299));
-    EXPECT_TRUE(detector.calculate(1300));
+    EXPECT_EQ(mDefaultValue, detector.calculate(900));
+    detector.setInput(1300, baseline);
+    EXPECT_FALSE(detector.calculate(1300));
+    detector.setInput(1500, baseline);
+    EXPECT_FALSE(detector.calculate(1899));
+    EXPECT_TRUE(detector.calculate(1900));
 }
 
-TEST(StillnessDetectorTest, Reset) {
-    StillnessDetector detector(Options{
-            .windowDuration = 1000, .translationalThreshold = 1, .rotationalThreshold = 0.05});
+TEST_P(StillnessDetectorTest, Suppression) {
+    StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+                                       .windowDuration = 1000,
+                                       .translationalThreshold = 1,
+                                       .rotationalThreshold = 0.05});
+
+    const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
+    const Pose3f outsideThreshold = baseline * Pose3f(Vector3f(1.1, 0, 0));
+    const Pose3f middlePoint = baseline * Pose3f(Vector3f(0.55, 0, 0));
+
+    detector.setInput(0, baseline);
+    detector.setInput(1000, baseline);
+    EXPECT_TRUE(detector.calculate(1000));
+    detector.setInput(1100, outsideThreshold);
+    EXPECT_FALSE(detector.calculate(1100));
+    detector.setInput(2000, middlePoint);
+    EXPECT_FALSE(detector.calculate(2000));
+    EXPECT_FALSE(detector.calculate(2099));
+    EXPECT_TRUE(detector.calculate(2100));
+}
+
+TEST_P(StillnessDetectorTest, Reset) {
+    StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+                                       .windowDuration = 1000,
+                                       .translationalThreshold = 1,
+                                       .rotationalThreshold = 0.05});
 
     const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
     const Pose3f withinThreshold =
             baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.01) * rotateY(-0.01));
-    EXPECT_FALSE(detector.calculate(0));
+    EXPECT_EQ(mDefaultValue, detector.calculate(0));
     detector.setInput(0, baseline);
-    EXPECT_FALSE(detector.calculate(0));
+    EXPECT_EQ(mDefaultValue, detector.calculate(0));
     detector.reset();
     detector.setInput(600, baseline);
-    EXPECT_FALSE(detector.calculate(600));
+    EXPECT_EQ(mDefaultValue, detector.calculate(600));
     detector.setInput(900, withinThreshold);
-    EXPECT_FALSE(detector.calculate(900));
+    EXPECT_EQ(mDefaultValue, detector.calculate(900));
     detector.setInput(1200, baseline);
-    EXPECT_FALSE(detector.calculate(1200));
+    EXPECT_EQ(mDefaultValue, detector.calculate(1200));
     detector.setInput(1599, withinThreshold);
-    EXPECT_FALSE(detector.calculate(1599));
+    EXPECT_EQ(mDefaultValue, detector.calculate(1599));
     detector.setInput(1600, baseline);
     EXPECT_TRUE(detector.calculate(1600));
 }
 
+INSTANTIATE_TEST_SUITE_P(StillnessDetectorTestParametrized, StillnessDetectorTest,
+                         testing::Values(false, true));
+
 }  // namespace
 }  // namespace media
 }  // namespace android
diff --git a/media/libheadtracking/StillnessDetector.cpp b/media/libheadtracking/StillnessDetector.cpp
index 5fa4e3a..9806352 100644
--- a/media/libheadtracking/StillnessDetector.cpp
+++ b/media/libheadtracking/StillnessDetector.cpp
@@ -25,6 +25,7 @@
 void StillnessDetector::reset() {
     mFifo.clear();
     mWindowFull = false;
+    mSuppressionDeadline.reset();
 }
 
 void StillnessDetector::setInput(int64_t timestamp, const Pose3f& input) {
@@ -35,27 +36,34 @@
 bool StillnessDetector::calculate(int64_t timestamp) {
     discardOld(timestamp);
 
-    // If the window has not been full, we don't consider ourselves still.
-    if (!mWindowFull) {
-        return false;
-    }
+    // Check whether all the poses in the queue are in the proximity of the new
+    // one. We want to do this before checking the overriding conditions below, in order to update
+    // the suppression deadline correctly.
+    bool moved = false;
 
-    // An empty FIFO and window full is considered still (this will happen in the unlikely case when
-    // the window duration is shorter than the gap between samples).
-    if (mFifo.empty()) {
-        return true;
-    }
-
-    // Otherwise, check whether all the poses remaining in the queue are in the proximity of the new
-    // one.
-    for (auto iter = mFifo.begin(); iter != mFifo.end() - 1; ++iter) {
-        const auto& event = *iter;
-        if (!areNear(event.pose, mFifo.back().pose)) {
-            return false;
+    if (!mFifo.empty()) {
+        for (auto iter = mFifo.begin(); iter != mFifo.end() - 1; ++iter) {
+            const auto& event = *iter;
+            if (!areNear(event.pose, mFifo.back().pose)) {
+                // Enable suppression for the duration of the window.
+                mSuppressionDeadline = timestamp + mOptions.windowDuration;
+                moved = true;
+                break;
+            }
         }
     }
 
-    return true;
+    // If the window has not been full, return the default value.
+    if (!mWindowFull) {
+        return mOptions.defaultValue;
+    }
+
+    // Force "in motion" while the suppression deadline is active.
+    if (mSuppressionDeadline.has_value()) {
+        return false;
+    }
+
+    return !moved;
 }
 
 void StillnessDetector::discardOld(int64_t timestamp) {
@@ -72,6 +80,11 @@
         mWindowFull = true;
         mFifo.pop_front();
     }
+
+    // Expire the suppression deadline.
+    if (mSuppressionDeadline.has_value() && mSuppressionDeadline <= timestamp) {
+        mSuppressionDeadline.reset();
+    }
 }
 
 bool StillnessDetector::areNear(const Pose3f& pose1, const Pose3f& pose2) const {
diff --git a/media/libheadtracking/StillnessDetector.h b/media/libheadtracking/StillnessDetector.h
index cae9d9d..ee4b2d8 100644
--- a/media/libheadtracking/StillnessDetector.h
+++ b/media/libheadtracking/StillnessDetector.h
@@ -36,10 +36,11 @@
  *    bool still = detector.calculate(timestamp);
  * }
  *
- * The stream is considered not still until a sufficient number of samples has been provided for an
- * initial fill-up of the window. In the special case of the window size being 0, this is not
- * required and the state is considered always "still". The reset() method can be used to empty the
- * window again and get back to this initial state.
+ * The detection is not considered reliable until a sufficient number of samples has been provided
+ * for an initial fill-up of the window. During that time, the detector will return whatever default
+ * value has been configured.
+ * The reset() method can be used to empty the window again and get back to this initial state.
+ * In the special case of the window size being 0, the state will always be considered "still".
  */
 class StillnessDetector {
   public:
@@ -48,6 +49,10 @@
      */
     struct Options {
         /**
+         * During the initial fill of the window, should we consider the state still?
+         */
+         bool defaultValue;
+        /**
          * How long is the window, in ticks. The special value of 0 indicates that the stream is
          * always considered still.
          */
@@ -87,6 +92,11 @@
     const float mCosHalfRotationalThreshold;
     std::deque<TimestampedPose> mFifo;
     bool mWindowFull = false;
+    // As soon as motion is detected, this will be set for the time of detection + window duration,
+    // and during this time we will always consider outselves in motion without checking. This is
+    // used for hyteresis purposes, since because of the approximate method we use for determining
+    // stillness, we may toggle back and forth at a rate faster than the window side.
+    std::optional<int64_t> mSuppressionDeadline;
 
     bool areNear(const Pose3f& pose1, const Pose3f& pose2) const;
     void discardOld(int64_t timestamp);
diff --git a/services/audiopolicy/service/SpatializerPoseController.cpp b/services/audiopolicy/service/SpatializerPoseController.cpp
index 80a3d29..cb017f0 100644
--- a/services/audiopolicy/service/SpatializerPoseController.cpp
+++ b/services/audiopolicy/service/SpatializerPoseController.cpp
@@ -38,7 +38,7 @@
 constexpr auto kMaxTranslationalVelocity = 2;
 
 // This is how fast, in rad/s, we allow rotation angle to shift during rate-limiting.
-constexpr auto kMaxRotationalVelocity = 4 * M_PI;
+constexpr auto kMaxRotationalVelocity = 8;
 
 // This should be set to the typical time scale that the translation sensors used drift in. This
 // means, loosely, for how long we can trust the reading to be "accurate enough". This would
@@ -65,23 +65,23 @@
 constexpr auto kMaxLostSamples = 4;
 
 // Auto-recenter kicks in after the head has been still for this long.
-constexpr auto kAutoRecenterWindowDuration = 10s;
+constexpr auto kAutoRecenterWindowDuration = 6s;
 
 // Auto-recenter considers head not still if translated by this much (in meters, approx).
 constexpr float kAutoRecenterTranslationThreshold = 0.1f;
 
 // Auto-recenter considers head not still if rotated by this much (in radians, approx).
-constexpr float kAutoRecenterRotationThreshold = 5.0f / 180 * M_PI;
+constexpr float kAutoRecenterRotationThreshold = 7.0f / 180 * M_PI;
 
 // Screen is considered to be unstable (not still) if it has moved significantly within the last
 // time window of this duration.
-constexpr auto kScreenStillnessWindowDuration = 10s;
+constexpr auto kScreenStillnessWindowDuration = 3s;
 
 // Screen is considered to have moved significantly if translated by this much (in meter, approx).
 constexpr float kScreenStillnessTranslationThreshold = 0.1f;
 
 // Screen is considered to have moved significantly if rotated by this much (in radians, approx).
-constexpr float kScreenStillnessRotationThreshold = 5.0f / 180 * M_PI;
+constexpr float kScreenStillnessRotationThreshold = 7.0f / 180 * M_PI;
 
 // Time units for system clock ticks. This is what the Sensor Framework timestamps represent and
 // what we use for pose filtering.