• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2# Copyright (C) 2016 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import logging
18
19from vts.runners.host import errors
20from vts.proto import AndroidSystemControlMessage_pb2 as ASysCtrlMsg
21from vts.runners.host.tcp_client import vts_tcp_client
22from vts.utils.python.mirror import shell_mirror_object
23
24
25class ShellMirror(object):
26    """The class that acts as the mirror to an Android device's shell terminal.
27
28    This class holds and manages the life cycle of multiple mirror objects that
29    map to different shell instances.
30
31    Attributes:
32        _host_command_port: int, the host-side port for command-response
33                            sessions.
34        _shell_mirrors: dict, key is instance name, value is mirror object.
35        enabled: bool, whether remote shell feature is enabled for the device.
36    """
37
38    def __init__(self, host_command_port):
39        self._shell_mirrors = {}
40        self._host_command_port = host_command_port
41        self.enabled = True
42
43    def __del__(self):
44        for instance_name in self._shell_mirrors:
45            self.RemoveShell(instance_name)
46        self._shell_mirrors = {}
47
48    def RemoveShell(self, instance_name):
49        """Removes a shell mirror object.
50
51        Args:
52            instance_name: string, the shell terminal instance name.
53        """
54        shell_mirror = self._shell_mirrors[instance_name]
55        shell_mirror.CleanUp()
56
57    def InvokeTerminal(self, instance_name, bits=32):
58        """Initiates a handler for a particular conventional HAL.
59
60        This will initiate a driver service for a shell on the target side,
61        create the top level mirror object for the same, and register it in
62        the manager.
63
64        Args:
65            instance_name: string, the shell terminal instance name.
66            bits: integer, processor architecture indicator: 32 or 64.
67        """
68        if not instance_name:
69            raise error.ComponentLoadingError("instance_name is None")
70        if bits not in [32, 64]:
71            raise error.ComponentLoadingError(
72                "Invalid value for bits: %s" % bits)
73
74        client = vts_tcp_client.VtsTcpClient()
75        client.Connect(command_port=self._host_command_port)
76
77        logging.info("Init the driver service for shell, %s", instance_name)
78        launched = client.LaunchDriverService(
79            driver_type=ASysCtrlMsg.VTS_DRIVER_TYPE_SHELL,
80            service_name="shell_" + instance_name,
81            bits=bits)
82
83        if not launched:
84            raise errors.ComponentLoadingError(
85                "Failed to launch shell driver service %s" % instance_name)
86
87        mirror_object = shell_mirror_object.ShellMirrorObject(client)
88        self._shell_mirrors[instance_name] = mirror_object
89
90    def __getattr__(self, name):
91        """Get shell sessions through attribute.
92
93        When a session is retrieved here, the 'enabled' flag of the shell mirror
94        object is checked and synchronized with shell mirror.
95
96        Args:
97            name: string, session name
98
99        Returns:
100            ShellMirrorObject, a remote shell session.
101
102        Raises:
103            KeyError when attribute does not exist.
104        """
105        res = self._shell_mirrors[name]
106
107        if res.enabled != self.enabled:
108            res.enabled = self.enabled
109        return res
110
111    @property
112    def default(self):
113        """returns a default shell mirror object that can execute a shell command"""
114        name = '_default'
115        if not hasattr(self, name):
116            self.InvokeTerminal(name)
117        return getattr(self, name)
118
119    def Execute(self, command, no_except=False):
120        """Execute a shell command with default shell terminal"""
121        return self.default.Execute(command, no_except)
122