Home | History | Annotate | Download | only in audio_AudioArtifacts
      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 audio volume test using the Chameleon board."""
      6 
      7 import logging
      8 import os
      9 import time
     10 
     11 from autotest_lib.client.cros.chameleon import audio_test_utils
     12 from autotest_lib.client.cros.chameleon import chameleon_audio_ids
     13 from autotest_lib.client.cros.chameleon import chameleon_audio_helper
     14 from autotest_lib.server.cros.audio import audio_test
     15 from autotest_lib.server.cros.multimedia import remote_facade_factory
     16 
     17 
     18 class audio_AudioArtifacts(audio_test.AudioTest):
     19     """Server side audio artifacts test.
     20 
     21     This test talks to a Chameleon board and a Cros device to detect
     22     audio artifacts from the Cros device.
     23 
     24     """
     25     version = 1
     26     RECORD_SECONDS = 20
     27     DELAY_AFTER_BINDING = 0.5
     28     KEEP_VOLUME_SECONDS = 0.5
     29     START_PLAYBACK_SECONDS = 0.5
     30 
     31     def run_once(self, host, source_id, sink_id, recorder_id,
     32                  golden_file, switch_hsp=False,
     33                  mute_duration_in_secs=None,
     34                  volume_changes=None,
     35                  record_secs=None):
     36         """Running audio volume test.
     37 
     38         mute_duration_in_secs and volume_changes couldn't be both not None.
     39 
     40         @param host: device under test CrosHost
     41         @param source_id: An ID defined in chameleon_audio_ids for source.
     42         @param sink_id: An ID defined in chameleon_audio_ids for sink if needed.
     43                         Currently this is only used on bluetooth.
     44         @param recorder: An ID defined in chameleon_audio_ids for recording.
     45         @param golden_file: A test file defined in audio_test_data.
     46         @param switch_hsp: Run a recording process on Cros device. This is
     47                            to trigger Cros switching from A2DP to HSP.
     48         @param mute_duration_in_secs: List of each duration of mute. For example,
     49                                       [0.4, 0.6] will have two delays, each
     50                                       duration will be 0.4 secs and 0.6 secs.
     51                                       And, between delays, there will be
     52                                       KEEP_VOLUME_SECONDS secs sine wave.
     53         @param volume_changes: List consisting of -1 and +1, where -1 denoting
     54                            decreasing volume, +1 denoting increasing volume.
     55                            Between each changes, the volume will be kept for
     56                            KEEP_VOLUME_SECONDS secs.
     57         @param record_secs: The duration of recording in seconds. If it is not
     58                             set, duration of the test data will be used. If
     59                             duration of test data is not set either, default
     60                             RECORD_SECONDS will be used.
     61 
     62         """
     63         if (source_id == chameleon_audio_ids.CrosIds.SPEAKER and
     64             not audio_test_utils.has_internal_speaker(host)):
     65             return
     66 
     67         chameleon_board = host.chameleon
     68         factory = remote_facade_factory.RemoteFacadeFactory(
     69                 host, results_dir=self.resultsdir)
     70 
     71         chameleon_board.setup_and_reset(self.outputdir)
     72 
     73         widget_factory = chameleon_audio_helper.AudioWidgetFactory(
     74                 factory, host)
     75 
     76         source = widget_factory.create_widget(source_id)
     77         recorder = widget_factory.create_widget(recorder_id)
     78 
     79         # Chameleon Mic does not need binding.
     80         binding = (recorder_id != chameleon_audio_ids.ChameleonIds.MIC)
     81 
     82         binder = None
     83 
     84         if binding:
     85             if sink_id:
     86                 sink = widget_factory.create_widget(sink_id)
     87                 binder = widget_factory.create_binder(source, sink, recorder)
     88             else:
     89                 binder = widget_factory.create_binder(source, recorder)
     90 
     91         start_volume, low_volume, high_volume = 75, 50, 100
     92 
     93         if not record_secs:
     94             if golden_file.duration_secs:
     95                 record_secs = golden_file.duration_secs
     96             else:
     97                 record_secs = self.RECORD_SECONDS
     98         logging.debug('Record duration: %f seconds', record_secs)
     99 
    100         # Checks if the file is local or is served on web.
    101         file_url = getattr(golden_file, 'url', None)
    102 
    103         with chameleon_audio_helper.bind_widgets(binder):
    104             # Checks the node selected by cras is correct.
    105             time.sleep(self.DELAY_AFTER_BINDING)
    106             audio_facade = factory.create_audio_facade()
    107 
    108             audio_test_utils.dump_cros_audio_logs(
    109                     host, audio_facade, self.resultsdir, 'after_binding')
    110 
    111             audio_facade.set_chrome_active_volume(start_volume)
    112 
    113             audio_test_utils.check_output_port(audio_facade, source.port_id)
    114 
    115             if switch_hsp:
    116                 audio_test_utils.switch_to_hsp(audio_facade)
    117 
    118             if not file_url:
    119                 logging.info('Setting playback data on Cros device')
    120                 source.set_playback_data(golden_file)
    121 
    122             logging.info('Start recording from Chameleon.')
    123             recorder.start_recording()
    124 
    125             if not file_url:
    126                 logging.info('Start playing %s on Cros device',
    127                              golden_file.path)
    128                 source.start_playback()
    129             else:
    130                 logging.info('Start playing %s on Cros device using browser',
    131                              file_url)
    132                 browser_facade = factory.create_browser_facade()
    133                 tab_descriptor = browser_facade.new_tab(file_url)
    134 
    135             if volume_changes:
    136                 time.sleep(self.START_PLAYBACK_SECONDS)
    137                 for x in volume_changes:
    138                     if x == -1:
    139                         audio_facade.set_chrome_active_volume(low_volume)
    140                     if x == +1:
    141                         audio_facade.set_chrome_active_volume(high_volume)
    142                     time.sleep(self.KEEP_VOLUME_SECONDS)
    143                 passed_time_secs = self.START_PLAYBACK_SECONDS
    144                 passed_time_secs += len(volume_changes) * self.KEEP_VOLUME_SECONDS
    145                 rest = max(0, record_secs - passed_time_secs)
    146                 time.sleep(rest)
    147             elif mute_duration_in_secs:
    148                 time.sleep(self.START_PLAYBACK_SECONDS)
    149                 passed_time_seconds = self.START_PLAYBACK_SECONDS
    150                 for mute_secs in mute_duration_in_secs:
    151                     audio_facade.set_chrome_active_volume(0)
    152                     time.sleep(mute_secs)
    153                     audio_facade.set_chrome_active_volume(start_volume)
    154                     time.sleep(self.KEEP_VOLUME_SECONDS)
    155                     passed_time_seconds += mute_secs + self.KEEP_VOLUME_SECONDS
    156                 rest = max(0, record_secs - passed_time_seconds)
    157                 time.sleep(rest)
    158             else:
    159                 time.sleep(record_secs)
    160 
    161             recorder.stop_recording()
    162             logging.info('Stopped recording from Chameleon.')
    163 
    164             audio_test_utils.dump_cros_audio_logs(
    165                     host, audio_facade, self.resultsdir,
    166                     'after_recording')
    167 
    168             if file_url:
    169                 browser_facade.close_tab(tab_descriptor)
    170             else:
    171                 source.stop_playback()
    172 
    173             recorder.read_recorded_binary()
    174             logging.info('Read recorded binary from Chameleon.')
    175 
    176             recorded_file = os.path.join(
    177                     self.resultsdir, "recorded.raw" )
    178             logging.info('Saving recorded data to %s', recorded_file)
    179             recorder.save_file(recorded_file)
    180 
    181             audio_test_utils.check_recorded_frequency(
    182                     golden_file, recorder,
    183                     check_artifacts=True,
    184                     mute_durations=mute_duration_in_secs,
    185                     volume_changes=volume_changes)
    186 
    187