1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import importlib
import os
import stat
from host_controller import common
from host_controller.build import build_flasher
from host_controller.command_processor import base_command_processor
class CommandFlash(base_command_processor.BaseCommandProcessor):
"""Command processor for flash command.
Attributes:
arg_parser: ConsoleArgumentParser object, argument parser.
console: cmd.Cmd console object.
command: string, command name which this processor will handle.
command_detail: string, detailed explanation for the command.
"""
command = "flash"
command_detail = "Flash images to a device."
# @Override
def SetUp(self):
"""Initializes the parser for flash command."""
self.arg_parser.add_argument(
"--image",
help=("The file name of an image to flash."
" Used to flash a single image."))
self.arg_parser.add_argument(
"--current",
metavar="PARTITION_IMAGE",
nargs="*",
type=lambda x: x.split("="),
help="The partitions and images to be flashed. The format is "
"<partition>=<image>. If PARTITION_IMAGE list is empty, "
"currently fetched " + ", ".join(common._DEFAULT_FLASH_IMAGES) +
" will be flashed.")
self.arg_parser.add_argument(
"--serial", default="", help="Serial number for device.")
self.arg_parser.add_argument(
"--build_dir",
help="Directory containing build images to be flashed.")
self.arg_parser.add_argument(
"--gsi", help="Path to generic system image")
self.arg_parser.add_argument("--vbmeta", help="Path to vbmeta image")
self.arg_parser.add_argument(
"--flasher_type",
default="fastboot",
help="Flasher type. Valid arguments are \"fastboot\", \"custom\", "
"and full module name followed by class name. The class must "
"inherit build_flasher.BuildFlasher, and implement "
"__init__(serial, flasher_path) and "
"Flash(device_images, additional_files, *flasher_args).")
self.arg_parser.add_argument(
"--flasher_path", default=None, help="Path to a flasher binary")
self.arg_parser.add_argument(
"flasher_args",
metavar="ARGUMENTS",
nargs="*",
help="The arguments passed to the flasher binary. If any argument "
"starts with \"-\", place all of them after \"--\" at end of "
"line.")
self.arg_parser.add_argument(
"--reboot_mode",
default="bootloader",
choices=("bootloader", "download"),
help="Reboot device to bootloader/download mode")
self.arg_parser.add_argument(
"--repackage",
default="tar.md5",
choices=("tar.md5"),
help="Repackage artifacts into given format before flashing.")
self.arg_parser.add_argument(
"--wait-for-boot",
default="true",
help="false to not wait for device booting.")
self.arg_parser.add_argument(
"--reboot", default="false", help="true to reboot the device(s).")
self.arg_parser.add_argument(
"--skip-vbmeta",
default=False,
type=bool,
help="true to skip flashing vbmeta.img if the device does not have "
"the vbmeta slot .")
# @Override
def Run(self, arg_line):
"""Flash GSI or build images to a device connected with ADB."""
args = self.arg_parser.ParseLine(arg_line)
# path
if (self.console.tools_info is not None
and args.flasher_path in self.console.tools_info):
flasher_path = self.console.tools_info[args.flasher_path]
elif args.flasher_path:
flasher_path = args.flasher_path
else:
flasher_path = ""
if os.path.exists(flasher_path):
flasher_mode = os.stat(flasher_path).st_mode
os.chmod(flasher_path,
flasher_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
# serial numbers
if args.serial:
flasher_serials = [args.serial]
elif self.console._serials:
flasher_serials = self.console._serials
else:
flasher_serials = [""]
# images
if args.image:
partition_image = {}
partition_image[args.image] = self.console.device_image_info[
args.image]
else:
if args.current:
partition_image = dict((partition,
self.console.device_image_info[image])
for partition, image in args.current)
else:
partition_image = dict(
(image.rsplit(".img", 1)[0],
self.console.device_image_info[image])
for image in common._DEFAULT_FLASH_IMAGES
if image in self.console.device_image_info)
# type
if args.flasher_type in ("fastboot", "custom"):
flasher_class = build_flasher.BuildFlasher
else:
class_path = args.flasher_type.rsplit(".", 1)
flasher_module = importlib.import_module(class_path[0])
flasher_class = getattr(flasher_module, class_path[1])
if not issubclass(flasher_class, build_flasher.BuildFlasher):
raise TypeError(
"%s is not a subclass of BuildFlasher." % class_path[1])
flashers = [flasher_class(s, flasher_path) for s in flasher_serials]
# Can be parallelized as long as that's proven reliable.
for flasher in flashers:
ret_flash = True
if args.flasher_type == "fastboot":
if args.image is not None:
ret_flash = flasher.FlashImage(partition_image, True
if args.reboot == "true"
else False)
elif args.current is not None:
ret_flash = flasher.Flash(partition_image,
args.skip_vbmeta)
else:
if args.gsi is None and args.build_dir is None:
self.arg_parser.error("Nothing requested: "
"specify --gsi or --build_dir")
return False
if args.build_dir is not None:
ret_flash = flasher.Flashall(args.build_dir)
if args.gsi is not None:
ret_flash = flasher.FlashGSI(
args.gsi,
args.vbmeta,
skip_vbmeta=args.skip_vbmeta)
elif args.flasher_type == "custom":
if flasher_path is not None:
if args.repackage is not None:
flasher.RepackageArtifacts(
self.console.device_image_info, args.repackage)
ret_flash = flasher.FlashUsingCustomBinary(
self.console.device_image_info, args.reboot_mode,
args.flasher_args, 300)
else:
self.arg_parser.error(
"Please specify the path to custom flash tool.")
return False
else:
ret_flash = flasher.Flash(partition_image,
self.console.tools_info,
*args.flasher_args)
if ret_flash == False:
return False
if args.wait_for_boot == "true":
for flasher in flashers:
ret_wait = flasher.WaitForDevice()
if ret_wait == False:
self.console.device_status[
flasher.device.serial] = common._DEVICE_STATUS_DICT[
"error"]
self.console.vti_endpoint_client.SetJobStatusFromLeasedTo(
"bootup-err")
return False
|