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