aaudio: fix output bugs and improve input performance, add loopback test

Support AAUDIO_PERFORMANCE_MODE in AudioStreamRecord.cpp
Fix race condition when closing a stream, which this test revealed.
Fix setting of negative notificationFrames for non-FAST tracks.

Convert test from old Oboe API to AAudio.
Add command line options to the test.
Add systrace calls.

Bug: 34093052
Bug: 38313432
Bug: 38178592
Test: loopback.cpp
Change-Id: Ib6d2995cdd3ed432937fde2f26c5394013f0d6e0
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index eb6bfd5..a74a030 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -60,15 +60,29 @@
                               ? 2 : getSamplesPerFrame();
     audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame);
 
-    audio_input_flags_t flags = (audio_input_flags_t) AUDIO_INPUT_FLAG_NONE;
-
     size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0
                         : builder.getBufferCapacity();
+
     // TODO implement an unspecified Android format then use that.
     audio_format_t format = (getFormat() == AAUDIO_UNSPECIFIED)
             ? AUDIO_FORMAT_PCM_FLOAT
             : AAudioConvert_aaudioToAndroidDataFormat(getFormat());
 
+    audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
+    switch(getPerformanceMode()) {
+        case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
+            flags = (audio_input_flags_t) (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW);
+            break;
+
+        case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
+        case AAUDIO_PERFORMANCE_MODE_NONE:
+        default:
+            // No flags.
+            break;
+    }
+
+    uint32_t notificationFrames = 0;
+
     // Setup the callback if there is one.
     AudioRecord::callback_t callback = nullptr;
     void *callbackData = nullptr;
@@ -77,11 +91,12 @@
         streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK;
         callback = getLegacyCallback();
         callbackData = this;
+        notificationFrames = builder.getFramesPerDataCallback();
     }
     mCallbackBufferSize = builder.getFramesPerDataCallback();
 
     mAudioRecord = new AudioRecord(
-            AUDIO_SOURCE_DEFAULT,
+            AUDIO_SOURCE_VOICE_RECOGNITION,
             getSampleRate(),
             format,
             channelMask,
@@ -89,7 +104,7 @@
             frameCount,
             callback,
             callbackData,
-            0,    //    uint32_t notificationFrames = 0,
+            notificationFrames,
             AUDIO_SESSION_ALLOCATE,
             streamTransferType,
             flags
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index f4a78e1..0af6457 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -29,7 +29,7 @@
 namespace aaudio {
 
 /**
- * Internal stream that uses the legacy AudioTrack path.
+ * Internal stream that uses the legacy AudioRecord path.
  */
 class AudioStreamRecord : public AudioStreamLegacy {
 public:
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index a7c7673..8c3732e 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -105,12 +105,14 @@
         callback = getLegacyCallback();
         callbackData = this;
 
-        notificationFrames = builder.getFramesPerDataCallback();
         // If the total buffer size is unspecified then base the size on the burst size.
-        if (frameCount == AAUDIO_UNSPECIFIED) {
+        if (frameCount == 0
+                && ((flags & AUDIO_OUTPUT_FLAG_FAST) != 0)) {
             // Take advantage of a special trick that allows us to create a buffer
             // that is some multiple of the burst size.
             notificationFrames = 0 - DEFAULT_BURSTS_PER_BUFFER_CAPACITY;
+        } else {
+            notificationFrames = builder.getFramesPerDataCallback();
         }
     }
     mCallbackBufferSize = builder.getFramesPerDataCallback();