audio: Add optional 'DriverInterface::getPosition' method.

This is a method which can be optionally implemented
by a stream in case it can provide more exact position,
for example by taking into account data in intermediate
buffers.

Implemented this method for StreamAlsa and StreamRemoteSubmix.

Bug: 264712385
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I392933f8f6b22d784726925199db00dcb0313648
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index ecb3c78..17c7feb 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -20,6 +20,7 @@
 #include <android-base/logging.h>
 
 #include <Utils.h>
+#include <audio_utils/clock.h>
 #include <error/expected_utils.h>
 
 #include "core-impl/StreamAlsa.h"
@@ -96,6 +97,37 @@
     return ::android::OK;
 }
 
+::android::status_t StreamAlsa::getPosition(StreamDescriptor::Position* position) {
+    if (mAlsaDeviceProxies.empty()) {
+        LOG(FATAL) << __func__ << ": no input devices";
+        return ::android::NO_INIT;
+    }
+    if (mIsInput) {
+        if (int ret = proxy_get_capture_position(mAlsaDeviceProxies[0].get(), &position->frames,
+                                                 &position->timeNs);
+            ret != 0) {
+            LOG(WARNING) << __func__ << ": failed to retrieve capture position: " << ret;
+            return ::android::INVALID_OPERATION;
+        }
+    } else {
+        uint64_t hwFrames;
+        struct timespec timestamp;
+        if (int ret = proxy_get_presentation_position(mAlsaDeviceProxies[0].get(), &hwFrames,
+                                                      &timestamp);
+            ret == 0) {
+            if (hwFrames > std::numeric_limits<int64_t>::max()) {
+                hwFrames -= std::numeric_limits<int64_t>::max();
+            }
+            position->frames = static_cast<int64_t>(hwFrames);
+            position->timeNs = audio_utils_ns_from_timespec(&timestamp);
+        } else {
+            LOG(WARNING) << __func__ << ": failed to retrieve presentation position: " << ret;
+            return ::android::INVALID_OPERATION;
+        }
+    }
+    return ::android::OK;
+}
+
 void StreamAlsa::shutdown() {
     mAlsaDeviceProxies.clear();
 }