OSDN Git Service

Create unit test framework for audio_a2dp_hw
authorPavlin Radoslavov <pavlin@google.com>
Wed, 5 Apr 2017 23:18:26 +0000 (16:18 -0700)
committerPavlin Radoslavov <pavlin@google.com>
Fri, 7 Apr 2017 21:55:51 +0000 (21:55 +0000)
Create unit test framework for audio_a2dp_hw and implement a unit test
for function audio_a2dp_hw_stream_compute_buffer_size()

Also:
 * Remove obsolete check for mixer unit size inside out_get_buffer_size()
 * Reorganize the file structure inside directory audio_a2dp_hw/ :
   - Moved the source code files *.cc to audio_a2dp_hw/src/
   - Moved the header file(s) *.h to audio_a2dp_hw/include/
   - The unit test file(s) are stored in audio_a2dp_hw/test/

Bug: 35849921
Test: This is the unit test. Code compilation and unit test succeed
Change-Id: I3dcc508cb6799462b7103cb2ee452b4399843899

19 files changed:
audio_a2dp_hw/Android.bp
audio_a2dp_hw/include/audio_a2dp_hw.h [moved from audio_a2dp_hw/audio_a2dp_hw.h with 76% similarity]
audio_a2dp_hw/src/audio_a2dp_hw.cc [moved from audio_a2dp_hw/audio_a2dp_hw.cc with 98% similarity]
audio_a2dp_hw/src/audio_a2dp_hw_utils.cc [moved from audio_a2dp_hw/audio_a2dp_hw_utils.cc with 100% similarity]
audio_a2dp_hw/test/audio_a2dp_hw_test.cc [new file with mode: 0644]
btif/Android.bp
btif/BUILD.gn
btif/include/btif_a2dp_control.h
btif/src/btif_a2dp.cc
btif/src/btif_a2dp_control.cc
btif/src/btif_a2dp_source.cc
btif/src/btif_av.cc
main/Android.bp
stack/BUILD.gn
stack/include/a2dp_codec_api.h
test/run_unit_tests.sh
udrv/Android.bp
udrv/BUILD.gn
udrv/ulinux/uipc.cc

index df7e33f..24bb1de 100644 (file)
@@ -1,15 +1,21 @@
+cc_defaults {
+    name: "audio_a2dp_hw_defaults",
+    defaults: ["fluoride_defaults"],
+    include_dirs: [
+        "system/bt",
+        "system/bt/audio_a2dp_hw/include",
+    ]
+}
+
 // Audio A2DP shared library for target
 // ========================================================
