Clamp float data sent to HAL

When memcpying from float to float, we don't check for values
above unity, including NaN. In all other PCM cases, we clamp on either
side of the conversion.

Prior to writing to the HAL, check the data to insulate HALs
which may not tolerate invalid float PCM data gracefully.

Bug: 247119066
Bug: 241662887
Test: atest AudioTrackTest
Change-Id: I355c98f94b1bc9e340f609348ba1b9184c0fd1e3
(cherry picked from commit ba9a1070434ad6de3c87c6b945e8d9bb870a5e77)
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3d44aec..3dcdb13 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4102,10 +4102,19 @@
                                        mEffectBufferFormat,
                                        mNormalFrameCount * mHapticChannelCount);
             }
-
-            memcpy_by_audio_format(mSinkBuffer, mFormat, effectBuffer, mEffectBufferFormat,
-                    mNormalFrameCount * (mChannelCount + mHapticChannelCount));
-
+            const size_t framesToCopy = mNormalFrameCount * (mChannelCount + mHapticChannelCount);
+            if (mFormat == AUDIO_FORMAT_PCM_FLOAT &&
+                    mEffectBufferFormat == AUDIO_FORMAT_PCM_FLOAT) {
+                // Clamp PCM float values more than this distance from 0 to insulate
+                // a HAL which doesn't handle NaN correctly.
+                static constexpr float HAL_FLOAT_SAMPLE_LIMIT = 2.0f;
+                memcpy_to_float_from_float_with_clamping(static_cast<float*>(mSinkBuffer),
+                        static_cast<const float*>(effectBuffer),
+                        framesToCopy, HAL_FLOAT_SAMPLE_LIMIT /* absMax */);
+            } else {
+                memcpy_by_audio_format(mSinkBuffer, mFormat,
+                        effectBuffer, mEffectBufferFormat, framesToCopy);
+            }
             // The sample data is partially interleaved when haptic channels exist,
             // we need to adjust channels here.
             if (mHapticChannelCount > 0) {