Selects the card id on platforms with multiple cards.

On some platforms, there are more than one sound cards. And the default one is
not with index: 0. So, we need a way to figure out the correct card id we
should used.

TEST=run the test on butterfly
BUG=307384

Change-Id: I990c711c1e9fd4616797ad598687c80cb6e7eba8
Reviewed-on: https://chromium-review.googlesource.com/175420
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Commit-Queue: Owen Lin <owenlin@chromium.org>
Tested-by: Owen Lin <owenlin@chromium.org>
diff --git a/client/cros/audio/audio_helper.py b/client/cros/audio/audio_helper.py
index 8c190a2..3904f5e 100644
--- a/client/cros/audio/audio_helper.py
+++ b/client/cros/audio/audio_helper.py
@@ -6,6 +6,8 @@
 import logging
 import os
 import re
+import shlex
+import subprocess
 import threading
 import time
 
@@ -473,3 +475,31 @@
 
         check_recorded_callback(sox_output_reduced)
 
+def find_hw_soundcard_name(cpuType=None):
+    '''Finds the name of the default hardware soundcard.
+
+    @param cpuType: (Optional) the cpu type.
+    '''
+
+    if not cpuType:
+        cpuType = utils.get_cpu_arch()
+
+    # On Intel platform, return the name "PCH".
+    if cpuType == 'x86_64' or cpuType == 'i386':
+        return 'PCH'
+
+    # On other platforms, if there is only one card, choose it; otherwise,
+    # choose the first card with controls named 'Speaker'
+    cmd = 'amixer -c %d scontrols'
+    id = 0
+    while True:
+        p = subprocess.Popen(shlex.split(cmd % id), stdout=subprocess.PIPE)
+        output, error = p.communicate()
+        if p.wait() != 0: # end of the card list
+            break;
+        if 'speaker' in output.lower():
+            return str(id)
+        id = id + 1
+
+    # If there is only one soundcard, return it, else return not found (None)
+    return '0' if id == 1 else None
diff --git a/client/site_tests/audiovideo_Microphone/audiovideo_Microphone.py b/client/site_tests/audiovideo_Microphone/audiovideo_Microphone.py
index fa8e5c3..af7e52c 100644
--- a/client/site_tests/audiovideo_Microphone/audiovideo_Microphone.py
+++ b/client/site_tests/audiovideo_Microphone/audiovideo_Microphone.py
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import os, time, utils
+import logging, os, tempfile, time, utils
 
 from autotest_lib.client.bin import test, utils
 from autotest_lib.client.common_lib import error
+from autotest_lib.client.cros.audio import audio_helper
 
 DURATION = 30
 BYTES_PER_SAMPLE = 2
@@ -14,38 +15,42 @@
 class audiovideo_Microphone(test.test):
     version = 1
 
-    def verify_capture(self, ch, rate):
-        file_name = "/tmp/%s-%s.capture" % (ch, rate)
-        cmd = "rm -f %s" % file_name
-        utils.system(cmd, ignore_status=True)
-        cmd = "arecord -f dat -D default -c %s -r %s -d %d %s"
-        cmd = cmd % (ch, rate, DURATION, file_name)
-        utils.system(cmd)
-        size = os.path.getsize(file_name)
-        if (size < DURATION * rate * ch * BYTES_PER_SAMPLE * TOLERATE) :
-            raise error.TestFail("File size not correct: %s" % file_name)
-        utils.system("rm -f %s" % file_name)
+    def verify_capture(self, sndcard, ch, rate):
+        cmd = "arecord -D plughw:%s -f dat -c %s -r %s -d %d %s"
+        recorded_file = tempfile.NamedTemporaryFile(mode='w+t').name
+        try:
+            utils.system(cmd % (sndcard, ch, rate, DURATION, recorded_file))
+            size = os.path.getsize(recorded_file)
+            if (size < DURATION * rate * ch * BYTES_PER_SAMPLE * TOLERATE) :
+                raise error.TestFail("File size not correct: %d" % size)
+        finally:
+            os.remove(recorded_file)
 
 
     def run_once(self):
         cpuType = utils.get_cpu_arch()
+
+        sndcard = audio_helper.find_hw_soundcard_name(cpuType)
+        if sndcard is None:
+            raise error.TestError('No sound card detected')
+
         # Microphone should be on by default.
         if cpuType != "arm":
-            cmd = 'amixer -c 0 cget name="Capture Switch" | grep values=on,on'
-            output = utils.system_output(cmd)
+            cmd = 'amixer -D hw:%s cget name="Capture Switch" | grep values=on,on'
+            output = utils.system_output(cmd % sndcard)
             if (output == ''):
                 raise error.TestFail('The microphone is not on by default.')
         else:
             # TODO(jiesun): find consistent way to find the ALSA mixer control
             # names for both internal mic and external mic on ARM, which is
             # independent of the audio codec hardware vendor.
-            print "Warning: Can not verify the microphone capture switch."
+            logging.warning("Can not verify the microphone capture switch.")
 
         # Mono and stereo capturing should work fine @ 44.1KHz and 48KHz.
-        self.verify_capture(1, 44100)
-        self.verify_capture(1, 48000)
-        self.verify_capture(2, 48000)
-        self.verify_capture(2, 44100)
+        self.verify_capture(sndcard, 1, 44100)
+        self.verify_capture(sndcard, 1, 48000)
+        self.verify_capture(sndcard, 2, 48000)
+        self.verify_capture(sndcard, 2, 44100)
 
         # TODO(zhurunz):
         # Low latency capturing should work fine with low CPU usage.