Home | History | Annotate | Download | only in audio_AudioARCPlayback
      1 # Copyright 2016 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """This is a server side ARC audio playback test using the Chameleon board."""
      6 
      7 import logging
      8 import os
      9 import time
     10 
     11 from autotest_lib.client.bin import utils
     12 from autotest_lib.client.cros.chameleon import audio_test_utils
     13 from autotest_lib.client.cros.chameleon import chameleon_audio_helper
     14 from autotest_lib.client.cros.chameleon import chameleon_audio_ids
     15 from autotest_lib.client.cros.multimedia import arc_resource_common
     16 from autotest_lib.server import autotest
     17 from autotest_lib.server.cros.audio import audio_test
     18 from autotest_lib.server.cros.multimedia import remote_facade_factory
     19 
     20 
     21 class audio_AudioARCPlayback(audio_test.AudioTest):
     22     """Server side ARC audio playback test.
     23 
     24     This test talks to a Chameleon board and a Cros device to verify
     25     audio playback function of the Cros device with ARC.
     26 
     27     """
     28     version = 1
     29     DELAY_AFTER_BINDING = 0.5
     30     WAIT_CLIENT_READY_TIMEOUT_SECS = 150
     31     WAIT_PLAYBACK_SECS = 10
     32 
     33     def run_once(self, host, source_id, sink_id, recorder_id,
     34                  golden_file, switch_hsp=False):
     35         """Runs record test through ARC on Cros device.
     36 
     37         @param host: device under test, a CrosHost.
     38         @param source_id: An ID defined in chameleon_audio_ids for source.
     39         @param sink_id: An ID defined in chameleon_audio_ids for sink if needed.
     40                         Currently this is only used on bluetooth.
     41         @param recorder_id: An ID defined in chameleon_audio_ids for recording.
     42         @param golden_file: A test file defined in audio_test_data.
     43         @param switch_hsp: Run a recording process on Cros device. This is
     44                            to trigger Cros switching from A2DP to HSP.
     45 
     46         """
     47         self.host = host
     48 
     49         if (source_id == chameleon_audio_ids.CrosIds.SPEAKER and
     50             not audio_test_utils.has_internal_speaker(host)):
     51             return
     52 
     53         self.client_at = None
     54 
     55         # Runs a client side test to start Chrome and install Play Music app.
     56         self.setup_playmusic_app()
     57 
     58         # Do not start Chrome because client side test had started it.
     59         # Do not install autotest because client side test had installed it.
     60         factory = remote_facade_factory.RemoteFacadeFactory(
     61                 host, no_chrome=True, install_autotest=False,
     62                 results_dir=self.resultsdir)
     63 
     64         # Setup Chameleon and create widgets.
     65         host.chameleon.setup_and_reset(self.outputdir)
     66 
     67         widget_factory = chameleon_audio_helper.AudioWidgetFactory(
     68                 factory, host)
     69 
     70         source = widget_factory.create_widget(source_id, use_arc=True)
     71         recorder = widget_factory.create_widget(recorder_id)
     72 
     73         # Chameleon Mic does not need binding.
     74         binding = (recorder_id != chameleon_audio_ids.ChameleonIds.MIC)
     75 
     76         binder = None
     77 
     78         if binding:
     79             if sink_id:
     80                 sink = widget_factory.create_widget(sink_id)
     81                 binder = widget_factory.create_binder(source, sink, recorder)
     82             else:
     83                 binder = widget_factory.create_binder(source, recorder)
     84 
     85         # Second peak ratio is determined by quality of audio path.
     86         second_peak_ratio = audio_test_utils.get_second_peak_ratio(
     87                 source_id=source_id,
     88                 recorder_id=recorder_id,
     89                 is_hsp=switch_hsp)
     90 
     91         with chameleon_audio_helper.bind_widgets(binder):
     92             time.sleep(self.DELAY_AFTER_BINDING)
     93 
     94             audio_facade = factory.create_audio_facade()
     95 
     96             audio_test_utils.dump_cros_audio_logs(
     97                     host, audio_facade, self.resultsdir, 'after_binding')
     98 
     99             # Checks the node selected by CRAS is correct.
    100             audio_test_utils.check_output_port(audio_facade, source.port_id)
    101 
    102             if switch_hsp:
    103                 audio_test_utils.switch_to_hsp(audio_facade)
    104 
    105             logging.info('Setting playback file on Cros device')
    106             source.set_playback_data(golden_file)
    107 
    108             logging.info('Start recording from Chameleon')
    109             recorder.start_recording()
    110 
    111             logging.info('Start playing %s on Cros device',
    112                          golden_file.path)
    113             source.start_playback()
    114 
    115             time.sleep(self.WAIT_PLAYBACK_SECS)
    116 
    117             recorder.stop_recording()
    118             logging.info('Stopped recording from Chameleon.')
    119 
    120             audio_test_utils.dump_cros_audio_logs(
    121                     host, audio_facade, self.resultsdir,
    122                     'after_recording')
    123 
    124             recorder.read_recorded_binary()
    125             logging.info('Read recorded binary from Chameleon.')
    126 
    127             recorded_file = os.path.join(self.resultsdir, "recorded.raw")
    128             logging.info('Saving recorded data to %s', recorded_file)
    129             recorder.save_file(recorded_file)
    130 
    131             audio_test_utils.check_recorded_frequency(
    132                     golden_file, recorder,
    133                     second_peak_ratio=second_peak_ratio)
    134 
    135 
    136     def run_client_side_test(self):
    137         """Runs a client side test on Cros device in background."""
    138         self.client_at = autotest.Autotest(self.host)
    139         logging.info('Start running client side test %s',
    140                      arc_resource_common.PlayMusicProps.TEST_NAME)
    141         self.client_at.run_test(
    142                 arc_resource_common.PlayMusicProps.TEST_NAME,
    143                 background=True)
    144 
    145 
    146     def setup_playmusic_app(self):
    147         """Setups Play Music app on Cros device.
    148 
    149         Runs a client side test on Cros device to start Chrome and ARC and
    150         install Play Music app.
    151         Wait for it to be ready.
    152 
    153         """
    154         # Removes ready tag that server side test should wait for later.
    155         self.remove_ready_tag()
    156 
    157         # Runs the client side test.
    158         self.run_client_side_test()
    159 
    160         logging.info('Waiting for client side Play Music app to be ready')
    161 
    162         # Waits for ready tag to be posted by client side test.
    163         utils.poll_for_condition(condition=self.ready_tag_exists,
    164                                  timeout=self.WAIT_CLIENT_READY_TIMEOUT_SECS,
    165                                  desc='Wait for client side test being ready',
    166                                  sleep_interval=1)
    167 
    168         logging.info('Client side Play Music app is ready')
    169 
    170 
    171     def cleanup(self):
    172         """Cleanup of the test."""
    173         self.touch_exit_tag()
    174         super(audio_AudioARCPlayback, self).cleanup()
    175 
    176 
    177     def remove_ready_tag(self):
    178         """Removes ready tag on Cros device."""
    179         if self.ready_tag_exists():
    180             self.host.run(command='rm %s' % (
    181                     arc_resource_common.PlayMusicProps.READY_TAG_FILE))
    182 
    183 
    184     def touch_exit_tag(self):
    185         """Touches exit tag on Cros device to stop client side test."""
    186         self.host.run(command='touch %s' % (
    187                 arc_resource_common.PlayMusicProps.EXIT_TAG_FILE))
    188 
    189 
    190     def ready_tag_exists(self):
    191         """Checks if ready tag exists.
    192 
    193         @returns: True if the tag file exists. False otherwise.
    194 
    195         """
    196         return self.host.path_exists(
    197                 arc_resource_common.PlayMusicProps.READY_TAG_FILE)
    198