aaudio: Improve consistency with CDD

1) Skip certain tests if the device doesn't support the corresponding feature:
   - skip tests that open output streams on devices that don't have output;
   - skip tests that open input streams on devices that don't have mic.

2) Do not fail tests if the measured latency is too high, only issue
   a warning.

Bug: 123245030
Test: atest CtsNativeMediaAAudioTestCases:AAudioTests
Merged-In: Ibf5306d644b437753c9d2d9152ff2b0675ebb365
Change-Id: Ibf5306d644b437753c9d2d9152ff2b0675ebb365
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp
index 141b867..3703a39 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp
@@ -62,11 +62,12 @@
 };
 
 void AAudioInputStreamTest::SetUp() {
+    mSetupSuccesful = false;
+    if (!deviceSupportsFeature(FEATURE_RECORDING)) return;
     mHelper.reset(new InputStreamBuilderHelper(
                     std::get<PARAM_SHARING_MODE>(GetParam()),
                     std::get<PARAM_PERF_MODE>(GetParam())));
     mHelper->initBuilder();
-    mSetupSuccesful = false;
     mHelper->createAndVerifyStream(&mSetupSuccesful);
     if (!mSetupSuccesful) return;
 
@@ -172,12 +173,13 @@
 };
 
 void AAudioOutputStreamTest::SetUp() {
+    mSetupSuccesful = false;
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     mHelper.reset(new OutputStreamBuilderHelper(
                     std::get<PARAM_SHARING_MODE>(GetParam()),
                     std::get<PARAM_PERF_MODE>(GetParam())));
     mHelper->initBuilder();
 
-    mSetupSuccesful = false;
     mHelper->createAndVerifyStream(&mSetupSuccesful);
     if (!mSetupSuccesful) return;
 
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp
index d48aeab..7ed3319 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_attributes.cpp
@@ -22,6 +22,8 @@
 #include <aaudio/AAudio.h>
 #include <gtest/gtest.h>
 
+#include "utils.h"
+
 constexpr int64_t kNanosPerSecond = 1000000000;
 constexpr int kNumFrames = 256;
 constexpr int kChannelCount = 2;
@@ -33,6 +35,10 @@
                             aaudio_content_type_t contentType,
                             aaudio_input_preset_t preset = DONT_SET,
                             aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
+    if (direction == AAUDIO_DIRECTION_INPUT
+            && !deviceSupportsFeature(FEATURE_RECORDING)) return;
+    else if (direction == AAUDIO_DIRECTION_OUTPUT
+            && !deviceSupportsFeature(FEATURE_PLAYBACK)) return;
 
     float *buffer = new float[kNumFrames * kChannelCount];
 
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
index 670c077..813b40c 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
@@ -143,6 +143,8 @@
 }
 
 void AAudioInputStreamCallbackTest::SetUp() {
+    mSetupSuccesful = false;
+    if (!deviceSupportsFeature(FEATURE_RECORDING)) return;
     mHelper.reset(new InputStreamBuilderHelper(
                     std::get<PARAM_SHARING_MODE>(GetParam()),
                     std::get<PARAM_PERF_MODE>(GetParam())));
@@ -156,7 +158,6 @@
         AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
     }
 
-    mSetupSuccesful = false;
     mHelper->createAndVerifyStream(&mSetupSuccesful);
 }
 
@@ -242,6 +243,8 @@
 }
 
 void AAudioOutputStreamCallbackTest::SetUp() {
+    mSetupSuccesful = false;
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     mHelper.reset(new OutputStreamBuilderHelper(
                     std::get<PARAM_SHARING_MODE>(GetParam()),
                     std::get<PARAM_PERF_MODE>(GetParam())));
@@ -255,7 +258,6 @@
         AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
     }
 
-    mSetupSuccesful = false;
     mHelper->createAndVerifyStream(&mSetupSuccesful);
 }
 
@@ -300,8 +302,11 @@
         }
 
         EXPECT_GE(mCbData->minLatency, 1);   // Absurdly low
-        EXPECT_LE(mCbData->maxLatency, 300); // Absurdly high, should be < 30
-                                               // Note that on some devices it's 200-something
+        // We only issue a warning here because the CDD does not mandate a specific minimum latency
+        if (mCbData->maxLatency > 300) {
+            __android_log_print(ANDROID_LOG_WARN, LOG_TAG,
+                    "Suspiciously high callback latency: %d", mCbData->maxLatency);
+        }
         //printf("latency: %d, %d\n", mCbData->minLatency, mCbData->maxLatency);
     }
 
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
index a3aa75d..8713b46 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_stream_builder.cpp
@@ -21,6 +21,8 @@
 #include <android/log.h>
 #include <gtest/gtest.h>
 
