AudioFlinger: Add datapath subproject

Test: ALLOW_LOCAL_TIDY_TRUE=1 mm -j .
Bug: 287521708
Merged-In: I1fbe85ff5c5fc58a3e49fa137b4247b33f919ecb
Change-Id: I1fbe85ff5c5fc58a3e49fa137b4247b33f919ecb
(cherry picked from commit 76913a08cba261ea59ca436ee99ff1ea3f2de6e8)
diff --git a/services/audioflinger/datapath/AudioStreamOut.cpp b/services/audioflinger/datapath/AudioStreamOut.cpp
new file mode 100644
index 0000000..6fa82e5
--- /dev/null
+++ b/services/audioflinger/datapath/AudioStreamOut.cpp
@@ -0,0 +1,212 @@
+/*
+**
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "AudioFlinger"
+//#define LOG_NDEBUG 0
+
+#include <media/audiohal/DeviceHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+#include <system/audio.h>
+#include <utils/Log.h>
+
+#include "AudioHwDevice.h"
+#include "AudioStreamOut.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags)
+        : audioHwDev(dev)
+        , flags(flags)
+{
+}
+
+// This must be defined here together with the HAL includes above and
+// not solely in the header.
+AudioStreamOut::~AudioStreamOut() = default;
+
+sp<DeviceHalInterface> AudioStreamOut::hwDev() const
+{
+    return audioHwDev->hwDevice();
+}
+
+status_t AudioStreamOut::getRenderPosition(uint64_t *frames)
+{
+    if (stream == nullptr) {
+        return NO_INIT;
+    }
+
+    uint32_t halPosition = 0;
+    const status_t status = stream->getRenderPosition(&halPosition);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    // Maintain a 64-bit render position using the 32-bit result from the HAL.
+    // This delta calculation relies on the arithmetic overflow behavior
+    // of integers. For example (100 - 0xFFFFFFF0) = 116.
+    const auto truncatedPosition = (uint32_t)mRenderPosition;
+    int32_t deltaHalPosition; // initialization not needed, overwitten by __builtin_sub_overflow()
+    (void) __builtin_sub_overflow(halPosition, truncatedPosition, &deltaHalPosition);
+
+    if (deltaHalPosition > 0) {
+        mRenderPosition += deltaHalPosition;
+    } else if (mExpectRetrograde) {
+        mExpectRetrograde = false;
+        mRenderPosition -= static_cast<uint64_t>(-deltaHalPosition);
+    }
+    // Scale from HAL sample rate to application rate.
+    *frames = mRenderPosition / mRateMultiplier;
+
+    return status;
+}
+
+// return bottom 32-bits of the render position
+status_t AudioStreamOut::getRenderPosition(uint32_t *frames)
+{
+    uint64_t position64 = 0;
+    const status_t status = getRenderPosition(&position64);
+    if (status == NO_ERROR) {
+        *frames = (uint32_t)position64;
+    }
+    return status;
+}
+
+status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp)
+{
+    if (stream == nullptr) {
+        return NO_INIT;
+    }
+
+    uint64_t halPosition = 0;
+    const status_t status = stream->getPresentationPosition(&halPosition, timestamp);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    // Adjust for standby using HAL rate frames.
+    // Only apply this correction if the HAL is getting PCM frames.
+    if (mHalFormatHasProportionalFrames) {
+        const uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ?
+                0 : (halPosition - mFramesWrittenAtStandby);
+        // Scale from HAL sample rate to application rate.
+        *frames = adjustedPosition / mRateMultiplier;
+    } else {
+        // For offloaded MP3 and other compressed formats.
+        *frames = halPosition;
+    }
+
+    return status;
+}
+
+status_t AudioStreamOut::open(
+        audio_io_handle_t handle,
+        audio_devices_t deviceType,
+        struct audio_config *config,
+        const char *address)
+{
+    sp<StreamOutHalInterface> outStream;
+
+    const audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
+                ? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)
+                : flags;
+
+    int status = hwDev()->openOutputStream(
+            handle,
+            deviceType,
+            customFlags,
+            config,
+            address,
+            &outStream);
+    ALOGV("AudioStreamOut::open(), HAL returned "
+            " stream %p, sampleRate %d, Format %#x, "
+            "channelMask %#x, status %d",
+            outStream.get(),
+            config->sample_rate,
+            config->format,
+            config->channel_mask,
+            status);
+
+    // Some HALs may not recognize AUDIO_FORMAT_IEC61937. But if we declare
+    // it as PCM then it will probably work.
+    if (status != NO_ERROR && config->format == AUDIO_FORMAT_IEC61937) {
+        struct audio_config customConfig = *config;
+        customConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+
+        status = hwDev()->openOutputStream(
+                handle,
+                deviceType,
+                customFlags,
+                &customConfig,
+                address,
+                &outStream);
+        ALOGV("AudioStreamOut::open(), treat IEC61937 as PCM, status = %d", status);
+    }
+
+    if (status == NO_ERROR) {
+        stream = outStream;
+        mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
+        status = stream->getFrameSize(&mHalFrameSize);
+        LOG_ALWAYS_FATAL_IF(status != OK, "Error retrieving frame size from HAL: %d", status);
+        LOG_ALWAYS_FATAL_IF(mHalFrameSize <= 0, "Error frame size was %zu but must be greater than"
+                " zero", mHalFrameSize);
+
+    }
+
+    return status;
+}
+
+audio_config_base_t AudioStreamOut::getAudioProperties() const
+{
+    audio_config_base_t result = AUDIO_CONFIG_BASE_INITIALIZER;
+    if (stream->getAudioProperties(&result) != OK) {
+        result.sample_rate = 0;
+        result.channel_mask = AUDIO_CHANNEL_INVALID;
+        result.format = AUDIO_FORMAT_INVALID;
+    }
+    return result;
+}
+
+int AudioStreamOut::flush()
+{
+    mRenderPosition = 0;
+    mExpectRetrograde = false;
+    mFramesWritten = 0;
+    mFramesWrittenAtStandby = 0;
+    const status_t result = stream->flush();
+    return result != INVALID_OPERATION ? result : NO_ERROR;
+}
+
+int AudioStreamOut::standby()
+{
+    mRenderPosition = 0;
+    mExpectRetrograde = false;
+    mFramesWrittenAtStandby = mFramesWritten;
+    return stream->standby();
+}
+
+ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
+{
+    size_t bytesWritten;
+    const status_t result = stream->write(buffer, numBytes, &bytesWritten);
+    if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
+        mFramesWritten += bytesWritten / mHalFrameSize;
+    }
+    return result == OK ? bytesWritten : result;
+}
+
+} // namespace android