audio: Implement more accurate timing for the stub stream

Stub output stream is like a /dev/null audio device, however
for synchronous transfers it must block for the duration of
the audio chunk being transferred. Implement more accurate
accounting for the blocking time using the same approach as
employed by the remote submix stream implementation.

Bug: 356719263
Test: atest CtsNativeMediaAAudioTestCases
      on aosp_cf_x86_64_auto target
(cherry picked from https://android-review.googlesource.com/q/commit:10fc96386edfa98fea9c5a2a35146f9a2d1efe31)
Merged-In: I137aed397246bcf2b5ef6789aa4d2d27ead64467
Change-Id: I137aed397246bcf2b5ef6789aa4d2d27ead64467
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index f4ee566..22b2020 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -44,6 +44,10 @@
     const bool mIsInput;
     bool mIsInitialized = false;  // Used for validating the state machine logic.
     bool mIsStandby = true;       // Used for validating the state machine logic.
+
+    // Used by the worker thread.
+    int64_t mStartTimeNs = 0;
+    long mFramesSinceStart = 0;
 };
 
 class StreamInStub final : public StreamIn, public StreamStub {
diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp
index 3b6a85a..a3d99a8 100644
--- a/audio/aidl/default/stub/StreamStub.cpp
+++ b/audio/aidl/default/stub/StreamStub.cpp
@@ -83,7 +83,6 @@
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
-    usleep(500);
     mIsStandby = true;
     return ::android::OK;
 }
@@ -92,8 +91,9 @@
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
-    usleep(500);
     mIsStandby = false;
+    mStartTimeNs = ::android::uptimeNanos();
+    mFramesSinceStart = 0;
     return ::android::OK;
 }
 
@@ -105,14 +105,23 @@
     if (mIsStandby) {
         LOG(FATAL) << __func__ << ": must not happen while in standby";
     }
-    static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
-    static constexpr float kScaleFactor = .8f;
+    *actualFrameCount = frameCount;
     if (mIsAsynchronous) {
         usleep(500);
     } else {
-        const size_t delayUs = static_cast<size_t>(
-                std::roundf(kScaleFactor * frameCount * kMicrosPerSecond / mSampleRate));
-        usleep(delayUs);
+        mFramesSinceStart += *actualFrameCount;
+        const long bufferDurationUs =
+                (*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
+        const auto totalDurationUs =
+                (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
+        const long totalOffsetUs =
+                mFramesSinceStart * MICROS_PER_SECOND / mContext.getSampleRate() - totalDurationUs;
+        LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs;
+        if (totalOffsetUs > 0) {
+            const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs);
+            LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us";
+            usleep(sleepTimeUs);
+        }
     }
     if (mIsInput) {
         uint8_t* byteBuffer = static_cast<uint8_t*>(buffer);
@@ -120,7 +129,6 @@
             byteBuffer[i] = std::rand() % 255;
         }
     }
-    *actualFrameCount = frameCount;
     return ::android::OK;
 }