1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*c2e18aaaSAndroid Build Coastguard Worker# 3*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project 4*c2e18aaaSAndroid Build Coastguard Worker# 5*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*c2e18aaaSAndroid Build Coastguard Worker# 9*c2e18aaaSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*c2e18aaaSAndroid Build Coastguard Worker# 11*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License. 16*c2e18aaaSAndroid Build Coastguard Worker 17*c2e18aaaSAndroid Build Coastguard Worker"""common_util 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard WorkerThis module has a collection of functions that provide helper functions to 20*c2e18aaaSAndroid Build Coastguard Workerother modules. 21*c2e18aaaSAndroid Build Coastguard Worker""" 22*c2e18aaaSAndroid Build Coastguard Worker 23*c2e18aaaSAndroid Build Coastguard Workerimport fnmatch 24*c2e18aaaSAndroid Build Coastguard Workerimport inspect 25*c2e18aaaSAndroid Build Coastguard Workerimport json 26*c2e18aaaSAndroid Build Coastguard Workerimport logging 27*c2e18aaaSAndroid Build Coastguard Workerimport os 28*c2e18aaaSAndroid Build Coastguard Workerimport re 29*c2e18aaaSAndroid Build Coastguard Workerimport sys 30*c2e18aaaSAndroid Build Coastguard Workerimport time 31*c2e18aaaSAndroid Build Coastguard Workerimport xml.dom.minidom 32*c2e18aaaSAndroid Build Coastguard Workerimport zipfile 33*c2e18aaaSAndroid Build Coastguard Worker 34*c2e18aaaSAndroid Build Coastguard Workerfrom functools import partial 35*c2e18aaaSAndroid Build Coastguard Workerfrom functools import wraps 36*c2e18aaaSAndroid Build Coastguard Workerfrom xml.etree import ElementTree 37*c2e18aaaSAndroid Build Coastguard Worker 38*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import constant 39*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import errors 40*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_utils 41*c2e18aaaSAndroid Build Coastguard Workerfrom atest import constants 42*c2e18aaaSAndroid Build Coastguard Workerfrom atest import module_info 43*c2e18aaaSAndroid Build Coastguard Worker 44*c2e18aaaSAndroid Build Coastguard Worker 45*c2e18aaaSAndroid Build Coastguard WorkerCOLORED_INFO = partial(atest_utils.colorize, color=constants.MAGENTA) 46*c2e18aaaSAndroid Build Coastguard WorkerCOLORED_PASS = partial(atest_utils.colorize, color=constants.GREEN) 47*c2e18aaaSAndroid Build Coastguard WorkerCOLORED_FAIL = partial(atest_utils.colorize, color=constants.RED) 48*c2e18aaaSAndroid Build Coastguard WorkerFAKE_MODULE_ERROR = '{} is a fake module.' 49*c2e18aaaSAndroid Build Coastguard WorkerOUTSIDE_ROOT_ERROR = '{} is outside android root.' 50*c2e18aaaSAndroid Build Coastguard WorkerPATH_NOT_EXISTS_ERROR = 'The path {} doesn\'t exist.' 51*c2e18aaaSAndroid Build Coastguard WorkerNO_MODULE_DEFINED_ERROR = 'No modules defined at {}.' 52*c2e18aaaSAndroid Build Coastguard Worker_REBUILD_MODULE_INFO = '%s We should rebuild module-info.json file for it.' 53*c2e18aaaSAndroid Build Coastguard Worker_ENVSETUP_NOT_RUN = ('Please run "source build/envsetup.sh" and "lunch" before ' 54*c2e18aaaSAndroid Build Coastguard Worker 'running aidegen.') 55*c2e18aaaSAndroid Build Coastguard Worker_LOG_FORMAT = '%(asctime)s %(filename)s:%(lineno)s:%(levelname)s: %(message)s' 56*c2e18aaaSAndroid Build Coastguard Worker_DATE_FORMAT = '%Y-%m-%d %H:%M:%S' 57*c2e18aaaSAndroid Build Coastguard Worker_ARG_IS_NULL_ERROR = "{0}.{1}: argument '{2}' is null." 58*c2e18aaaSAndroid Build Coastguard Worker_ARG_TYPE_INCORRECT_ERROR = "{0}.{1}: argument '{2}': type is {3}, must be {4}." 59*c2e18aaaSAndroid Build Coastguard Worker_IDE_UNDEFINED = constant.IDE_DICT[constant.IDE_UNDEFINED] 60*c2e18aaaSAndroid Build Coastguard Worker_IDE_INTELLIJ = constant.IDE_DICT[constant.IDE_INTELLIJ] 61*c2e18aaaSAndroid Build Coastguard Worker_IDE_CLION = constant.IDE_DICT[constant.IDE_CLION] 62*c2e18aaaSAndroid Build Coastguard Worker_IDE_VSCODE = constant.IDE_DICT[constant.IDE_VSCODE] 63*c2e18aaaSAndroid Build Coastguard Worker 64*c2e18aaaSAndroid Build Coastguard Worker 65*c2e18aaaSAndroid Build Coastguard Workerdef time_logged(func=None, *, message='', maximum=1): 66*c2e18aaaSAndroid Build Coastguard Worker """Decorate a function to find out how much time it spends. 67*c2e18aaaSAndroid Build Coastguard Worker 68*c2e18aaaSAndroid Build Coastguard Worker Args: 69*c2e18aaaSAndroid Build Coastguard Worker func: a function is to be calculated its spending time. 70*c2e18aaaSAndroid Build Coastguard Worker message: the message the decorated function wants to show. 71*c2e18aaaSAndroid Build Coastguard Worker maximum: an integer, minutes. If time exceeds the maximum time show 72*c2e18aaaSAndroid Build Coastguard Worker message, otherwise doesn't. 73*c2e18aaaSAndroid Build Coastguard Worker 74*c2e18aaaSAndroid Build Coastguard Worker Returns: 75*c2e18aaaSAndroid Build Coastguard Worker The wrapper function. 76*c2e18aaaSAndroid Build Coastguard Worker """ 77*c2e18aaaSAndroid Build Coastguard Worker if func is None: 78*c2e18aaaSAndroid Build Coastguard Worker return partial(time_logged, message=message, maximum=maximum) 79*c2e18aaaSAndroid Build Coastguard Worker 80*c2e18aaaSAndroid Build Coastguard Worker @wraps(func) 81*c2e18aaaSAndroid Build Coastguard Worker def wrapper(*args, **kwargs): 82*c2e18aaaSAndroid Build Coastguard Worker """A wrapper function.""" 83*c2e18aaaSAndroid Build Coastguard Worker 84*c2e18aaaSAndroid Build Coastguard Worker start = time.time() 85*c2e18aaaSAndroid Build Coastguard Worker try: 86*c2e18aaaSAndroid Build Coastguard Worker return func(*args, **kwargs) 87*c2e18aaaSAndroid Build Coastguard Worker finally: 88*c2e18aaaSAndroid Build Coastguard Worker timestamp = time.time() - start 89*c2e18aaaSAndroid Build Coastguard Worker logging.debug('{}.{} takes: {:.2f}s'.format( 90*c2e18aaaSAndroid Build Coastguard Worker func.__module__, func.__name__, timestamp)) 91*c2e18aaaSAndroid Build Coastguard Worker if message and timestamp > maximum * 60: 92*c2e18aaaSAndroid Build Coastguard Worker print(message) 93*c2e18aaaSAndroid Build Coastguard Worker 94*c2e18aaaSAndroid Build Coastguard Worker return wrapper 95*c2e18aaaSAndroid Build Coastguard Worker 96*c2e18aaaSAndroid Build Coastguard Worker 97*c2e18aaaSAndroid Build Coastguard Workerdef get_related_paths(atest_module_info, target=None): 98*c2e18aaaSAndroid Build Coastguard Worker """Get the relative and absolute paths of target from module-info. 99*c2e18aaaSAndroid Build Coastguard Worker 100*c2e18aaaSAndroid Build Coastguard Worker Args: 101*c2e18aaaSAndroid Build Coastguard Worker atest_module_info: A ModuleInfo instance. 102*c2e18aaaSAndroid Build Coastguard Worker target: A string user input from command line. It could be several cases 103*c2e18aaaSAndroid Build Coastguard Worker such as: 104*c2e18aaaSAndroid Build Coastguard Worker 1. Module name, e.g. Settings 105*c2e18aaaSAndroid Build Coastguard Worker 2. Module path, e.g. packages/apps/Settings 106*c2e18aaaSAndroid Build Coastguard Worker 3. Relative path, e.g. ../../packages/apps/Settings 107*c2e18aaaSAndroid Build Coastguard Worker 4. Current directory, e.g. '.' or no argument 108*c2e18aaaSAndroid Build Coastguard Worker 5. An empty string, which added by AIDEGen, used for generating 109*c2e18aaaSAndroid Build Coastguard Worker the iml files for the whole Android repo tree. 110*c2e18aaaSAndroid Build Coastguard Worker e.g. 111*c2e18aaaSAndroid Build Coastguard Worker 1. ~/aosp$ aidegen 112*c2e18aaaSAndroid Build Coastguard Worker 2. ~/aosp/frameworks/base$ aidegen -a 113*c2e18aaaSAndroid Build Coastguard Worker 6. An absolute path, e.g. /usr/local/home/test/aosp 114*c2e18aaaSAndroid Build Coastguard Worker 115*c2e18aaaSAndroid Build Coastguard Worker Return: 116*c2e18aaaSAndroid Build Coastguard Worker rel_path: The relative path of a module, return None if no matching 117*c2e18aaaSAndroid Build Coastguard Worker module found. 118*c2e18aaaSAndroid Build Coastguard Worker abs_path: The absolute path of a module, return None if no matching 119*c2e18aaaSAndroid Build Coastguard Worker module found. 120*c2e18aaaSAndroid Build Coastguard Worker """ 121*c2e18aaaSAndroid Build Coastguard Worker rel_path = None 122*c2e18aaaSAndroid Build Coastguard Worker abs_path = None 123*c2e18aaaSAndroid Build Coastguard Worker # take the command 'aidegen .' as 'aidegen'. 124*c2e18aaaSAndroid Build Coastguard Worker if target == '.': 125*c2e18aaaSAndroid Build Coastguard Worker target = None 126*c2e18aaaSAndroid Build Coastguard Worker if target: 127*c2e18aaaSAndroid Build Coastguard Worker # For the case of whole Android repo tree. 128*c2e18aaaSAndroid Build Coastguard Worker if target == constant.WHOLE_ANDROID_TREE_TARGET: 129*c2e18aaaSAndroid Build Coastguard Worker rel_path = '' 130*c2e18aaaSAndroid Build Coastguard Worker abs_path = get_android_root_dir() 131*c2e18aaaSAndroid Build Coastguard Worker # User inputs an absolute path. 132*c2e18aaaSAndroid Build Coastguard Worker elif os.path.isabs(target): 133*c2e18aaaSAndroid Build Coastguard Worker abs_path = target 134*c2e18aaaSAndroid Build Coastguard Worker rel_path = os.path.relpath(abs_path, get_android_root_dir()) 135*c2e18aaaSAndroid Build Coastguard Worker # User inputs a module name. 136*c2e18aaaSAndroid Build Coastguard Worker elif atest_module_info.is_module(target): 137*c2e18aaaSAndroid Build Coastguard Worker paths = atest_module_info.get_paths(target) 138*c2e18aaaSAndroid Build Coastguard Worker if paths: 139*c2e18aaaSAndroid Build Coastguard Worker rel_path = paths[0].strip(os.sep) 140*c2e18aaaSAndroid Build Coastguard Worker abs_path = os.path.join(get_android_root_dir(), rel_path) 141*c2e18aaaSAndroid Build Coastguard Worker # User inputs a module path or a relative path of android root folder. 142*c2e18aaaSAndroid Build Coastguard Worker elif (atest_module_info.get_module_names(target) 143*c2e18aaaSAndroid Build Coastguard Worker or os.path.isdir(os.path.join(get_android_root_dir(), target))): 144*c2e18aaaSAndroid Build Coastguard Worker rel_path = target.strip(os.sep) 145*c2e18aaaSAndroid Build Coastguard Worker abs_path = os.path.join(get_android_root_dir(), rel_path) 146*c2e18aaaSAndroid Build Coastguard Worker # User inputs a relative path of current directory. 147*c2e18aaaSAndroid Build Coastguard Worker else: 148*c2e18aaaSAndroid Build Coastguard Worker abs_path = os.path.abspath(os.path.join(os.getcwd(), target)) 149*c2e18aaaSAndroid Build Coastguard Worker rel_path = os.path.relpath(abs_path, get_android_root_dir()) 150*c2e18aaaSAndroid Build Coastguard Worker else: 151*c2e18aaaSAndroid Build Coastguard Worker # User doesn't input. 152*c2e18aaaSAndroid Build Coastguard Worker abs_path = os.getcwd() 153*c2e18aaaSAndroid Build Coastguard Worker if is_android_root(abs_path): 154*c2e18aaaSAndroid Build Coastguard Worker rel_path = '' 155*c2e18aaaSAndroid Build Coastguard Worker else: 156*c2e18aaaSAndroid Build Coastguard Worker rel_path = os.path.relpath(abs_path, get_android_root_dir()) 157*c2e18aaaSAndroid Build Coastguard Worker return rel_path, abs_path 158*c2e18aaaSAndroid Build Coastguard Worker 159*c2e18aaaSAndroid Build Coastguard Worker 160*c2e18aaaSAndroid Build Coastguard Workerdef is_target_android_root(atest_module_info, targets): 161*c2e18aaaSAndroid Build Coastguard Worker """Check if any target is the Android root path. 162*c2e18aaaSAndroid Build Coastguard Worker 163*c2e18aaaSAndroid Build Coastguard Worker Args: 164*c2e18aaaSAndroid Build Coastguard Worker atest_module_info: A ModuleInfo instance contains data of 165*c2e18aaaSAndroid Build Coastguard Worker module-info.json. 166*c2e18aaaSAndroid Build Coastguard Worker targets: A list of target modules or project paths from user input. 167*c2e18aaaSAndroid Build Coastguard Worker 168*c2e18aaaSAndroid Build Coastguard Worker Returns: 169*c2e18aaaSAndroid Build Coastguard Worker True if target is Android root, otherwise False. 170*c2e18aaaSAndroid Build Coastguard Worker """ 171*c2e18aaaSAndroid Build Coastguard Worker for target in targets: 172*c2e18aaaSAndroid Build Coastguard Worker _, abs_path = get_related_paths(atest_module_info, target) 173*c2e18aaaSAndroid Build Coastguard Worker if is_android_root(abs_path): 174*c2e18aaaSAndroid Build Coastguard Worker return True 175*c2e18aaaSAndroid Build Coastguard Worker return False 176*c2e18aaaSAndroid Build Coastguard Worker 177*c2e18aaaSAndroid Build Coastguard Worker 178*c2e18aaaSAndroid Build Coastguard Workerdef is_android_root(abs_path): 179*c2e18aaaSAndroid Build Coastguard Worker """Check if an absolute path is the Android root path. 180*c2e18aaaSAndroid Build Coastguard Worker 181*c2e18aaaSAndroid Build Coastguard Worker Args: 182*c2e18aaaSAndroid Build Coastguard Worker abs_path: The absolute path of a module. 183*c2e18aaaSAndroid Build Coastguard Worker 184*c2e18aaaSAndroid Build Coastguard Worker Returns: 185*c2e18aaaSAndroid Build Coastguard Worker True if abs_path is Android root, otherwise False. 186*c2e18aaaSAndroid Build Coastguard Worker """ 187*c2e18aaaSAndroid Build Coastguard Worker return abs_path == get_android_root_dir() 188*c2e18aaaSAndroid Build Coastguard Worker 189*c2e18aaaSAndroid Build Coastguard Worker 190*c2e18aaaSAndroid Build Coastguard Workerdef has_build_target(atest_module_info, rel_path): 191*c2e18aaaSAndroid Build Coastguard Worker """Determine if a relative path contains buildable module. 192*c2e18aaaSAndroid Build Coastguard Worker 193*c2e18aaaSAndroid Build Coastguard Worker Args: 194*c2e18aaaSAndroid Build Coastguard Worker atest_module_info: A ModuleInfo instance contains data of 195*c2e18aaaSAndroid Build Coastguard Worker module-info.json. 196*c2e18aaaSAndroid Build Coastguard Worker rel_path: The module path relative to android root. 197*c2e18aaaSAndroid Build Coastguard Worker 198*c2e18aaaSAndroid Build Coastguard Worker Returns: 199*c2e18aaaSAndroid Build Coastguard Worker True if the relative path contains a build target, otherwise false. 200*c2e18aaaSAndroid Build Coastguard Worker """ 201*c2e18aaaSAndroid Build Coastguard Worker return any( 202*c2e18aaaSAndroid Build Coastguard Worker is_source_under_relative_path(mod_path, rel_path) 203*c2e18aaaSAndroid Build Coastguard Worker for mod_path in atest_module_info.path_to_module_info) 204*c2e18aaaSAndroid Build Coastguard Worker 205*c2e18aaaSAndroid Build Coastguard Worker 206*c2e18aaaSAndroid Build Coastguard Workerdef _check_modules(atest_module_info, targets, raise_on_lost_module=True): 207*c2e18aaaSAndroid Build Coastguard Worker """Check if all targets are valid build targets. 208*c2e18aaaSAndroid Build Coastguard Worker 209*c2e18aaaSAndroid Build Coastguard Worker Args: 210*c2e18aaaSAndroid Build Coastguard Worker atest_module_info: A ModuleInfo instance contains data of 211*c2e18aaaSAndroid Build Coastguard Worker module-info.json. 212*c2e18aaaSAndroid Build Coastguard Worker targets: A list of target modules or project paths from user input. 213*c2e18aaaSAndroid Build Coastguard Worker When locating the path of the target, given a matched module 214*c2e18aaaSAndroid Build Coastguard Worker name has priority over path. Below is the priority of locating a 215*c2e18aaaSAndroid Build Coastguard Worker target: 216*c2e18aaaSAndroid Build Coastguard Worker 1. Module name, e.g. Settings 217*c2e18aaaSAndroid Build Coastguard Worker 2. Module path, e.g. packages/apps/Settings 218*c2e18aaaSAndroid Build Coastguard Worker 3. Relative path, e.g. ../../packages/apps/Settings 219*c2e18aaaSAndroid Build Coastguard Worker 4. Current directory, e.g. '.' or no argument 220*c2e18aaaSAndroid Build Coastguard Worker raise_on_lost_module: A boolean, pass to _check_module to determine if 221*c2e18aaaSAndroid Build Coastguard Worker ProjectPathNotExistError or NoModuleDefinedInModuleInfoError 222*c2e18aaaSAndroid Build Coastguard Worker should be raised. 223*c2e18aaaSAndroid Build Coastguard Worker 224*c2e18aaaSAndroid Build Coastguard Worker Returns: 225*c2e18aaaSAndroid Build Coastguard Worker True if any _check_module return flip the True/False. 226*c2e18aaaSAndroid Build Coastguard Worker """ 227*c2e18aaaSAndroid Build Coastguard Worker for target in targets: 228*c2e18aaaSAndroid Build Coastguard Worker if not check_module(atest_module_info, target, raise_on_lost_module): 229*c2e18aaaSAndroid Build Coastguard Worker return False 230*c2e18aaaSAndroid Build Coastguard Worker return True 231*c2e18aaaSAndroid Build Coastguard Worker 232*c2e18aaaSAndroid Build Coastguard Worker 233*c2e18aaaSAndroid Build Coastguard Workerdef check_module(atest_module_info, target, raise_on_lost_module=True): 234*c2e18aaaSAndroid Build Coastguard Worker """Check if a target is valid or it's a path containing build target. 235*c2e18aaaSAndroid Build Coastguard Worker 236*c2e18aaaSAndroid Build Coastguard Worker Args: 237*c2e18aaaSAndroid Build Coastguard Worker atest_module_info: A ModuleInfo instance contains the data of 238*c2e18aaaSAndroid Build Coastguard Worker module-info.json. 239*c2e18aaaSAndroid Build Coastguard Worker target: A target module or project path from user input. 240*c2e18aaaSAndroid Build Coastguard Worker When locating the path of the target, given a matched module 241*c2e18aaaSAndroid Build Coastguard Worker name has priority over path. Below is the priority of locating a 242*c2e18aaaSAndroid Build Coastguard Worker target: 243*c2e18aaaSAndroid Build Coastguard Worker 1. Module name, e.g. Settings 244*c2e18aaaSAndroid Build Coastguard Worker 2. Module path, e.g. packages/apps/Settings 245*c2e18aaaSAndroid Build Coastguard Worker 3. Relative path, e.g. ../../packages/apps/Settings 246*c2e18aaaSAndroid Build Coastguard Worker 4. Current directory, e.g. . or no argument 247*c2e18aaaSAndroid Build Coastguard Worker 5. An absolute path, e.g. /usr/local/home/test/aosp 248*c2e18aaaSAndroid Build Coastguard Worker raise_on_lost_module: A boolean, handles if ProjectPathNotExistError or 249*c2e18aaaSAndroid Build Coastguard Worker NoModuleDefinedInModuleInfoError should be raised. 250*c2e18aaaSAndroid Build Coastguard Worker 251*c2e18aaaSAndroid Build Coastguard Worker Returns: 252*c2e18aaaSAndroid Build Coastguard Worker 1. If there is no error _check_module always return True. 253*c2e18aaaSAndroid Build Coastguard Worker 2. If there is an error, 254*c2e18aaaSAndroid Build Coastguard Worker a. When raise_on_lost_module is False, _check_module will raise the 255*c2e18aaaSAndroid Build Coastguard Worker error. 256*c2e18aaaSAndroid Build Coastguard Worker b. When raise_on_lost_module is True, _check_module will return 257*c2e18aaaSAndroid Build Coastguard Worker False if module's error is ProjectPathNotExistError or 258*c2e18aaaSAndroid Build Coastguard Worker NoModuleDefinedInModuleInfoError else raise the error. 259*c2e18aaaSAndroid Build Coastguard Worker 260*c2e18aaaSAndroid Build Coastguard Worker Raises: 261*c2e18aaaSAndroid Build Coastguard Worker Raise ProjectPathNotExistError and NoModuleDefinedInModuleInfoError only 262*c2e18aaaSAndroid Build Coastguard Worker when raise_on_lost_module is True, others don't subject to the limit. 263*c2e18aaaSAndroid Build Coastguard Worker The rules for raising exceptions: 264*c2e18aaaSAndroid Build Coastguard Worker 1. Absolute path of a module is None -> FakeModuleError 265*c2e18aaaSAndroid Build Coastguard Worker 2. Module doesn't exist in repo root -> ProjectOutsideAndroidRootError 266*c2e18aaaSAndroid Build Coastguard Worker 3. The given absolute path is not a dir -> ProjectPathNotExistError 267*c2e18aaaSAndroid Build Coastguard Worker 4. If the given abs path doesn't contain any target and not repo root 268*c2e18aaaSAndroid Build Coastguard Worker -> NoModuleDefinedInModuleInfoError 269*c2e18aaaSAndroid Build Coastguard Worker """ 270*c2e18aaaSAndroid Build Coastguard Worker rel_path, abs_path = get_related_paths(atest_module_info, target) 271*c2e18aaaSAndroid Build Coastguard Worker if not abs_path: 272*c2e18aaaSAndroid Build Coastguard Worker err = FAKE_MODULE_ERROR.format(target) 273*c2e18aaaSAndroid Build Coastguard Worker logging.error(err) 274*c2e18aaaSAndroid Build Coastguard Worker raise errors.FakeModuleError(err) 275*c2e18aaaSAndroid Build Coastguard Worker if not is_source_under_relative_path(abs_path, get_android_root_dir()): 276*c2e18aaaSAndroid Build Coastguard Worker err = OUTSIDE_ROOT_ERROR.format(abs_path) 277*c2e18aaaSAndroid Build Coastguard Worker logging.error(err) 278*c2e18aaaSAndroid Build Coastguard Worker raise errors.ProjectOutsideAndroidRootError(err) 279*c2e18aaaSAndroid Build Coastguard Worker if not os.path.isdir(abs_path): 280*c2e18aaaSAndroid Build Coastguard Worker err = PATH_NOT_EXISTS_ERROR.format(rel_path) 281*c2e18aaaSAndroid Build Coastguard Worker if raise_on_lost_module: 282*c2e18aaaSAndroid Build Coastguard Worker logging.error(err) 283*c2e18aaaSAndroid Build Coastguard Worker raise errors.ProjectPathNotExistError(err) 284*c2e18aaaSAndroid Build Coastguard Worker logging.debug(_REBUILD_MODULE_INFO, err) 285*c2e18aaaSAndroid Build Coastguard Worker return False 286*c2e18aaaSAndroid Build Coastguard Worker if (not has_build_target(atest_module_info, rel_path) 287*c2e18aaaSAndroid Build Coastguard Worker and not is_android_root(abs_path)): 288*c2e18aaaSAndroid Build Coastguard Worker err = NO_MODULE_DEFINED_ERROR.format(rel_path) 289*c2e18aaaSAndroid Build Coastguard Worker if raise_on_lost_module: 290*c2e18aaaSAndroid Build Coastguard Worker logging.error(err) 291*c2e18aaaSAndroid Build Coastguard Worker raise errors.NoModuleDefinedInModuleInfoError(err) 292*c2e18aaaSAndroid Build Coastguard Worker logging.debug(_REBUILD_MODULE_INFO, err) 293*c2e18aaaSAndroid Build Coastguard Worker return False 294*c2e18aaaSAndroid Build Coastguard Worker return True 295*c2e18aaaSAndroid Build Coastguard Worker 296*c2e18aaaSAndroid Build Coastguard Worker 297*c2e18aaaSAndroid Build Coastguard Workerdef get_abs_path(rel_path): 298*c2e18aaaSAndroid Build Coastguard Worker """Get absolute path from a relative path. 299*c2e18aaaSAndroid Build Coastguard Worker 300*c2e18aaaSAndroid Build Coastguard Worker Args: 301*c2e18aaaSAndroid Build Coastguard Worker rel_path: A string, a relative path to get_android_root_dir(). 302*c2e18aaaSAndroid Build Coastguard Worker 303*c2e18aaaSAndroid Build Coastguard Worker Returns: 304*c2e18aaaSAndroid Build Coastguard Worker abs_path: A string, an absolute path starts with 305*c2e18aaaSAndroid Build Coastguard Worker get_android_root_dir(). 306*c2e18aaaSAndroid Build Coastguard Worker """ 307*c2e18aaaSAndroid Build Coastguard Worker if not rel_path: 308*c2e18aaaSAndroid Build Coastguard Worker return get_android_root_dir() 309*c2e18aaaSAndroid Build Coastguard Worker if is_source_under_relative_path(rel_path, get_android_root_dir()): 310*c2e18aaaSAndroid Build Coastguard Worker return rel_path 311*c2e18aaaSAndroid Build Coastguard Worker return os.path.join(get_android_root_dir(), rel_path) 312*c2e18aaaSAndroid Build Coastguard Worker 313*c2e18aaaSAndroid Build Coastguard Worker 314*c2e18aaaSAndroid Build Coastguard Workerdef is_target(src_file, src_file_extensions): 315*c2e18aaaSAndroid Build Coastguard Worker """Check if src_file is a type of src_file_extensions. 316*c2e18aaaSAndroid Build Coastguard Worker 317*c2e18aaaSAndroid Build Coastguard Worker Args: 318*c2e18aaaSAndroid Build Coastguard Worker src_file: A string of the file path to be checked. 319*c2e18aaaSAndroid Build Coastguard Worker src_file_extensions: A list of file types to be checked 320*c2e18aaaSAndroid Build Coastguard Worker 321*c2e18aaaSAndroid Build Coastguard Worker Returns: 322*c2e18aaaSAndroid Build Coastguard Worker True if src_file is one of the types of src_file_extensions, otherwise 323*c2e18aaaSAndroid Build Coastguard Worker False. 324*c2e18aaaSAndroid Build Coastguard Worker """ 325*c2e18aaaSAndroid Build Coastguard Worker return any(src_file.endswith(x) for x in src_file_extensions) 326*c2e18aaaSAndroid Build Coastguard Worker 327*c2e18aaaSAndroid Build Coastguard Worker 328*c2e18aaaSAndroid Build Coastguard Workerdef get_atest_module_info(targets=None): 329*c2e18aaaSAndroid Build Coastguard Worker """Get the right version of atest ModuleInfo instance. 330*c2e18aaaSAndroid Build Coastguard Worker 331*c2e18aaaSAndroid Build Coastguard Worker The rules: 332*c2e18aaaSAndroid Build Coastguard Worker 1. If targets is None: 333*c2e18aaaSAndroid Build Coastguard Worker We just want to get an atest ModuleInfo instance. 334*c2e18aaaSAndroid Build Coastguard Worker 2. If targets isn't None: 335*c2e18aaaSAndroid Build Coastguard Worker Check if the targets don't exist in ModuleInfo, we'll regain a new 336*c2e18aaaSAndroid Build Coastguard Worker atest ModuleInfo instance by setting force_build=True and call 337*c2e18aaaSAndroid Build Coastguard Worker _check_modules again. If targets still don't exist, raise exceptions. 338*c2e18aaaSAndroid Build Coastguard Worker 339*c2e18aaaSAndroid Build Coastguard Worker Args: 340*c2e18aaaSAndroid Build Coastguard Worker targets: A list of targets to be built. 341*c2e18aaaSAndroid Build Coastguard Worker 342*c2e18aaaSAndroid Build Coastguard Worker Returns: 343*c2e18aaaSAndroid Build Coastguard Worker An atest ModuleInfo instance. 344*c2e18aaaSAndroid Build Coastguard Worker """ 345*c2e18aaaSAndroid Build Coastguard Worker amodule_info = module_info.ModuleInfo() 346*c2e18aaaSAndroid Build Coastguard Worker if targets and not _check_modules( 347*c2e18aaaSAndroid Build Coastguard Worker amodule_info, targets, raise_on_lost_module=False): 348*c2e18aaaSAndroid Build Coastguard Worker amodule_info = module_info.ModuleInfo(force_build=True) 349*c2e18aaaSAndroid Build Coastguard Worker _check_modules(amodule_info, targets) 350*c2e18aaaSAndroid Build Coastguard Worker return amodule_info 351*c2e18aaaSAndroid Build Coastguard Worker 352*c2e18aaaSAndroid Build Coastguard Worker 353*c2e18aaaSAndroid Build Coastguard Workerdef get_blueprint_json_path(file_name): 354*c2e18aaaSAndroid Build Coastguard Worker """Assemble the path of blueprint json file. 355*c2e18aaaSAndroid Build Coastguard Worker 356*c2e18aaaSAndroid Build Coastguard Worker Args: 357*c2e18aaaSAndroid Build Coastguard Worker file_name: A string of blueprint json file name. 358*c2e18aaaSAndroid Build Coastguard Worker 359*c2e18aaaSAndroid Build Coastguard Worker Returns: 360*c2e18aaaSAndroid Build Coastguard Worker The path of json file. 361*c2e18aaaSAndroid Build Coastguard Worker """ 362*c2e18aaaSAndroid Build Coastguard Worker return os.path.join(get_soong_out_path(), file_name) 363*c2e18aaaSAndroid Build Coastguard Worker 364*c2e18aaaSAndroid Build Coastguard Worker 365*c2e18aaaSAndroid Build Coastguard Workerdef back_to_cwd(func): 366*c2e18aaaSAndroid Build Coastguard Worker """Decorate a function change directory back to its original one. 367*c2e18aaaSAndroid Build Coastguard Worker 368*c2e18aaaSAndroid Build Coastguard Worker Args: 369*c2e18aaaSAndroid Build Coastguard Worker func: a function is to be changed back to its original directory. 370*c2e18aaaSAndroid Build Coastguard Worker 371*c2e18aaaSAndroid Build Coastguard Worker Returns: 372*c2e18aaaSAndroid Build Coastguard Worker The wrapper function. 373*c2e18aaaSAndroid Build Coastguard Worker """ 374*c2e18aaaSAndroid Build Coastguard Worker 375*c2e18aaaSAndroid Build Coastguard Worker @wraps(func) 376*c2e18aaaSAndroid Build Coastguard Worker def wrapper(*args, **kwargs): 377*c2e18aaaSAndroid Build Coastguard Worker """A wrapper function.""" 378*c2e18aaaSAndroid Build Coastguard Worker cwd = os.getcwd() 379*c2e18aaaSAndroid Build Coastguard Worker try: 380*c2e18aaaSAndroid Build Coastguard Worker return func(*args, **kwargs) 381*c2e18aaaSAndroid Build Coastguard Worker finally: 382*c2e18aaaSAndroid Build Coastguard Worker os.chdir(cwd) 383*c2e18aaaSAndroid Build Coastguard Worker 384*c2e18aaaSAndroid Build Coastguard Worker return wrapper 385*c2e18aaaSAndroid Build Coastguard Worker 386*c2e18aaaSAndroid Build Coastguard Worker 387*c2e18aaaSAndroid Build Coastguard Workerdef get_android_out_dir(): 388*c2e18aaaSAndroid Build Coastguard Worker """Get out directory in different conditions. 389*c2e18aaaSAndroid Build Coastguard Worker 390*c2e18aaaSAndroid Build Coastguard Worker Returns: 391*c2e18aaaSAndroid Build Coastguard Worker Android out directory path. 392*c2e18aaaSAndroid Build Coastguard Worker """ 393*c2e18aaaSAndroid Build Coastguard Worker android_root_path = get_android_root_dir() 394*c2e18aaaSAndroid Build Coastguard Worker android_out_dir = os.getenv(constants.ANDROID_OUT_DIR) 395*c2e18aaaSAndroid Build Coastguard Worker out_dir_common_base = os.getenv(constant.OUT_DIR_COMMON_BASE_ENV_VAR) 396*c2e18aaaSAndroid Build Coastguard Worker android_out_dir_common_base = (os.path.join( 397*c2e18aaaSAndroid Build Coastguard Worker out_dir_common_base, os.path.basename(android_root_path)) 398*c2e18aaaSAndroid Build Coastguard Worker if out_dir_common_base else None) 399*c2e18aaaSAndroid Build Coastguard Worker return (android_out_dir or android_out_dir_common_base 400*c2e18aaaSAndroid Build Coastguard Worker or constant.ANDROID_DEFAULT_OUT) 401*c2e18aaaSAndroid Build Coastguard Worker 402*c2e18aaaSAndroid Build Coastguard Worker 403*c2e18aaaSAndroid Build Coastguard Workerdef get_android_root_dir(): 404*c2e18aaaSAndroid Build Coastguard Worker """Get Android root directory. 405*c2e18aaaSAndroid Build Coastguard Worker 406*c2e18aaaSAndroid Build Coastguard Worker If the path doesn't exist show message to ask users to run envsetup.sh and 407*c2e18aaaSAndroid Build Coastguard Worker lunch first. 408*c2e18aaaSAndroid Build Coastguard Worker 409*c2e18aaaSAndroid Build Coastguard Worker Returns: 410*c2e18aaaSAndroid Build Coastguard Worker Android root directory path. 411*c2e18aaaSAndroid Build Coastguard Worker """ 412*c2e18aaaSAndroid Build Coastguard Worker android_root_path = os.environ.get(constants.ANDROID_BUILD_TOP) 413*c2e18aaaSAndroid Build Coastguard Worker if not android_root_path: 414*c2e18aaaSAndroid Build Coastguard Worker _show_env_setup_msg_and_exit() 415*c2e18aaaSAndroid Build Coastguard Worker return android_root_path 416*c2e18aaaSAndroid Build Coastguard Worker 417*c2e18aaaSAndroid Build Coastguard Worker 418*c2e18aaaSAndroid Build Coastguard Workerdef get_aidegen_root_dir(): 419*c2e18aaaSAndroid Build Coastguard Worker """Get AIDEGen root directory. 420*c2e18aaaSAndroid Build Coastguard Worker 421*c2e18aaaSAndroid Build Coastguard Worker Returns: 422*c2e18aaaSAndroid Build Coastguard Worker AIDEGen root directory path. 423*c2e18aaaSAndroid Build Coastguard Worker """ 424*c2e18aaaSAndroid Build Coastguard Worker return os.path.join(get_android_root_dir(), constant.AIDEGEN_ROOT_PATH) 425*c2e18aaaSAndroid Build Coastguard Worker 426*c2e18aaaSAndroid Build Coastguard Worker 427*c2e18aaaSAndroid Build Coastguard Workerdef _show_env_setup_msg_and_exit(): 428*c2e18aaaSAndroid Build Coastguard Worker """Show message if users didn't run envsetup.sh and lunch.""" 429*c2e18aaaSAndroid Build Coastguard Worker print(_ENVSETUP_NOT_RUN) 430*c2e18aaaSAndroid Build Coastguard Worker sys.exit(0) 431*c2e18aaaSAndroid Build Coastguard Worker 432*c2e18aaaSAndroid Build Coastguard Worker 433*c2e18aaaSAndroid Build Coastguard Workerdef get_soong_out_path(): 434*c2e18aaaSAndroid Build Coastguard Worker """Assemble out directory's soong path. 435*c2e18aaaSAndroid Build Coastguard Worker 436*c2e18aaaSAndroid Build Coastguard Worker Returns: 437*c2e18aaaSAndroid Build Coastguard Worker Out directory's soong path. 438*c2e18aaaSAndroid Build Coastguard Worker """ 439*c2e18aaaSAndroid Build Coastguard Worker return os.path.join(get_android_root_dir(), get_android_out_dir(), 'soong') 440*c2e18aaaSAndroid Build Coastguard Worker 441*c2e18aaaSAndroid Build Coastguard Worker 442*c2e18aaaSAndroid Build Coastguard Workerdef configure_logging(verbose): 443*c2e18aaaSAndroid Build Coastguard Worker """Configure the logger. 444*c2e18aaaSAndroid Build Coastguard Worker 445*c2e18aaaSAndroid Build Coastguard Worker Args: 446*c2e18aaaSAndroid Build Coastguard Worker verbose: A boolean. If true, display DEBUG level logs. 447*c2e18aaaSAndroid Build Coastguard Worker """ 448*c2e18aaaSAndroid Build Coastguard Worker log_format = _LOG_FORMAT 449*c2e18aaaSAndroid Build Coastguard Worker datefmt = _DATE_FORMAT 450*c2e18aaaSAndroid Build Coastguard Worker level = logging.DEBUG if verbose else logging.INFO 451*c2e18aaaSAndroid Build Coastguard Worker # Clear all handlers to prevent setting level not working. 452*c2e18aaaSAndroid Build Coastguard Worker logging.getLogger().handlers = [] 453*c2e18aaaSAndroid Build Coastguard Worker logging.basicConfig(level=level, format=log_format, datefmt=datefmt) 454*c2e18aaaSAndroid Build Coastguard Worker 455*c2e18aaaSAndroid Build Coastguard Worker 456*c2e18aaaSAndroid Build Coastguard Workerdef exist_android_bp(abs_path): 457*c2e18aaaSAndroid Build Coastguard Worker """Check if the Android.bp exists under specific folder. 458*c2e18aaaSAndroid Build Coastguard Worker 459*c2e18aaaSAndroid Build Coastguard Worker Args: 460*c2e18aaaSAndroid Build Coastguard Worker abs_path: An absolute path string. 461*c2e18aaaSAndroid Build Coastguard Worker 462*c2e18aaaSAndroid Build Coastguard Worker Returns: A boolean, true if the Android.bp exists under the folder, 463*c2e18aaaSAndroid Build Coastguard Worker otherwise false. 464*c2e18aaaSAndroid Build Coastguard Worker """ 465*c2e18aaaSAndroid Build Coastguard Worker return os.path.isfile(os.path.join(abs_path, constant.ANDROID_BP)) 466*c2e18aaaSAndroid Build Coastguard Worker 467*c2e18aaaSAndroid Build Coastguard Worker 468*c2e18aaaSAndroid Build Coastguard Workerdef exist_android_mk(abs_path): 469*c2e18aaaSAndroid Build Coastguard Worker """Check if the Android.mk exists under specific folder. 470*c2e18aaaSAndroid Build Coastguard Worker 471*c2e18aaaSAndroid Build Coastguard Worker Args: 472*c2e18aaaSAndroid Build Coastguard Worker abs_path: An absolute path string. 473*c2e18aaaSAndroid Build Coastguard Worker 474*c2e18aaaSAndroid Build Coastguard Worker Returns: A boolean, true if the Android.mk exists under the folder, 475*c2e18aaaSAndroid Build Coastguard Worker otherwise false. 476*c2e18aaaSAndroid Build Coastguard Worker """ 477*c2e18aaaSAndroid Build Coastguard Worker return os.path.isfile(os.path.join(abs_path, constant.ANDROID_MK)) 478*c2e18aaaSAndroid Build Coastguard Worker 479*c2e18aaaSAndroid Build Coastguard Worker 480*c2e18aaaSAndroid Build Coastguard Workerdef is_source_under_relative_path(source, relative_path): 481*c2e18aaaSAndroid Build Coastguard Worker """Check if a source file is a project relative path file. 482*c2e18aaaSAndroid Build Coastguard Worker 483*c2e18aaaSAndroid Build Coastguard Worker Args: 484*c2e18aaaSAndroid Build Coastguard Worker source: Android source file path. 485*c2e18aaaSAndroid Build Coastguard Worker relative_path: Relative path of the module. 486*c2e18aaaSAndroid Build Coastguard Worker 487*c2e18aaaSAndroid Build Coastguard Worker Returns: 488*c2e18aaaSAndroid Build Coastguard Worker True if source file is a project relative path file, otherwise False. 489*c2e18aaaSAndroid Build Coastguard Worker """ 490*c2e18aaaSAndroid Build Coastguard Worker return re.search( 491*c2e18aaaSAndroid Build Coastguard Worker constant.RE_INSIDE_PATH_CHECK.format(relative_path), source) 492*c2e18aaaSAndroid Build Coastguard Worker 493*c2e18aaaSAndroid Build Coastguard Worker 494*c2e18aaaSAndroid Build Coastguard Workerdef remove_user_home_path(data): 495*c2e18aaaSAndroid Build Coastguard Worker """Replace the user home path string with a constant string. 496*c2e18aaaSAndroid Build Coastguard Worker 497*c2e18aaaSAndroid Build Coastguard Worker Args: 498*c2e18aaaSAndroid Build Coastguard Worker data: A string of xml content or an attributeError of error message. 499*c2e18aaaSAndroid Build Coastguard Worker 500*c2e18aaaSAndroid Build Coastguard Worker Returns: 501*c2e18aaaSAndroid Build Coastguard Worker A string which replaced the user home path to $USER_HOME$. 502*c2e18aaaSAndroid Build Coastguard Worker """ 503*c2e18aaaSAndroid Build Coastguard Worker return str(data).replace(os.path.expanduser('~'), constant.USER_HOME) 504*c2e18aaaSAndroid Build Coastguard Worker 505*c2e18aaaSAndroid Build Coastguard Worker 506*c2e18aaaSAndroid Build Coastguard Workerdef io_error_handle(func): 507*c2e18aaaSAndroid Build Coastguard Worker """Decorates a function of handling io error and raising exception. 508*c2e18aaaSAndroid Build Coastguard Worker 509*c2e18aaaSAndroid Build Coastguard Worker Args: 510*c2e18aaaSAndroid Build Coastguard Worker func: A function is to be raised exception if writing file failed. 511*c2e18aaaSAndroid Build Coastguard Worker 512*c2e18aaaSAndroid Build Coastguard Worker Returns: 513*c2e18aaaSAndroid Build Coastguard Worker The wrapper function. 514*c2e18aaaSAndroid Build Coastguard Worker """ 515*c2e18aaaSAndroid Build Coastguard Worker 516*c2e18aaaSAndroid Build Coastguard Worker @wraps(func) 517*c2e18aaaSAndroid Build Coastguard Worker def wrapper(*args, **kwargs): 518*c2e18aaaSAndroid Build Coastguard Worker """A wrapper function.""" 519*c2e18aaaSAndroid Build Coastguard Worker try: 520*c2e18aaaSAndroid Build Coastguard Worker return func(*args, **kwargs) 521*c2e18aaaSAndroid Build Coastguard Worker except (OSError, IOError) as err: 522*c2e18aaaSAndroid Build Coastguard Worker print('{0}.{1} I/O error: {2}'.format( 523*c2e18aaaSAndroid Build Coastguard Worker func.__module__, func.__name__, err)) 524*c2e18aaaSAndroid Build Coastguard Worker raise 525*c2e18aaaSAndroid Build Coastguard Worker return wrapper 526*c2e18aaaSAndroid Build Coastguard Worker 527*c2e18aaaSAndroid Build Coastguard Worker 528*c2e18aaaSAndroid Build Coastguard Workerdef check_args(**decls): 529*c2e18aaaSAndroid Build Coastguard Worker """Decorates a function to check its argument types. 530*c2e18aaaSAndroid Build Coastguard Worker 531*c2e18aaaSAndroid Build Coastguard Worker Usage: 532*c2e18aaaSAndroid Build Coastguard Worker @check_args(name=str, text=str) 533*c2e18aaaSAndroid Build Coastguard Worker def parse_rule(name, text): 534*c2e18aaaSAndroid Build Coastguard Worker ... 535*c2e18aaaSAndroid Build Coastguard Worker 536*c2e18aaaSAndroid Build Coastguard Worker Args: 537*c2e18aaaSAndroid Build Coastguard Worker decls: A dictionary with keys as arguments' names and values as 538*c2e18aaaSAndroid Build Coastguard Worker arguments' types. 539*c2e18aaaSAndroid Build Coastguard Worker 540*c2e18aaaSAndroid Build Coastguard Worker Returns: 541*c2e18aaaSAndroid Build Coastguard Worker The wrapper function. 542*c2e18aaaSAndroid Build Coastguard Worker """ 543*c2e18aaaSAndroid Build Coastguard Worker 544*c2e18aaaSAndroid Build Coastguard Worker def decorator(func): 545*c2e18aaaSAndroid Build Coastguard Worker """A wrapper function.""" 546*c2e18aaaSAndroid Build Coastguard Worker fmodule = func.__module__ 547*c2e18aaaSAndroid Build Coastguard Worker fname = func.__name__ 548*c2e18aaaSAndroid Build Coastguard Worker fparams = inspect.signature(func).parameters 549*c2e18aaaSAndroid Build Coastguard Worker 550*c2e18aaaSAndroid Build Coastguard Worker @wraps(func) 551*c2e18aaaSAndroid Build Coastguard Worker def decorated(*args, **kwargs): 552*c2e18aaaSAndroid Build Coastguard Worker """A wrapper function.""" 553*c2e18aaaSAndroid Build Coastguard Worker params = dict(zip(fparams, args)) 554*c2e18aaaSAndroid Build Coastguard Worker for arg_name, arg_type in decls.items(): 555*c2e18aaaSAndroid Build Coastguard Worker try: 556*c2e18aaaSAndroid Build Coastguard Worker arg_val = params[arg_name] 557*c2e18aaaSAndroid Build Coastguard Worker except KeyError: 558*c2e18aaaSAndroid Build Coastguard Worker # If arg_name can't be found in function's signature, it 559*c2e18aaaSAndroid Build Coastguard Worker # might be a case of a partial function or default 560*c2e18aaaSAndroid Build Coastguard Worker # parameters, we'll neglect it. 561*c2e18aaaSAndroid Build Coastguard Worker if arg_name not in kwargs: 562*c2e18aaaSAndroid Build Coastguard Worker continue 563*c2e18aaaSAndroid Build Coastguard Worker arg_val = kwargs.get(arg_name) 564*c2e18aaaSAndroid Build Coastguard Worker if arg_val is None: 565*c2e18aaaSAndroid Build Coastguard Worker raise TypeError(_ARG_IS_NULL_ERROR.format( 566*c2e18aaaSAndroid Build Coastguard Worker fmodule, fname, arg_name)) 567*c2e18aaaSAndroid Build Coastguard Worker if not isinstance(arg_val, arg_type): 568*c2e18aaaSAndroid Build Coastguard Worker raise TypeError(_ARG_TYPE_INCORRECT_ERROR.format( 569*c2e18aaaSAndroid Build Coastguard Worker fmodule, fname, arg_name, type(arg_val), arg_type)) 570*c2e18aaaSAndroid Build Coastguard Worker return func(*args, **kwargs) 571*c2e18aaaSAndroid Build Coastguard Worker return decorated 572*c2e18aaaSAndroid Build Coastguard Worker 573*c2e18aaaSAndroid Build Coastguard Worker return decorator 574*c2e18aaaSAndroid Build Coastguard Worker 575*c2e18aaaSAndroid Build Coastguard Worker 576*c2e18aaaSAndroid Build Coastguard Worker@io_error_handle 577*c2e18aaaSAndroid Build Coastguard Workerdef dump_json_dict(json_path, data): 578*c2e18aaaSAndroid Build Coastguard Worker """Dumps a dictionary of data into a json file. 579*c2e18aaaSAndroid Build Coastguard Worker 580*c2e18aaaSAndroid Build Coastguard Worker Args: 581*c2e18aaaSAndroid Build Coastguard Worker json_path: An absolute json file path string. 582*c2e18aaaSAndroid Build Coastguard Worker data: A dictionary of data to be written into a json file. 583*c2e18aaaSAndroid Build Coastguard Worker """ 584*c2e18aaaSAndroid Build Coastguard Worker with open(json_path, 'w', encoding='utf-8') as json_file: 585*c2e18aaaSAndroid Build Coastguard Worker json.dump(data, json_file, indent=4) 586*c2e18aaaSAndroid Build Coastguard Worker 587*c2e18aaaSAndroid Build Coastguard Worker 588*c2e18aaaSAndroid Build Coastguard Worker@io_error_handle 589*c2e18aaaSAndroid Build Coastguard Workerdef get_json_dict(json_path): 590*c2e18aaaSAndroid Build Coastguard Worker """Loads a json file from path and convert it into a json dictionary. 591*c2e18aaaSAndroid Build Coastguard Worker 592*c2e18aaaSAndroid Build Coastguard Worker Args: 593*c2e18aaaSAndroid Build Coastguard Worker json_path: An absolute json file path string. 594*c2e18aaaSAndroid Build Coastguard Worker 595*c2e18aaaSAndroid Build Coastguard Worker Returns: 596*c2e18aaaSAndroid Build Coastguard Worker A dictionary loaded from the json_path. 597*c2e18aaaSAndroid Build Coastguard Worker """ 598*c2e18aaaSAndroid Build Coastguard Worker with open(json_path, 'r', encoding='utf-8') as jfile: 599*c2e18aaaSAndroid Build Coastguard Worker return json.load(jfile) 600*c2e18aaaSAndroid Build Coastguard Worker 601*c2e18aaaSAndroid Build Coastguard Worker 602*c2e18aaaSAndroid Build Coastguard Worker@io_error_handle 603*c2e18aaaSAndroid Build Coastguard Workerdef read_file_line_to_list(file_path): 604*c2e18aaaSAndroid Build Coastguard Worker """Read a file line by line and write them into a list. 605*c2e18aaaSAndroid Build Coastguard Worker 606*c2e18aaaSAndroid Build Coastguard Worker Args: 607*c2e18aaaSAndroid Build Coastguard Worker file_path: A string of a file's path. 608*c2e18aaaSAndroid Build Coastguard Worker 609*c2e18aaaSAndroid Build Coastguard Worker Returns: 610*c2e18aaaSAndroid Build Coastguard Worker A list of the file's content by line. 611*c2e18aaaSAndroid Build Coastguard Worker """ 612*c2e18aaaSAndroid Build Coastguard Worker files = [] 613*c2e18aaaSAndroid Build Coastguard Worker with open(file_path, 'r', encoding='utf8') as infile: 614*c2e18aaaSAndroid Build Coastguard Worker for line in infile: 615*c2e18aaaSAndroid Build Coastguard Worker files.append(line.strip()) 616*c2e18aaaSAndroid Build Coastguard Worker return files 617*c2e18aaaSAndroid Build Coastguard Worker 618*c2e18aaaSAndroid Build Coastguard Worker 619*c2e18aaaSAndroid Build Coastguard Worker@io_error_handle 620*c2e18aaaSAndroid Build Coastguard Workerdef read_file_content(path, encode_type='utf8'): 621*c2e18aaaSAndroid Build Coastguard Worker """Read file's content. 622*c2e18aaaSAndroid Build Coastguard Worker 623*c2e18aaaSAndroid Build Coastguard Worker Args: 624*c2e18aaaSAndroid Build Coastguard Worker path: Path of input file. 625*c2e18aaaSAndroid Build Coastguard Worker encode_type: A string of encoding name, default to UTF-8. 626*c2e18aaaSAndroid Build Coastguard Worker 627*c2e18aaaSAndroid Build Coastguard Worker Returns: 628*c2e18aaaSAndroid Build Coastguard Worker String: Content of the file. 629*c2e18aaaSAndroid Build Coastguard Worker """ 630*c2e18aaaSAndroid Build Coastguard Worker with open(path, 'r', encoding=encode_type) as template: 631*c2e18aaaSAndroid Build Coastguard Worker return template.read() 632*c2e18aaaSAndroid Build Coastguard Worker 633*c2e18aaaSAndroid Build Coastguard Worker 634*c2e18aaaSAndroid Build Coastguard Worker@io_error_handle 635*c2e18aaaSAndroid Build Coastguard Workerdef file_generate(path, content): 636*c2e18aaaSAndroid Build Coastguard Worker """Generate file from content. 637*c2e18aaaSAndroid Build Coastguard Worker 638*c2e18aaaSAndroid Build Coastguard Worker Args: 639*c2e18aaaSAndroid Build Coastguard Worker path: Path of target file. 640*c2e18aaaSAndroid Build Coastguard Worker content: String content of file. 641*c2e18aaaSAndroid Build Coastguard Worker """ 642*c2e18aaaSAndroid Build Coastguard Worker if not os.path.exists(os.path.dirname(path)): 643*c2e18aaaSAndroid Build Coastguard Worker os.makedirs(os.path.dirname(path)) 644*c2e18aaaSAndroid Build Coastguard Worker with open(path, 'w', encoding='utf-8') as target: 645*c2e18aaaSAndroid Build Coastguard Worker target.write(content) 646*c2e18aaaSAndroid Build Coastguard Worker 647*c2e18aaaSAndroid Build Coastguard Worker 648*c2e18aaaSAndroid Build Coastguard Workerdef get_lunch_target(): 649*c2e18aaaSAndroid Build Coastguard Worker """Gets the Android lunch target in current console. 650*c2e18aaaSAndroid Build Coastguard Worker 651*c2e18aaaSAndroid Build Coastguard Worker Returns: 652*c2e18aaaSAndroid Build Coastguard Worker A json format string of lunch target in current console. 653*c2e18aaaSAndroid Build Coastguard Worker """ 654*c2e18aaaSAndroid Build Coastguard Worker product = os.environ.get(constant.TARGET_PRODUCT) 655*c2e18aaaSAndroid Build Coastguard Worker build_variant = os.environ.get(constant.TARGET_BUILD_VARIANT) 656*c2e18aaaSAndroid Build Coastguard Worker if product and build_variant: 657*c2e18aaaSAndroid Build Coastguard Worker return json.dumps( 658*c2e18aaaSAndroid Build Coastguard Worker {constant.LUNCH_TARGET: "-".join([product, build_variant])}) 659*c2e18aaaSAndroid Build Coastguard Worker return None 660*c2e18aaaSAndroid Build Coastguard Worker 661*c2e18aaaSAndroid Build Coastguard Worker 662*c2e18aaaSAndroid Build Coastguard Workerdef get_blueprint_json_files_relative_dict(): 663*c2e18aaaSAndroid Build Coastguard Worker """Gets a dictionary with key: environment variable, value: absolute path. 664*c2e18aaaSAndroid Build Coastguard Worker 665*c2e18aaaSAndroid Build Coastguard Worker Returns: 666*c2e18aaaSAndroid Build Coastguard Worker A dictionary with key: environment variable and value: absolute path of 667*c2e18aaaSAndroid Build Coastguard Worker the file generated by the environment variable. 668*c2e18aaaSAndroid Build Coastguard Worker """ 669*c2e18aaaSAndroid Build Coastguard Worker data = {} 670*c2e18aaaSAndroid Build Coastguard Worker root_dir = get_android_root_dir() 671*c2e18aaaSAndroid Build Coastguard Worker bp_java_path = os.path.join( 672*c2e18aaaSAndroid Build Coastguard Worker root_dir, get_blueprint_json_path( 673*c2e18aaaSAndroid Build Coastguard Worker constant.BLUEPRINT_JAVA_JSONFILE_NAME)) 674*c2e18aaaSAndroid Build Coastguard Worker data[constant.GEN_JAVA_DEPS] = bp_java_path 675*c2e18aaaSAndroid Build Coastguard Worker bp_cc_path = os.path.join( 676*c2e18aaaSAndroid Build Coastguard Worker root_dir, get_blueprint_json_path(constant.BLUEPRINT_CC_JSONFILE_NAME)) 677*c2e18aaaSAndroid Build Coastguard Worker data[constant.GEN_CC_DEPS] = bp_cc_path 678*c2e18aaaSAndroid Build Coastguard Worker data[constant.GEN_COMPDB] = os.path.join(get_soong_out_path(), 679*c2e18aaaSAndroid Build Coastguard Worker constant.RELATIVE_COMPDB_PATH, 680*c2e18aaaSAndroid Build Coastguard Worker constant.COMPDB_JSONFILE_NAME) 681*c2e18aaaSAndroid Build Coastguard Worker data[constant.GEN_RUST] = os.path.join( 682*c2e18aaaSAndroid Build Coastguard Worker root_dir, get_blueprint_json_path(constant.RUST_PROJECT_JSON)) 683*c2e18aaaSAndroid Build Coastguard Worker return data 684*c2e18aaaSAndroid Build Coastguard Worker 685*c2e18aaaSAndroid Build Coastguard Worker 686*c2e18aaaSAndroid Build Coastguard Workerdef to_pretty_xml(root, indent=" "): 687*c2e18aaaSAndroid Build Coastguard Worker """Gets pretty xml from an xml.etree.ElementTree root. 688*c2e18aaaSAndroid Build Coastguard Worker 689*c2e18aaaSAndroid Build Coastguard Worker Args: 690*c2e18aaaSAndroid Build Coastguard Worker root: An element tree root. 691*c2e18aaaSAndroid Build Coastguard Worker indent: The indent of XML. 692*c2e18aaaSAndroid Build Coastguard Worker Returns: 693*c2e18aaaSAndroid Build Coastguard Worker A string of pretty xml. 694*c2e18aaaSAndroid Build Coastguard Worker """ 695*c2e18aaaSAndroid Build Coastguard Worker xml_string = xml.dom.minidom.parseString( 696*c2e18aaaSAndroid Build Coastguard Worker ElementTree.tostring(root)).toprettyxml(indent) 697*c2e18aaaSAndroid Build Coastguard Worker # Remove the xml declaration since IntelliJ doesn't use it. 698*c2e18aaaSAndroid Build Coastguard Worker xml_string = xml_string.split("\n", 1)[1] 699*c2e18aaaSAndroid Build Coastguard Worker # Remove the weird newline issue from toprettyxml. 700*c2e18aaaSAndroid Build Coastguard Worker return os.linesep.join([s for s in xml_string.splitlines() if s.strip()]) 701*c2e18aaaSAndroid Build Coastguard Worker 702*c2e18aaaSAndroid Build Coastguard Worker 703*c2e18aaaSAndroid Build Coastguard Workerdef to_boolean(str_bool): 704*c2e18aaaSAndroid Build Coastguard Worker """Converts a string to a boolean. 705*c2e18aaaSAndroid Build Coastguard Worker 706*c2e18aaaSAndroid Build Coastguard Worker Args: 707*c2e18aaaSAndroid Build Coastguard Worker str_bool: A string in the expression of boolean type. 708*c2e18aaaSAndroid Build Coastguard Worker 709*c2e18aaaSAndroid Build Coastguard Worker Returns: 710*c2e18aaaSAndroid Build Coastguard Worker A boolean True if the string is one of ('True', 'true', 'T', 't', '1') 711*c2e18aaaSAndroid Build Coastguard Worker else False. 712*c2e18aaaSAndroid Build Coastguard Worker """ 713*c2e18aaaSAndroid Build Coastguard Worker return str_bool and str_bool.lower() in ('true', 't', '1') 714*c2e18aaaSAndroid Build Coastguard Worker 715*c2e18aaaSAndroid Build Coastguard Worker 716*c2e18aaaSAndroid Build Coastguard Workerdef find_git_root(relpath): 717*c2e18aaaSAndroid Build Coastguard Worker """Finds the parent directory which has a .git folder from the relpath. 718*c2e18aaaSAndroid Build Coastguard Worker 719*c2e18aaaSAndroid Build Coastguard Worker Args: 720*c2e18aaaSAndroid Build Coastguard Worker relpath: A string of relative path. 721*c2e18aaaSAndroid Build Coastguard Worker 722*c2e18aaaSAndroid Build Coastguard Worker Returns: 723*c2e18aaaSAndroid Build Coastguard Worker A string of the absolute path which contains a .git, otherwise, none. 724*c2e18aaaSAndroid Build Coastguard Worker """ 725*c2e18aaaSAndroid Build Coastguard Worker dir_list = relpath.split(os.sep) 726*c2e18aaaSAndroid Build Coastguard Worker for i in range(len(dir_list), 0, -1): 727*c2e18aaaSAndroid Build Coastguard Worker real_path = os.path.join(get_android_root_dir(), 728*c2e18aaaSAndroid Build Coastguard Worker os.sep.join(dir_list[:i]), 729*c2e18aaaSAndroid Build Coastguard Worker constant.GIT_FOLDER_NAME) 730*c2e18aaaSAndroid Build Coastguard Worker if os.path.exists(real_path): 731*c2e18aaaSAndroid Build Coastguard Worker return os.path.dirname(real_path) 732*c2e18aaaSAndroid Build Coastguard Worker logging.warning('%s can\'t find its .git folder.', relpath) 733*c2e18aaaSAndroid Build Coastguard Worker return None 734*c2e18aaaSAndroid Build Coastguard Worker 735*c2e18aaaSAndroid Build Coastguard Worker 736*c2e18aaaSAndroid Build Coastguard Workerdef determine_language_ide(lang, ide, jlist=None, clist=None, rlist=None): 737*c2e18aaaSAndroid Build Coastguard Worker """Determines the language and IDE by the input language and IDE arguments. 738*c2e18aaaSAndroid Build Coastguard Worker 739*c2e18aaaSAndroid Build Coastguard Worker If IDE and language are undefined, the priority of the language is: 740*c2e18aaaSAndroid Build Coastguard Worker 1. Java 741*c2e18aaaSAndroid Build Coastguard Worker 2. C/C++ 742*c2e18aaaSAndroid Build Coastguard Worker 3. Rust 743*c2e18aaaSAndroid Build Coastguard Worker 744*c2e18aaaSAndroid Build Coastguard Worker Args: 745*c2e18aaaSAndroid Build Coastguard Worker lang: A character represents the input language. 746*c2e18aaaSAndroid Build Coastguard Worker ide: A character represents the input IDE. 747*c2e18aaaSAndroid Build Coastguard Worker jlist: A list of Android Java projects, the default value is None. 748*c2e18aaaSAndroid Build Coastguard Worker clist: A list of Android C/C++ projects, the default value is None. 749*c2e18aaaSAndroid Build Coastguard Worker rlist: A list of Android Rust projects, the default value is None. 750*c2e18aaaSAndroid Build Coastguard Worker 751*c2e18aaaSAndroid Build Coastguard Worker Returns: 752*c2e18aaaSAndroid Build Coastguard Worker A tuple of the determined language and IDE name strings. 753*c2e18aaaSAndroid Build Coastguard Worker """ 754*c2e18aaaSAndroid Build Coastguard Worker if ide == _IDE_UNDEFINED and lang == constant.LANG_UNDEFINED: 755*c2e18aaaSAndroid Build Coastguard Worker if jlist: 756*c2e18aaaSAndroid Build Coastguard Worker lang = constant.LANG_JAVA 757*c2e18aaaSAndroid Build Coastguard Worker elif clist: 758*c2e18aaaSAndroid Build Coastguard Worker lang = constant.LANG_CC 759*c2e18aaaSAndroid Build Coastguard Worker elif rlist: 760*c2e18aaaSAndroid Build Coastguard Worker lang = constant.LANG_RUST 761*c2e18aaaSAndroid Build Coastguard Worker if lang in (constant.LANG_UNDEFINED, constant.LANG_JAVA): 762*c2e18aaaSAndroid Build Coastguard Worker if ide == _IDE_UNDEFINED: 763*c2e18aaaSAndroid Build Coastguard Worker ide = _IDE_INTELLIJ 764*c2e18aaaSAndroid Build Coastguard Worker lang = constant.LANG_JAVA 765*c2e18aaaSAndroid Build Coastguard Worker if constant.IDE_NAME_DICT[ide] == constant.IDE_CLION: 766*c2e18aaaSAndroid Build Coastguard Worker lang = constant.LANG_CC 767*c2e18aaaSAndroid Build Coastguard Worker elif lang == constant.LANG_CC: 768*c2e18aaaSAndroid Build Coastguard Worker if ide == _IDE_UNDEFINED: 769*c2e18aaaSAndroid Build Coastguard Worker ide = _IDE_CLION 770*c2e18aaaSAndroid Build Coastguard Worker if constant.IDE_NAME_DICT[ide] == constant.IDE_INTELLIJ: 771*c2e18aaaSAndroid Build Coastguard Worker lang = constant.LANG_JAVA 772*c2e18aaaSAndroid Build Coastguard Worker elif lang == constant.LANG_RUST: 773*c2e18aaaSAndroid Build Coastguard Worker ide = _IDE_VSCODE 774*c2e18aaaSAndroid Build Coastguard Worker return constant.LANGUAGE_NAME_DICT[lang], constant.IDE_NAME_DICT[ide] 775*c2e18aaaSAndroid Build Coastguard Worker 776*c2e18aaaSAndroid Build Coastguard Worker 777*c2e18aaaSAndroid Build Coastguard Workerdef check_java_or_kotlin_file_exists(abs_path): 778*c2e18aaaSAndroid Build Coastguard Worker """Checks if any Java or Kotlin files exist in an abs_path directory. 779*c2e18aaaSAndroid Build Coastguard Worker 780*c2e18aaaSAndroid Build Coastguard Worker Args: 781*c2e18aaaSAndroid Build Coastguard Worker abs_path: A string of absolute path of a directory to be checked. 782*c2e18aaaSAndroid Build Coastguard Worker 783*c2e18aaaSAndroid Build Coastguard Worker Returns: 784*c2e18aaaSAndroid Build Coastguard Worker True if any Java or Kotlin files exist otherwise False. 785*c2e18aaaSAndroid Build Coastguard Worker """ 786*c2e18aaaSAndroid Build Coastguard Worker for _, _, filenames in os.walk(abs_path): 787*c2e18aaaSAndroid Build Coastguard Worker for extension in (constant.JAVA_FILES, constant.KOTLIN_FILES): 788*c2e18aaaSAndroid Build Coastguard Worker if fnmatch.filter(filenames, extension): 789*c2e18aaaSAndroid Build Coastguard Worker return True 790*c2e18aaaSAndroid Build Coastguard Worker return False 791*c2e18aaaSAndroid Build Coastguard Worker 792*c2e18aaaSAndroid Build Coastguard Worker 793*c2e18aaaSAndroid Build Coastguard Worker@io_error_handle 794*c2e18aaaSAndroid Build Coastguard Workerdef unzip_file(src, dest): 795*c2e18aaaSAndroid Build Coastguard Worker """Unzips the source zip file and extract it to the destination directory. 796*c2e18aaaSAndroid Build Coastguard Worker 797*c2e18aaaSAndroid Build Coastguard Worker Args: 798*c2e18aaaSAndroid Build Coastguard Worker src: A string of the file to be unzipped. 799*c2e18aaaSAndroid Build Coastguard Worker dest: A string of the destination directory to be extracted to. 800*c2e18aaaSAndroid Build Coastguard Worker """ 801*c2e18aaaSAndroid Build Coastguard Worker with zipfile.ZipFile(src, 'r') as zip_ref: 802*c2e18aaaSAndroid Build Coastguard Worker zip_ref.extractall(dest) 803