Change setDiscontinuity API

Require clients to specify mode for each discontinuity.

Zero mode discontinuities cannot be cleared. Pending
continuous mode discontinuities are cleared by zero mode
discontinuities.

Test: atest timestampverifier_tests
Change-Id: I5596b955b86cf489f44530d8092b3c85f056c1a8
diff --git a/audio_utils/include/audio_utils/TimestampVerifier.h b/audio_utils/include/audio_utils/TimestampVerifier.h
index a09c528..ed27cac 100644
--- a/audio_utils/include/audio_utils/TimestampVerifier.h
+++ b/audio_utils/include/audio_utils/TimestampVerifier.h
@@ -159,6 +159,12 @@
         ++mTimestamps;
     }
 
+    // How a discontinuity affects frame position.
+    enum DiscontinuityMode : int32_t {
+        DISCONTINUITY_MODE_CONTINUOUS, // frame position is unaffected.
+        DISCONTINUITY_MODE_ZERO,       // frame position resets to zero.
+    };
+
     /** registers a discontinuity.
      *
      * The next timestamp added does not participate in any statistics with the last
@@ -166,10 +172,19 @@
      *
      * Consecutive discontinuities are treated as one for the purposes of counting.
      */
-    constexpr void discontinuity() {
-        if (!mDiscontinuity) {
+    constexpr void discontinuity(DiscontinuityMode mode) {
+        assert(mode == DISCONTINUITY_MODE_CONTINUOUS || mode == DISCONTINUITY_MODE_ZERO);
+
+        // If there is a pending ZERO discontinuity, do not override with CONTINUOUS
+        if (mode == DISCONTINUITY_MODE_CONTINUOUS && mDiscontinuityMode == DISCONTINUITY_MODE_ZERO
+                && mDiscontinuity) {
+            return;
+        }
+
+        if (mode != mDiscontinuityMode || !mDiscontinuity) {
             // ALOGD("discontinuity");
             mDiscontinuity = true;
+            mDiscontinuityMode = mode;
             mCold = true;
             ++mDiscontinuities;
         }
@@ -184,18 +199,6 @@
         ++mErrors;
     }
 
-    // How a discontinuity affects frame position.
-    enum DiscontinuityMode : int32_t {
-        DISCONTINUITY_MODE_CONTINUOUS, // frame position is unaffected.
-        DISCONTINUITY_MODE_ZERO,       // frame position resets to zero.
-    };
-
-    constexpr void setDiscontinuityMode(DiscontinuityMode mode) {
-        assert(mode == DISCONTINUITY_MODE_CONTINUOUS
-                || mode == DISCONTINUITY_MODE_ZERO);
-        mDiscontinuityMode = mode;
-    }
-
     constexpr DiscontinuityMode getDiscontinuityMode() const {
         return mDiscontinuityMode;
     }
diff --git a/audio_utils/tests/timestampverifier_tests.cpp b/audio_utils/tests/timestampverifier_tests.cpp
index f2e6543..a811823 100644
--- a/audio_utils/tests/timestampverifier_tests.cpp
+++ b/audio_utils/tests/timestampverifier_tests.cpp
@@ -36,7 +36,7 @@
         t += (int64_t)1e9;
     }
     for (size_t i = 0; i < discontinuities; ++i) {
-        tv.discontinuity();
+        tv.discontinuity(tv.DISCONTINUITY_MODE_CONTINUOUS);
     }
     for (size_t i = 0; i < errors; ++i) {
         tv.error();
@@ -103,7 +103,6 @@
 TEST(TimestampVerifier, discontinuity_zero)
 {
     android::TimestampVerifier<int64_t, int64_t> tv;
-    tv.setDiscontinuityMode(tv.DISCONTINUITY_MODE_ZERO);
 
     // Add timestamps advancing at normal rate over 2 seconds
     tv.add(0, 0, 48000);
@@ -111,7 +110,7 @@
     tv.add(96000, 2000000000, 48000);
 
     // Raise (mode zero) discontinuity at "3 seconds"
-    tv.discontinuity();
+    tv.discontinuity(tv.DISCONTINUITY_MODE_ZERO);
     // Add timestamp where frame count has reset to zero (and not advancing)
     tv.add(0, 3000000000, 48000);