1#
2# Copyright (C) 2018 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 host_controller import common
20from host_controller.command_processor import base_command_processor
21from host_controller.utils.ipc import file_lock_semaphore
22from host_controller.utils.usb import usb_utils
23
24from vts.utils.python.common import cmd_utils
25
26
27class CommandFastboot(base_command_processor.BaseCommandProcessor):
28    """Command processor for fastboot command.
29
30    Attributes:
31        arg_parser: ConsoleArgumentParser object, argument parser.
32        command: string, command name which this processor will handle.
33        command_detail: string, detailed explanation for the command.
34    """
35
36    command = "fastboot"
37    command_detail = "Runs a fastboot command."
38
39    # @Override
40    def SetUp(self):
41        """Initializes the parser for device command."""
42        self.sem_fastboot = file_lock_semaphore.FileLockSemaphore("fastboot")
43        self.arg_parser.add_argument(
44            "--serial",
45            "-s",
46            required=True,
47            default=None,
48            help="The target device serial to run the command.")
49        self.arg_parser.add_argument(
50            "--retry",
51            type=int,
52            default=2,
53            help="The number of times to retry if a command fails.")
54        self.arg_parser.add_argument(
55            "--timeout",
56            type=float,
57            default=common.DEFAULT_DEVICE_TIMEOUT_SECS,
58            help="The maximum timeout value of this command in seconds. "
59            "Set to 0 to disable the timeout functionality.")
60        self.arg_parser.add_argument(
61            "command",
62            metavar="COMMAND",
63            nargs="+",
64            help="The command to be executed. If the command contains "
65            "arguments starting with \"-\", place the command at end of line "
66            "after \"--\".")
67
68    # @Override
69    def Run(self, arg_line):
70        """Runs a fastboot command."""
71        args = self.arg_parser.ParseLine(arg_line)
72        cmd_list = ["fastboot"]
73        if args.serial:
74            if "," in args.serial:
75                logging.error("Only one serial can be specified")
76                return False
77            cmd_list.append("-s %s" % args.serial)
78        cmd_list.extend(self.ReplaceVars(args.command))
79        cmd = " ".join(cmd_list)
80        for _ in range(args.retry + 1):
81            self.sem_fastboot.Acquire()
82            if args.timeout == 0:
83                stdout, stderr, retcode = cmd_utils.ExecuteOneShellCommand(cmd)
84            else:
85                stdout, stderr, retcode = cmd_utils.ExecuteOneShellCommand(
86                    cmd, args.timeout,
87                    usb_utils.ResetUsbDeviceOfSerial_Callback, args.serial)
88            self.sem_fastboot.Release()
89            if stdout:
90                logging.info(stdout)
91            if stderr:
92                logging.error(stderr)
93            if retcode == 0:
94                return
95            logging.warn("Retrying... (%s)", cmd)
96
97        if self.console.job_pool and args.serial:
98            self.console.device_status[
99                args.serial] = common._DEVICE_STATUS_DICT["error"]
100        return False
101