-cc_library_shared {
+cc_library {
     name: "audio.a2dp.default",
-    defaults: ["fluoride_defaults"],
+    defaults: ["audio_a2dp_hw_defaults"],
     relative_install_path: "hw",
     srcs: [
-        "audio_a2dp_hw.cc",
-        "audio_a2dp_hw_utils.cc",
-    ],
-    include_dirs: [
-        "system/bt",
+        "src/audio_a2dp_hw.cc",
+        "src/audio_a2dp_hw_utils.cc",
     ],
     shared_libs: [
         "liblog",
@@ -19,8 +25,23 @@ cc_library_shared {
 
 cc_library_static {
     name: "libaudio-a2dp-hw-utils",
-    defaults: ["fluoride_defaults"],
+    defaults: ["audio_a2dp_hw_defaults"],
     srcs: [
-        "audio_a2dp_hw_utils.cc",
+        "src/audio_a2dp_hw_utils.cc",
+    ],
+}
+
+// Audio A2DP library unit tests for target and host
+// ========================================================
+cc_test {
+    name: "net_test_audio_a2dp_hw",
+    test_suites: ["device-tests"],
+    defaults: ["audio_a2dp_hw_defaults"],
+    srcs: [
+        "test/audio_a2dp_hw_test.cc",
+    ],
+    shared_libs: [
+        "liblog",
     ],
+    static_libs: ["audio.a2dp.default"],
 }
similarity index 76%
rename from audio_a2dp_hw/audio_a2dp_hw.h
rename to audio_a2dp_hw/include/audio_a2dp_hw.h
index 4476f6a..62dac66 100644 (file)
@@ -29,6 +29,8 @@
 
 #include <stdint.h>
 
+#include <hardware/bt_av.h>
+
 /*****************************************************************************
  *  Constants & Macros
  *****************************************************************************/
@@ -41,9 +43,6 @@
 // If one assumes the write buffer is always full during normal BT playback,
 // then increasing this value increases our playback latency.
 //
-// FIXME: AUDIO_STREAM_OUTPUT_BUFFER_SZ should be controlled by the actual audio
-// sample rate rather than being constant.
-//
 // FIXME: The BT HAL should consume data at a constant rate.
 // AudioFlinger assumes that the HAL draws data at a constant rate, which is
 // true for most audio devices; however, the BT engine reads data at a variable
@@ -115,6 +114,37 @@ typedef uint8_t tA2DP_BITS_PER_SAMPLE;
  *  Functions
  *****************************************************************************/
 
+// Computes the Audio A2DP HAL output buffer size.
+// |codec_sample_rate| is the sample rate of the output stream.
+// |codec_bits_per_sample| is the number of bits per sample of the output
+// stream.
+// |codec_channel_mode| is the channel mode of the output stream.
+//
+// The buffer size is computed by using the following formula:
+//
+// AUDIO_STREAM_OUTPUT_BUFFER_SIZE =
+//    (TIME_PERIOD_MS * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS *
+//     SAMPLE_RATE_HZ * NUMBER_OF_CHANNELS * (BITS_PER_SAMPLE / 8)) / 1000
+//
+// AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is
+// divided for AudioFlinger data delivery. The AudioFlinger mixer delivers
+// data in chunks of
+// (AUDIO_STREAM_OUTPUT_BUFFER_SIZE / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS) .
+// If the number of periods is 2, the socket buffer represents "double
+// buffering" of the AudioFlinger mixer buffer.
+//
+// Furthermore, the AudioFlinger expects the buffer size to be a multiple
+// of 16 frames.
+//
+// NOTE: Currently, the computation uses the conservative 20ms time period.
+//
+// Returns the computed buffer size. If any of the input parameters is
+// invalid, the return value is the default |AUDIO_STREAM_OUTPUT_BUFFER_SZ|.
+extern size_t audio_a2dp_hw_stream_compute_buffer_size(
+    btav_a2dp_codec_sample_rate_t codec_sample_rate,
+    btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample,
+    btav_a2dp_codec_channel_mode_t codec_channel_mode);
+
 // Returns a string representation of |event|.
 extern const char* audio_a2dp_hw_dump_ctrl_event(tA2DP_CTRL_CMD event);
 
similarity index 98%
rename from audio_a2dp_hw/audio_a2dp_hw.cc
rename to audio_a2dp_hw/src/audio_a2dp_hw.cc
index 2885205..db63fa3 100644 (file)
@@ -40,7 +40,6 @@
 #include <mutex>
 
 #include <hardware/audio.h>
-#include <hardware/bt_av.h>
 #include <hardware/hardware.h>
 #include <system/audio.h>
 
@@ -150,10 +149,6 @@ struct a2dp_stream_in {
  *****************************************************************************/
 
 static size_t out_get_buffer_size(const struct audio_stream* stream);
-static size_t audio_stream_compute_buffer_size(
-    btav_a2dp_codec_sample_rate_t codec_sample_rate,
-    btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample,
-    btav_a2dp_codec_channel_mode_t codec_channel_mode);
 
 /*****************************************************************************
  *  Externs
@@ -611,7 +606,7 @@ static int a2dp_read_output_audio_config(
     common->cfg.rate = stream_config.rate;
     common->cfg.channel_mask = stream_config.channel_mask;
     common->cfg.format = stream_config.format;
-    common->buffer_sz = audio_stream_compute_buffer_size(
+    common->buffer_sz = audio_a2dp_hw_stream_compute_buffer_size(
         codec_config->sample_rate, codec_config->bits_per_sample,
         codec_config->channel_mode);
   }
@@ -922,24 +917,19 @@ static size_t out_get_buffer_size(const struct audio_stream* stream) {
   // period_size is the AudioFlinger mixer buffer size.
   const size_t period_size =
       out->common.buffer_sz / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS;
-  const size_t mixer_unit_size = 16 /* frames */ * 4 /* framesize */;
 
   DEBUG("socket buffer size: %zu  period size: %zu", out->common.buffer_sz,
         period_size);
-  if (period_size % mixer_unit_size != 0) {
-    ERROR("period size %zu not a multiple of %zu", period_size,
-          mixer_unit_size);
-  }
 
   return period_size;
 }
 
-static size_t audio_stream_compute_buffer_size(
+size_t audio_a2dp_hw_stream_compute_buffer_size(
     btav_a2dp_codec_sample_rate_t codec_sample_rate,
     btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample,
     btav_a2dp_codec_channel_mode_t codec_channel_mode) {
   size_t buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ;  // Default value
-  const uint32_t time_period_ms = 20;                // Conservative 20ms
+  const uint64_t time_period_ms = 20;                // Conservative 20ms
   uint32_t sample_rate;
   uint32_t bits_per_sample;
   uint32_t number_of_channels;
diff --git a/audio_a2dp_hw/test/audio_a2dp_hw_test.cc b/audio_a2dp_hw/test/audio_a2dp_hw_test.cc
new file mode 100644 (file)
index 0000000..f2cefa8
--- /dev/null
@@ -0,0 +1,142 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2017 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.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
+
+namespace {
+static uint32_t codec_sample_rate2value(
+    btav_a2dp_codec_sample_rate_t codec_sample_rate) {
+  switch (codec_sample_rate) {
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
+      return 44100;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
+      return 48000;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
+      return 88200;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
+      return 96000;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
+      return 176400;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+      return 192000;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
+      break;
+  }
+  return 0;
+}
+
+static uint32_t codec_bits_per_sample2value(
+    btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample) {
+  switch (codec_bits_per_sample) {
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
+      return 16;
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
+      return 24;
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
+      return 32;
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
+      break;
+  }
+  return 0;
+}
+
+static uint32_t codec_channel_mode2value(
+    btav_a2dp_codec_channel_mode_t codec_channel_mode) {
+  switch (codec_channel_mode) {
+    case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
+      return 1;
+    case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+      return 2;
+    case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
+      break;
+  }
+  return 0;
+}
+
+}  // namespace
+
+class AudioA2dpHwTest : public ::testing::Test {
+ protected:
+  AudioA2dpHwTest() {}
+
+ private:
+};
+
+TEST_F(AudioA2dpHwTest, test_compute_buffer_size) {
+  const btav_a2dp_codec_sample_rate_t codec_sample_rate_array[] = {
+      BTAV_A2DP_CODEC_SAMPLE_RATE_NONE,  BTAV_A2DP_CODEC_SAMPLE_RATE_44100,
+      BTAV_A2DP_CODEC_SAMPLE_RATE_48000, BTAV_A2DP_CODEC_SAMPLE_RATE_88200,
+      BTAV_A2DP_CODEC_SAMPLE_RATE_96000, BTAV_A2DP_CODEC_SAMPLE_RATE_176400,
+      BTAV_A2DP_CODEC_SAMPLE_RATE_192000};
+
+  const btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample_array[] = {
+      BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16,
+      BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32};
+
+  const btav_a2dp_codec_channel_mode_t codec_channel_mode_array[] = {
+      BTAV_A2DP_CODEC_CHANNEL_MODE_NONE, BTAV_A2DP_CODEC_CHANNEL_MODE_MONO,
+      BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO};
+
+  for (const auto codec_sample_rate : codec_sample_rate_array) {
+    for (const auto codec_bits_per_sample : codec_bits_per_sample_array) {
+      for (const auto codec_channel_mode : codec_channel_mode_array) {
+        size_t buffer_size = audio_a2dp_hw_stream_compute_buffer_size(
+            codec_sample_rate, codec_bits_per_sample, codec_channel_mode);
+
+        // Check for invalid input
+        if ((codec_sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) ||
+            (codec_bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) ||
+            (codec_channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) {
+          EXPECT_EQ(buffer_size,
+                    static_cast<size_t>(AUDIO_STREAM_OUTPUT_BUFFER_SZ));
+          continue;
+        }
+
+        uint32_t sample_rate = codec_sample_rate2value(codec_sample_rate);
+        EXPECT_TRUE(sample_rate != 0);
+
+        uint32_t bits_per_sample =
+            codec_bits_per_sample2value(codec_bits_per_sample);
+        EXPECT_TRUE(bits_per_sample != 0);
+
+        uint32_t number_of_channels =
+            codec_channel_mode2value(codec_channel_mode);
+        EXPECT_TRUE(number_of_channels != 0);
+
+        const uint64_t time_period_ms = 20;  // TODO: Must be a parameter
+        size_t expected_buffer_size =
+            (time_period_ms * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * sample_rate *
+             number_of_channels * (bits_per_sample / 8)) /
+            1000;
+
+        // Compute the divisor and adjust the buffer size
+        const size_t divisor = (AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * 16 *
+                                number_of_channels * bits_per_sample) /
+                               8;
+        const size_t remainder = expected_buffer_size % divisor;
+        if (remainder != 0) {
+          expected_buffer_size += divisor - remainder;
+        }
+
+        EXPECT_EQ(buffer_size, expected_buffer_size);
+      }
+    }
+  }
+}
index b3d7dab..20f917a 100644 (file)
@@ -19,7 +19,6 @@ btifCommonIncludes = [
     "system/bt/vnd/include",
     "system/bt/embdrv/sbc/encoder/include",
     "system/bt/embdrv/sbc/decoder/include",
-    "system/bt/audio_a2dp_hw",
     "system/bt/utils/include",
 ]
 
index 61a0614..8bbdbbf 100644 (file)
@@ -16,7 +16,7 @@
 
 static_library("btif") {
   sources = [
-    "//audio_a2dp_hw/audio_a2dp_hw_utils.cc",
+    "//audio_a2dp_hw/src/audio_a2dp_hw_utils.cc",
     "src/btif_a2dp.cc",
     "src/btif_a2dp_control.cc",
     "src/btif_a2dp_sink.cc",
@@ -78,7 +78,6 @@ static_library("btif") {
   include_dirs = [
     "include",
     "//",
-    "//audio_a2dp_hw",
     "//bta/include",
     "//bta/sys",
     "//btcore/include",
index fdd4c06..fb935f5 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef BTIF_A2DP_CONTROL_H
 #define BTIF_A2DP_CONTROL_H
 
-#include "audio_a2dp_hw/audio_a2dp_hw.h"
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 
 // Initialize the A2DP control module. It should be called during the
 // startup stage of A2DP streaming.
index 90c6504..7c83ff9 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <stdbool.h>
 
-#include "audio_a2dp_hw.h"
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 #include "bt_common.h"
 #include "bta_av_api.h"
 #include "btif_a2dp.h"
index 555f3f3..22cf7aa 100644 (file)
@@ -23,7 +23,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 
-#include "audio_a2dp_hw.h"
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 #include "bt_common.h"
 #include "btif_a2dp.h"
 #include "btif_a2dp_control.h"
index f8ec300..6be76aa 100644 (file)
@@ -24,7 +24,7 @@
 #include <string.h>
 #include <algorithm>
 
-#include "audio_a2dp_hw.h"
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 #include "bt_common.h"
 #include "bta_av_ci.h"
 #include "btcore/include/bdaddr.h"
index 4e22160..7e4ad4e 100644 (file)
@@ -27,7 +27,7 @@
 #include <hardware/bt_av.h>
 #include <hardware/bt_rc.h>
 
-#include "audio_a2dp_hw.h"
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 #include "bt_common.h"
 #include "bt_utils.h"
 #include "bta_api.h"
index 760c3ac..a889294 100644 (file)
@@ -32,7 +32,6 @@ cc_library_shared {
         "system/bt/vnd/include",
         "system/bt/embdrv/sbc/encoder/include",
         "system/bt/embdrv/sbc/decoder/include",
-        "system/bt/audio_a2dp_hw",
         "system/bt/utils/include",
     ],
     logtags: ["../EventLogTags.logtags"],
index 0c8547b..9e0dc37 100644 (file)
@@ -195,7 +195,6 @@ executable("stack_unittests") {
   include_dirs = [
     "include",
     "//",
-    "//audio_a2dp_hw",
     "//bta/include",
     "//bta/sys",
     "//btcore/include",
index f85837f..cb28466 100644 (file)
@@ -32,7 +32,7 @@
 #include <hardware/bt_av.h>
 
 #include "a2dp_api.h"
-#include "audio_a2dp_hw/audio_a2dp_hw.h"
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 #include "avdt_api.h"
 #include "osi/include/time.h"
 
index e7a256c..ecc6c36 100755 (executable)
@@ -2,6 +2,7 @@
 
 known_tests=(
   bluetoothtbd_test
+  net_test_audio_a2dp_hw
   net_test_bluetooth
   net_test_btcore
   net_test_bta
index b1530f7..a571478 100644 (file)
@@ -7,7 +7,6 @@ cc_library_static {
     include_dirs: [
       "system/bt",
       "system/bt/include",
-      "system/bt/audio_a2dp_hw",
       "system/bt/utils/include",
       "system/bt/stack/include",
     ],
index 1993cc3..679d469 100644 (file)
@@ -23,7 +23,6 @@ source_set("udrv") {
     "include",
     "uipc",
     "//",
-    "//audio_a2dp_hw",
     "//include",
     "//stack/include",
     "//utils/include",
index bb7f8e5..a524a36 100644 (file)
@@ -40,7 +40,7 @@
 #include <unistd.h>
 #include <mutex>
 
-#include "audio_a2dp_hw.h"
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 #include "bt_common.h"
 #include "bt_types.h"
 #include "bt_utils.h"