1#!/usr/bin/env python 2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""XML RPC server for multimedia testing.""" 7 8import argparse 9import code 10import logging 11import os 12import six.moves.xmlrpc_client 13import sys 14import traceback 15 16import common # pylint: disable=unused-import 17from autotest_lib.client.bin import utils 18from autotest_lib.client.common_lib import logging_config 19from autotest_lib.client.cros import constants 20from autotest_lib.client.cros import upstart 21from autotest_lib.client.cros import xmlrpc_server 22from autotest_lib.client.cros.multimedia import assistant_facade 23from autotest_lib.client.cros.multimedia import audio_facade 24from autotest_lib.client.cros.multimedia import browser_facade 25from autotest_lib.client.cros.multimedia import cfm_facade 26from autotest_lib.client.cros.multimedia import display_facade 27from autotest_lib.client.cros.multimedia import facade_resource 28from autotest_lib.client.cros.multimedia import graphics_facade 29from autotest_lib.client.cros.multimedia import input_facade 30from autotest_lib.client.cros.multimedia import kiosk_facade 31from autotest_lib.client.cros.multimedia import system_facade 32from autotest_lib.client.cros.multimedia import usb_facade 33from autotest_lib.client.cros.multimedia import video_facade 34 35# Python3 required for the following: 36if sys.version_info[0] >= 3: 37 from autotest_lib.client.cros.multimedia import bluetooth_facade 38 39 40class MultimediaXmlRpcDelegate(xmlrpc_server.XmlRpcDelegate): 41 """XML RPC delegate for multimedia testing.""" 42 43 def __init__(self, resource): 44 """Initializes the facade objects.""" 45 46 # TODO: (crbug.com/618111) Add test driven switch for 47 # supporting arc_mode enabled or disabled. At this time 48 # if ARC build is tested, arc_mode is always enabled. 49 arc_res = None 50 if utils.get_board_property('CHROMEOS_ARC_VERSION'): 51 logging.info('Using ARC resource on ARC enabled board.') 52 from autotest_lib.client.cros.multimedia import arc_resource 53 arc_res = arc_resource.ArcResource() 54 55 self._facades = { 56 'assistant': 57 assistant_facade.AssistantFacadeLocal(resource), 58 'audio': 59 audio_facade.AudioFacadeLocal(resource, 60 arc_resource=arc_res), 61 'video': 62 video_facade.VideoFacadeLocal(resource, 63 arc_resource=arc_res), 64 'display': 65 display_facade.DisplayFacadeLocal(resource), 66 'system': 67 system_facade.SystemFacadeLocal(), 68 'usb': 69 usb_facade.USBFacadeLocal(), 70 'browser': 71 browser_facade.BrowserFacadeLocal(resource), 72 'input': 73 input_facade.InputFacadeLocal(), 74 'cfm_main_screen': 75 cfm_facade.CFMFacadeLocal(resource, 'hotrod'), 76 'cfm_mimo_screen': 77 cfm_facade.CFMFacadeLocal(resource, 'control'), 78 'kiosk': 79 kiosk_facade.KioskFacadeLocal(resource), 80 'graphics': 81 graphics_facade.GraphicsFacadeLocal() 82 } 83 84 # Limit some facades to python3 85 if sys.version_info[0] >= 3: 86 self._facades[ 87 'bluetooth'] = bluetooth_facade.BluezFacadeLocal() 88 self._facades['floss'] = bluetooth_facade.FlossFacadeLocal( 89 ) 90 91 def __exit__(self, exception, value, traceback): 92 """Clean up the resources.""" 93 self._facades['audio'].cleanup() 94 95 if 'floss' in self._facades: 96 self._facades['floss'].cleanup() 97 98 def _dispatch(self, method, params): 99 """Dispatches the method to the proper facade. 100 101 We turn off allow_dotted_names option. The method handles the dot 102 and dispatches the method to the proper native facade, like 103 DisplayFacadeLocal. 104 105 """ 106 try: 107 try: 108 if '.' not in method: 109 func = getattr(self, method) 110 else: 111 facade_name, method_name = method.split('.', 1) 112 if facade_name in self._facades: 113 func = getattr(self._facades[facade_name], method_name) 114 else: 115 raise Exception('unknown facade: %s' % facade_name) 116 except AttributeError: 117 raise Exception('method %s not supported' % method) 118 119 logging.info('Dispatching method %s with args %s', 120 str(func), str(params)) 121 return func(*params) 122 except: 123 # TODO(ihf): Try to return meaningful stacktraces from the client. 124 return traceback.format_exc() 125 126 127def config_logging(): 128 """Configs logging to be verbose and use console handler.""" 129 config = logging_config.LoggingConfig() 130 config.configure_logging(use_console=True, verbose=True) 131 132 133def main(): 134 """The main function, to run the XMLRPC server.""" 135 parser = argparse.ArgumentParser() 136 parser.add_argument('-d', '--debug', action='store_true', required=False, 137 help=('create a debug console with a ServerProxy "s" ' 138 'connecting to the XML RPC sever at localhost')) 139 args = parser.parse_args() 140 pid = os.getpid() 141 142 if args.debug: 143 s = six.moves.xmlrpc_client.ServerProxy('http://localhost:%d' % 144 constants.MULTIMEDIA_XMLRPC_SERVER_PORT, 145 allow_none=True) 146 code.interact(local=locals()) 147 else: 148 config_logging() 149 logging.debug('multimedia_xmlrpc_server[%s] main...', pid) 150 xmlrpc_server.terminate_old(__file__) 151 152 # bind before full setup, so the error is the last thing in the log 153 server = xmlrpc_server.XmlRpcServer( 154 'localhost', constants.MULTIMEDIA_XMLRPC_SERVER_PORT) 155 156 # Restart Cras to clean up any audio activities. 157 upstart.restart_job('cras') 158 159 with facade_resource.FacadeResource() as res: 160 server.register_delegate(MultimediaXmlRpcDelegate(res)) 161 server.run() 162 logging.debug('multimedia_xmlrpc_server[%s] exiting...', pid) 163 logging.debug('multimedia_xmlrpc_server[%s] done.\n', pid) 164 165 166if __name__ == '__main__': 167 main() 168