1#!/usr/bin/env python3 2# 3# Copyright 2019, 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 17"""Module Info class used to hold cached merged_module_info.json.""" 18 19import json 20import logging 21import os 22 23from pathlib import Path 24 25from atest import constants 26from atest import module_info 27 28from aidegen import constant 29from aidegen.lib import common_util 30from aidegen.lib import module_info_util 31from aidegen.lib.singleton import Singleton 32 33 34class AidegenModuleInfo(module_info.ModuleInfo, metaclass=Singleton): 35 """Class that offers fast/easy lookup for Module related details.""" 36 37 38 def _load_module_info_file(self, module_file): 39 """Loads the module file. 40 41 Args: 42 module_file: String of path to file to load up. Used for testing. 43 44 Returns: 45 Tuple of module_info_target and a json object. 46 """ 47 # If module_file is specified, we're testing so we don't care if 48 # module_info_target stays None. 49 module_info_target = None 50 file_path = module_file 51 52 if not file_path: 53 module_info_target, file_path = self._discover_mod_file_and_target( 54 self.force_build) 55 self.mod_info_file_path = Path(file_path) 56 57 logging.debug('Loading %s as module-info.', file_path) 58 with open(file_path, encoding='utf8') as json_file: 59 mod_info = json.load(json_file) 60 61 return module_info_target, mod_info 62 63 @staticmethod 64 def _discover_mod_file_and_target(force_build): 65 """Find the module file. 66 67 If force_build is True, we'll remove module_bp_java_deps.json first and 68 let module_info_util.generate_merged_module_info regenerate it again. 69 70 Args: 71 force_build: Boolean to indicate if we should rebuild the 72 module_info file regardless if it's created or not. 73 74 Returns: 75 Tuple of the relative and absolute paths of the merged module info 76 file. 77 """ 78 module_file_path = common_util.get_blueprint_json_path( 79 constant.BLUEPRINT_JAVA_JSONFILE_NAME) 80 if force_build and os.path.isfile(module_file_path): 81 os.remove(module_file_path) 82 merged_file_path = os.path.join(common_util.get_soong_out_path(), 83 constant.MERGED_MODULE_INFO) 84 if not os.path.isfile(merged_file_path): 85 logging.debug( 86 'Generating %s - this is required for the initial runs.', 87 merged_file_path) 88 data = module_info_util.generate_merged_module_info() 89 common_util.dump_json_dict(merged_file_path, data) 90 merged_file_rel_path = os.path.relpath( 91 merged_file_path, common_util.get_android_root_dir()) 92 return merged_file_rel_path, merged_file_path 93 94 @staticmethod 95 def is_target_module(mod_info): 96 """Determine if the module is a target module. 97 98 Determine if a module's class is in TARGET_CLASSES. 99 100 Args: 101 mod_info: A module's module-info dictionary to be checked. 102 103 Returns: 104 A boolean, true if it is a target module, otherwise false. 105 """ 106 if mod_info: 107 return any( 108 x in mod_info.get(constants.MODULE_CLASS, []) 109 for x in constant.TARGET_CLASSES) 110 return False 111 112 @staticmethod 113 def is_project_path_relative_module(mod_info, rel_path): 114 """Determine if the given project path is relative to the module. 115 116 The rules: 117 1. If constant.KEY_PATH not in mod_info, we can't tell if it's a 118 module return False. 119 2. If rel_path is empty, it's under Android root, return True. 120 3. If module's path equals or starts with rel_path return True, 121 otherwise return False. 122 123 Args: 124 mod_info: the module-info dictionary of the checked module. 125 rel_path: project's relative path 126 127 Returns: 128 True if it's the given project path is relative to the module, 129 otherwise False. 130 """ 131 if (constant.KEY_PATH not in mod_info 132 or not mod_info[constant.KEY_PATH]): 133 return False 134 path = mod_info[constant.KEY_PATH][0] 135 if rel_path == '': 136 return True 137 if (constant.KEY_CLASS in mod_info 138 and common_util.is_source_under_relative_path(path, rel_path)): 139 return True 140 return False 141