1#!/usr/bin/env python3 2# 3# Copyright 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 17import logging 18 19from acts.config_parser import ActsConfigError 20from acts.libs.ota.ota_runners import ota_runner 21from acts.libs.ota.ota_tools import ota_tool_factory 22from acts.libs.ota.ota_tools import adb_sideload_ota_tool 23 24_bound_devices = {} 25 26DEFAULT_OTA_TOOL = adb_sideload_ota_tool.AdbSideloadOtaTool.__name__ 27DEFAULT_OTA_COMMAND = 'adb' 28 29 30def create_all_from_configs(config, android_devices): 31 """Creates a new OtaTool for each given AndroidDevice. 32 33 After an OtaTool is assigned to a device, another OtaTool cannot be created 34 for that device. This will prevent OTA Update tests that accidentally flash 35 the same build onto a device more than once. 36 37 Args: 38 config: the ACTS config user_params. 39 android_devices: The devices to run an OTA Update on. 40 41 Returns: 42 A list of OtaRunners responsible for updating the given devices. The 43 indexes match the indexes of the corresponding AndroidDevice in 44 android_devices. 45 """ 46 return [create_from_configs(config, ad) for ad in android_devices] 47 48 49def create_from_configs(config, android_device): 50 """Creates a new OtaTool for the given AndroidDevice. 51 52 After an OtaTool is assigned to a device, another OtaTool cannot be created 53 for that device. This will prevent OTA Update tests that accidentally flash 54 the same build onto a device more than once. 55 56 Args: 57 config: the ACTS config user_params. 58 android_device: The device to run the OTA Update on. 59 60 Returns: 61 An OtaRunner responsible for updating the given device. 62 """ 63 # Default to adb sideload 64 try: 65 ota_tool_class_name = get_ota_value_from_config( 66 config, 'ota_tool', android_device) 67 except ActsConfigError: 68 ota_tool_class_name = DEFAULT_OTA_TOOL 69 70 if ota_tool_class_name not in config: 71 if ota_tool_class_name is not DEFAULT_OTA_TOOL: 72 raise ActsConfigError( 73 'If the ota_tool is overloaded, the path to the tool must be ' 74 'added to the ACTS config file under {"OtaToolName": ' 75 '"path/to/tool"} (in this case, {"%s": "path/to/tool"}.' % 76 ota_tool_class_name) 77 else: 78 command = DEFAULT_OTA_COMMAND 79 else: 80 command = config[ota_tool_class_name] 81 if type(command) is list: 82 # If file came as a list in the config. 83 if len(command) == 1: 84 command = command[0] 85 else: 86 raise ActsConfigError( 87 'Config value for "%s" must be either a string or a list ' 88 'of exactly one element' % ota_tool_class_name) 89 90 ota_package = get_ota_value_from_config(config, 'ota_package', 91 android_device) 92 ota_sl4a = get_ota_value_from_config(config, 'ota_sl4a', android_device) 93 if type(ota_sl4a) != type(ota_package): 94 raise ActsConfigError( 95 'The ota_package and ota_sl4a must either both be strings, or ' 96 'both be lists. Device with serial "%s" has mismatched types.' % 97 android_device.serial) 98 return create(ota_package, ota_sl4a, android_device, ota_tool_class_name, 99 command) 100 101 102def create(ota_package, 103 ota_sl4a, 104 android_device, 105 ota_tool_class_name=DEFAULT_OTA_TOOL, 106 command=DEFAULT_OTA_COMMAND, 107 use_cached_runners=True): 108 """ 109 Args: 110 ota_package: A string or list of strings corresponding to the 111 update.zip package location(s) for running an OTA update. 112 ota_sl4a: A string or list of strings corresponding to the 113 sl4a.apk package location(s) for running an OTA update. 114 ota_tool_class_name: The class name for the desired ota_tool 115 command: The command line tool name for the updater 116 android_device: The AndroidDevice to run the OTA Update on. 117 use_cached_runners: Whether or not to use runners cached by previous 118 create calls. 119 120 Returns: 121 An OtaRunner with the given properties from the arguments. 122 """ 123 ota_tool = ota_tool_factory.create(ota_tool_class_name, command) 124 return create_from_package(ota_package, ota_sl4a, android_device, ota_tool, 125 use_cached_runners) 126 127 128def create_from_package(ota_package, 129 ota_sl4a, 130 android_device, 131 ota_tool, 132 use_cached_runners=True): 133 """ 134 Args: 135 ota_package: A string or list of strings corresponding to the 136 update.zip package location(s) for running an OTA update. 137 ota_sl4a: A string or list of strings corresponding to the 138 sl4a.apk package location(s) for running an OTA update. 139 ota_tool: The OtaTool to be paired with the returned OtaRunner 140 android_device: The AndroidDevice to run the OTA Update on. 141 use_cached_runners: Whether or not to use runners cached by previous 142 create calls. 143 144 Returns: 145 An OtaRunner with the given properties from the arguments. 146 """ 147 if android_device in _bound_devices and use_cached_runners: 148 logging.warning('Android device %s has already been assigned an ' 149 'OtaRunner. Returning previously created runner.') 150 return _bound_devices[android_device] 151 152 if type(ota_package) != type(ota_sl4a): 153 raise TypeError( 154 'The ota_package and ota_sl4a must either both be strings, or ' 155 'both be lists. Device with serial "%s" has requested mismatched ' 156 'types.' % android_device.serial) 157 158 if type(ota_package) is str: 159 runner = ota_runner.SingleUseOtaRunner(ota_tool, android_device, 160 ota_package, ota_sl4a) 161 elif type(ota_package) is list: 162 runner = ota_runner.MultiUseOtaRunner(ota_tool, android_device, 163 ota_package, ota_sl4a) 164 else: 165 raise TypeError('The "ota_package" value in the acts config must be ' 166 'either a list or a string.') 167 168 _bound_devices[android_device] = runner 169 return runner 170 171 172def get_ota_value_from_config(config, key, android_device): 173 """Returns a key for the given AndroidDevice. 174 175 Args: 176 config: The ACTS config 177 key: The base key desired (ota_tool, ota_sl4a, or ota_package) 178 android_device: An AndroidDevice 179 180 Returns: The value at the specified key. 181 Throws: ActsConfigError if the value cannot be determined from the config. 182 """ 183 suffix = '' 184 if 'ota_map' in config: 185 if android_device.serial in config['ota_map']: 186 suffix = '_%s' % config['ota_map'][android_device.serial] 187 188 ota_package_key = '%s%s' % (key, suffix) 189 if ota_package_key not in config: 190 if suffix is not '': 191 raise ActsConfigError( 192 'Asked for an OTA Update without specifying a required value. ' 193 '"ota_map" has entry {"%s": "%s"}, but there is no ' 194 'corresponding entry {"%s":"/path/to/file"} found within the ' 195 'ACTS config.' % (android_device.serial, suffix[1:], 196 ota_package_key)) 197 else: 198 raise ActsConfigError( 199 'Asked for an OTA Update without specifying a required value. ' 200 '"ota_map" does not exist or have a key for serial "%s", and ' 201 'the default value entry "%s" cannot be found within the ACTS ' 202 'config.' % (android_device.serial, ota_package_key)) 203 204 return config[ota_package_key] 205