+#include "utils.h"
+
 // Creates a builder, the caller takes ownership
 static void create_stream_builder(AAudioStreamBuilder** aaudioBuilder) {
     aaudio_result_t result = AAudio_createStreamBuilder(aaudioBuilder);
@@ -85,6 +87,7 @@
 
 // Test creating a default stream with everything unspecified.
 TEST(test_aaudio, aaudio_stream_unspecified) {
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     create_stream_builder(&aaudioBuilder);
 
@@ -110,6 +113,7 @@
 };
 
 TEST_P(AAudioStreamBuilderSamplingRateTest, openStream) {
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     create_stream_builder(&aaudioBuilder);
     AAudioStreamBuilder_setSampleRate(aaudioBuilder, GetParam());
@@ -138,6 +142,7 @@
 };
 
 TEST_P(AAudioStreamBuilderChannelCountTest, openStream) {
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     create_stream_builder(&aaudioBuilder);
     AAudioStreamBuilder_setChannelCount(aaudioBuilder, GetParam());
@@ -171,6 +176,7 @@
 };
 
 TEST_P(AAudioStreamBuilderFormatTest, openStream) {
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     create_stream_builder(&aaudioBuilder);
     AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
@@ -198,6 +204,7 @@
 };
 
 TEST_P(AAudioStreamBuilderSharingModeTest, openStream) {
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     create_stream_builder(&aaudioBuilder);
     AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
@@ -225,6 +232,10 @@
 };
 
 TEST_P(AAudioStreamBuilderDirectionTest, openStream) {
+    if (GetParam() == AAUDIO_DIRECTION_OUTPUT
+            && !deviceSupportsFeature(FEATURE_PLAYBACK)) return;
+    if (GetParam() == AAUDIO_DIRECTION_INPUT
+            && !deviceSupportsFeature(FEATURE_RECORDING)) return;
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     create_stream_builder(&aaudioBuilder);
     AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
@@ -254,6 +265,7 @@
 };
 
 TEST_P(AAudioStreamBuilderBufferCapacityTest, openStream) {
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     create_stream_builder(&aaudioBuilder);
     AAudioStreamBuilder_setBufferCapacityInFrames(aaudioBuilder, GetParam());
@@ -287,6 +299,7 @@
 };
 
 TEST_P(AAudioStreamBuilderPerfModeTest, openStream) {
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     create_stream_builder(&aaudioBuilder);
     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, GetParam());
diff --git a/tests/tests/nativemedia/aaudio/jni/test_session_id.cpp b/tests/tests/nativemedia/aaudio/jni/test_session_id.cpp
index fa82f71..dfde6e7 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_session_id.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_session_id.cpp
@@ -23,12 +23,14 @@
 #include <gtest/gtest.h>
 
 #include "test_aaudio.h"
+#include "utils.h"
 
 constexpr int kNumFrames = 256;
 constexpr int kChannelCount = 2;
 
 // Test AAUDIO_SESSION_ID_NONE default
 static void checkSessionIdNone(aaudio_performance_mode_t perfMode) {
+    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
 
     float *buffer = new float[kNumFrames * kChannelCount];
 
@@ -72,6 +74,10 @@
 // Test AAUDIO_SESSION_ID_ALLOCATE
 static void checkSessionIdAllocate(aaudio_performance_mode_t perfMode,
                                    aaudio_direction_t direction) {
+    // Since this test creates streams in both directions, it can't work
+    // if either of them is not supported by the device.
+    if (!deviceSupportsFeature(FEATURE_RECORDING)
+            || !deviceSupportsFeature(FEATURE_PLAYBACK)) return;
 
     float *buffer = new float[kNumFrames * kChannelCount];
 
diff --git a/tests/tests/nativemedia/aaudio/jni/utils.cpp b/tests/tests/nativemedia/aaudio/jni/utils.cpp
index 55d1e13..d843614 100644
--- a/tests/tests/nativemedia/aaudio/jni/utils.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/utils.cpp
@@ -16,9 +16,12 @@
 
 #define LOG_TAG "AAudioTest"
 
+#include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <string>
+
 #include <android/log.h>
 #include <gtest/gtest.h>
 
@@ -51,6 +54,28 @@
     return "UNKNOWN";
 }
 
+// Runs "pm list features" and attempts to find the specified feature in its output.
+bool deviceSupportsFeature(const char* feature) {
+    bool hasFeature = false;
+    FILE *p = popen("/system/bin/pm list features", "re");
+    if (p) {
+      char* line = NULL;
+      size_t len = 0;
+      while (getline(&line, &len, p) > 0) {
+          if (strstr(line, feature)) {
+              hasFeature = true;
+              break;
+          }
+      }
+      pclose(p);
+    } else {
+        __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "popen failed: %d", errno);
+        _exit(EXIT_FAILURE);
+    }
+    __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Feature %s: %ssupported",
+            feature, hasFeature ? "" : "not ");
+    return hasFeature;
+}
 
 // These periods are quite generous. They are not designed to put
 // any restrictions on the implementation, but only to ensure sanity.
diff --git a/tests/tests/nativemedia/aaudio/jni/utils.h b/tests/tests/nativemedia/aaudio/jni/utils.h
index 7f38fef..4211410 100644
--- a/tests/tests/nativemedia/aaudio/jni/utils.h
+++ b/tests/tests/nativemedia/aaudio/jni/utils.h
@@ -24,6 +24,11 @@
 const char* performanceModeToString(aaudio_performance_mode_t mode);
 const char* sharingModeToString(aaudio_sharing_mode_t mode);
 
+static constexpr const char* FEATURE_PLAYBACK = "android.hardware.audio.output";
+static constexpr const char* FEATURE_RECORDING = "android.hardware.microphone";
+static constexpr const char* FEATURE_LOW_LATENCY = "android.hardware.audio.low_latency";
+bool deviceSupportsFeature(const char* feature);
+
 class StreamBuilderHelper {
   public:
     struct Parameters {