1*b7c941bbSAndroid Build Coastguard Worker#!/usr/bin/python3 2*b7c941bbSAndroid Build Coastguard Worker# 3*b7c941bbSAndroid Build Coastguard Worker# Copyright (C) 2017 The Android Open Source Project 4*b7c941bbSAndroid Build Coastguard Worker# 5*b7c941bbSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the 'License'); 6*b7c941bbSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*b7c941bbSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*b7c941bbSAndroid Build Coastguard Worker# 9*b7c941bbSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*b7c941bbSAndroid Build Coastguard Worker# 11*b7c941bbSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*b7c941bbSAndroid Build Coastguard Worker# distributed under the License is distributed on an 'AS IS' BASIS, 13*b7c941bbSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*b7c941bbSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*b7c941bbSAndroid Build Coastguard Worker# limitations under the License. 16*b7c941bbSAndroid Build Coastguard Worker# 17*b7c941bbSAndroid Build Coastguard Worker 18*b7c941bbSAndroid Build Coastguard Workerimport functools 19*b7c941bbSAndroid Build Coastguard Workerimport math 20*b7c941bbSAndroid Build Coastguard Workerimport socket 21*b7c941bbSAndroid Build Coastguard Workerimport subprocess 22*b7c941bbSAndroid Build Coastguard Workerimport sys 23*b7c941bbSAndroid Build Coastguard Workerimport tempfile 24*b7c941bbSAndroid Build Coastguard Worker 25*b7c941bbSAndroid Build Coastguard Workerfrom android_device import * 26*b7c941bbSAndroid Build Coastguard Worker 27*b7c941bbSAndroid Build Coastguard Worker 28*b7c941bbSAndroid Build Coastguard Workerdef find_free_port(): 29*b7c941bbSAndroid Build Coastguard Worker s = socket.socket() 30*b7c941bbSAndroid Build Coastguard Worker s.bind(('', 0)) 31*b7c941bbSAndroid Build Coastguard Worker return int(s.getsockname()[1]) 32*b7c941bbSAndroid Build Coastguard Worker 33*b7c941bbSAndroid Build Coastguard Worker 34*b7c941bbSAndroid Build Coastguard Workerclass AVD(object): 35*b7c941bbSAndroid Build Coastguard Worker def __init__(self, name, emu_path): 36*b7c941bbSAndroid Build Coastguard Worker self._name = name 37*b7c941bbSAndroid Build Coastguard Worker self._emu_path = emu_path 38*b7c941bbSAndroid Build Coastguard Worker self._opts = '' 39*b7c941bbSAndroid Build Coastguard Worker self._adb_name = None 40*b7c941bbSAndroid Build Coastguard Worker self._emu_proc = None 41*b7c941bbSAndroid Build Coastguard Worker 42*b7c941bbSAndroid Build Coastguard Worker def start(self): 43*b7c941bbSAndroid Build Coastguard Worker if self._emu_proc: 44*b7c941bbSAndroid Build Coastguard Worker raise Exception('Emulator already running') 45*b7c941bbSAndroid Build Coastguard Worker 46*b7c941bbSAndroid Build Coastguard Worker port_adb = find_free_port() 47*b7c941bbSAndroid Build Coastguard Worker port_tty = find_free_port() 48*b7c941bbSAndroid Build Coastguard Worker # -no-window might be useful here 49*b7c941bbSAndroid Build Coastguard Worker if self._name == "local": 50*b7c941bbSAndroid Build Coastguard Worker emu_cmd = "emulator %s-ports %d,%d -gpu on -wipe-data" \ 51*b7c941bbSAndroid Build Coastguard Worker % (self._opts, port_adb, port_tty) 52*b7c941bbSAndroid Build Coastguard Worker else: 53*b7c941bbSAndroid Build Coastguard Worker emu_cmd = "%s -avd %s %s-ports %d,%d" \ 54*b7c941bbSAndroid Build Coastguard Worker % (self._emu_path, self._name, self._opts, port_adb, port_tty) 55*b7c941bbSAndroid Build Coastguard Worker print(emu_cmd) 56*b7c941bbSAndroid Build Coastguard Worker 57*b7c941bbSAndroid Build Coastguard Worker emu_proc = subprocess.Popen(emu_cmd.split(" "), bufsize=-1, stdout=subprocess.DEVNULL, 58*b7c941bbSAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 59*b7c941bbSAndroid Build Coastguard Worker 60*b7c941bbSAndroid Build Coastguard Worker # The emulator ought to be starting now. 61*b7c941bbSAndroid Build Coastguard Worker self._adb_name = "emulator-%d" % (port_tty - 1) 62*b7c941bbSAndroid Build Coastguard Worker self._emu_proc = emu_proc 63*b7c941bbSAndroid Build Coastguard Worker 64*b7c941bbSAndroid Build Coastguard Worker def stop(self): 65*b7c941bbSAndroid Build Coastguard Worker if not self._emu_proc: 66*b7c941bbSAndroid Build Coastguard Worker raise Exception('Emulator not currently running') 67*b7c941bbSAndroid Build Coastguard Worker self._emu_proc.kill() 68*b7c941bbSAndroid Build Coastguard Worker (out, err) = self._emu_proc.communicate() 69*b7c941bbSAndroid Build Coastguard Worker self._emu_proc = None 70*b7c941bbSAndroid Build Coastguard Worker return out, err 71*b7c941bbSAndroid Build Coastguard Worker 72*b7c941bbSAndroid Build Coastguard Worker def get_serial(self): 73*b7c941bbSAndroid Build Coastguard Worker if not self._emu_proc: 74*b7c941bbSAndroid Build Coastguard Worker raise Exception('Emulator not currently running') 75*b7c941bbSAndroid Build Coastguard Worker return self._adb_name 76*b7c941bbSAndroid Build Coastguard Worker 77*b7c941bbSAndroid Build Coastguard Worker def get_device(self): 78*b7c941bbSAndroid Build Coastguard Worker if not self._emu_proc: 79*b7c941bbSAndroid Build Coastguard Worker raise Exception('Emulator not currently running') 80*b7c941bbSAndroid Build Coastguard Worker return AndroidDevice(self._adb_name) 81*b7c941bbSAndroid Build Coastguard Worker 82*b7c941bbSAndroid Build Coastguard Worker def configure_screen(self, density, width_dp, height_dp): 83*b7c941bbSAndroid Build Coastguard Worker width_px = int(math.ceil(width_dp * density / 1600) * 10) 84*b7c941bbSAndroid Build Coastguard Worker height_px = int(math.ceil(height_dp * density / 1600) * 10) 85*b7c941bbSAndroid Build Coastguard Worker self._opts = "-prop qemu.sf.lcd_density=%d -skin %dx%d " % (density, width_px, height_px) 86