1#!/usr/bin/env python2 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 traceback 14 15import common # pylint: disable=unused-import 16from autotest_lib.client.bin import utils 17from autotest_lib.client.common_lib import logging_config 18from autotest_lib.client.cros import constants 19from autotest_lib.client.cros import upstart 20from autotest_lib.client.cros import xmlrpc_server 21from autotest_lib.client.cros.multimedia import assistant_facade_native 22from autotest_lib.client.cros.multimedia import audio_facade_native 23from autotest_lib.client.cros.multimedia import bluetooth_facade_native 24from autotest_lib.client.cros.multimedia import browser_facade_native 25from autotest_lib.client.cros.multimedia import cfm_facade_native 26from autotest_lib.client.cros.multimedia import display_facade_native 27from autotest_lib.client.cros.multimedia import facade_resource 28from autotest_lib.client.cros.multimedia import graphics_facade_native 29from autotest_lib.client.cros.multimedia import input_facade_native 30from autotest_lib.client.cros.multimedia import kiosk_facade_native 31from autotest_lib.client.cros.multimedia import system_facade_native 32from autotest_lib.client.cros.multimedia import usb_facade_native 33from autotest_lib.client.cros.multimedia import video_facade_native 34 35 36class MultimediaXmlRpcDelegate(xmlrpc_server.XmlRpcDelegate): 37 """XML RPC delegate for multimedia testing.""" 38 39 def __init__(self, resource): 40 """Initializes the facade objects.""" 41 42 # TODO: (crbug.com/618111) Add test driven switch for 43 # supporting arc_mode enabled or disabled. At this time 44 # if ARC build is tested, arc_mode is always enabled. 45 arc_res = None 46 if utils.get_board_property('CHROMEOS_ARC_VERSION'): 47 logging.info('Using ARC resource on ARC enabled board.') 48 from autotest_lib.client.cros.multimedia import arc_resource 49 arc_res = arc_resource.ArcResource() 50 51 self._facades = { 52 'assistant': 53 assistant_facade_native.AssistantFacadeNative(resource), 54 'audio': 55 audio_facade_native.AudioFacadeNative(resource, 56 arc_resource=arc_res), 57 'bluetooth': 58 bluetooth_facade_native.BluetoothFacadeNative(), 59 'video': 60 video_facade_native.VideoFacadeNative(resource, 61 arc_resource=arc_res), 62 'display': 63 display_facade_native.DisplayFacadeNative(resource), 64 'system': 65 system_facade_native.SystemFacadeNative(), 66 'usb': 67 usb_facade_native.USBFacadeNative(), 68 'browser': 69 browser_facade_native.BrowserFacadeNative(resource), 70 'input': 71 input_facade_native.InputFacadeNative(), 72 'cfm_main_screen': 73 cfm_facade_native.CFMFacadeNative(resource, 'hotrod'), 74 'cfm_mimo_screen': 75 cfm_facade_native.CFMFacadeNative(resource, 'control'), 76 'kiosk': 77 kiosk_facade_native.KioskFacadeNative(resource), 78 'graphics': 79 graphics_facade_native.GraphicsFacadeNative() 80 } 81 82 83 def __exit__(self, exception, value, traceback): 84 """Clean up the resources.""" 85 self._facades['audio'].cleanup() 86 87 88 def _dispatch(self, method, params): 89 """Dispatches the method to the proper facade. 90 91 We turn off allow_dotted_names option. The method handles the dot 92 and dispatches the method to the proper native facade, like 93 DisplayFacadeNative. 94 95 """ 96 try: 97 try: 98 if '.' not in method: 99 func = getattr(self, method) 100 else: 101 facade_name, method_name = method.split('.', 1) 102 if facade_name in self._facades: 103 func = getattr(self._facades[facade_name], method_name) 104 else: 105 raise Exception('unknown facade: %s' % facade_name) 106 except AttributeError: 107 raise Exception('method %s not supported' % method) 108 109 logging.info('Dispatching method %s with args %s', 110 str(func), str(params)) 111 return func(*params) 112 except: 113 # TODO(ihf): Try to return meaningful stacktraces from the client. 114 return traceback.format_exc() 115 116 117def config_logging(): 118 """Configs logging to be verbose and use console handler.""" 119 config = logging_config.LoggingConfig() 120 config.configure_logging(use_console=True, verbose=True) 121 122 123def main(): 124 """The main function, to run the XMLRPC server.""" 125 parser = argparse.ArgumentParser() 126 parser.add_argument('-d', '--debug', action='store_true', required=False, 127 help=('create a debug console with a ServerProxy "s" ' 128 'connecting to the XML RPC sever at localhost')) 129 args = parser.parse_args() 130 pid = os.getpid() 131 132 if args.debug: 133 s = six.moves.xmlrpc_client.ServerProxy('http://localhost:%d' % 134 constants.MULTIMEDIA_XMLRPC_SERVER_PORT, 135 allow_none=True) 136 code.interact(local=locals()) 137 else: 138 config_logging() 139 logging.debug('multimedia_xmlrpc_server[%s] main...', pid) 140 xmlrpc_server.terminate_old(__file__) 141 142 # bind before full setup, so the error is the last thing in the log 143 server = xmlrpc_server.XmlRpcServer( 144 'localhost', constants.MULTIMEDIA_XMLRPC_SERVER_PORT) 145 146 # Restart Cras to clean up any audio activities. 147 upstart.restart_job('cras') 148 149 with facade_resource.FacadeResource() as res: 150 server.register_delegate(MultimediaXmlRpcDelegate(res)) 151 server.run() 152 logging.debug('multimedia_xmlrpc_server[%s] exiting...', pid) 153 logging.debug('multimedia_xmlrpc_server[%s] done.\n', pid) 154 155 156if __name__ == '__main__': 157 main() 158