1# Copyright 2016 Google Inc. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Shared library for frontends to jsonrpc servers.""" 15 16import code 17import os 18import pprint 19import sys 20 21from mobly.controllers import android_device 22 23 24class Error(Exception): 25 pass 26 27 28class JsonRpcShellBase: 29 30 def _start_services(self, console_env): 31 """Starts the services needed by this client and adds them to console_env. 32 33 Must be implemented by subclasses. 34 """ 35 raise NotImplementedError() 36 37 def _get_banner(self, serial): 38 """Returns the user-friendly banner message to print before the console. 39 40 Must be implemented by subclasses. 41 """ 42 raise NotImplementedError() 43 44 def load_device(self, serial=None): 45 """Creates an AndroidDevice for the given serial number. 46 47 If no serial is given, it will read from the ANDROID_SERIAL 48 environmental variable. If the environmental variable is not set, then 49 it will read from 'adb devices' if there is only one. 50 """ 51 serials = android_device.list_adb_devices() 52 if not serials: 53 raise Error('No adb device found!') 54 # No serial provided, try to pick up the device automatically. 55 if not serial: 56 env_serial = os.environ.get('ANDROID_SERIAL', None) 57 if env_serial is not None: 58 serial = env_serial 59 elif len(serials) == 1: 60 serial = serials[0] 61 else: 62 raise Error( 63 'Expected one phone, but %d found. Use the -s flag or ' 64 'specify ANDROID_SERIAL.' 65 % len(serials) 66 ) 67 if serial not in serials: 68 raise Error('Device "%s" is not found by adb.' % serial) 69 ads = android_device.get_instances([serial]) 70 assert len(ads) == 1 71 self._ad = ads[0] 72 73 def start_console(self): 74 # Set up initial console environment 75 console_env = { 76 'ad': self._ad, 77 'pprint': pprint.pprint, 78 } 79 80 # Start the services 81 self._start_services(console_env) 82 83 # Start the console 84 console_banner = self._get_banner(self._ad.serial) 85 code.interact(banner=console_banner, local=console_env) 86 87 # Tear everything down 88 self._ad.services.stop_all() 89 90 def main(self, serial=None): 91 try: 92 self.load_device(serial) 93 except Error as e: 94 print('ERROR: %s' % e, file=sys.stderr) 95 sys.exit(1) 96 self.start_console() 97